excalidraw-skill
Original:🇺🇸 English
Translated
7 scripts
Programmatic canvas toolkit for creating, editing, and refining Excalidraw diagrams via MCP tools with real-time canvas sync. Use when an agent needs to (1) draw or lay out diagrams on a live canvas, (2) iteratively refine diagrams using describe_scene and get_canvas_screenshot to see its own work, (3) export/import .excalidraw files or PNG/SVG images, (4) save/restore canvas snapshots, (5) convert Mermaid to Excalidraw, or (6) perform element-level CRUD, alignment, distribution, grouping, duplication, and locking. Requires a running canvas server (EXPRESS_SERVER_URL, default http://localhost:3000).
10installs
Sourcelingzhi227/claude-skills
Added on
NPX Install
npx skill4agent add lingzhi227/claude-skills excalidraw-skillTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Excalidraw Skill
Step 0: Detect Connection Mode
Before doing anything, determine which mode is available. Run these checks in order:
Check 1: MCP Server (Best experience)
bash
mcp-cli tools | grep excalidrawIf you see tools like → use MCP mode. Call MCP tools directly.
excalidraw/batch_create_elementsCheck 2: REST API (Fallback — works without MCP server)
bash
curl -s http://localhost:3000/healthIf you get → use REST API mode. Use HTTP endpoints ( / ) from the cheatsheet.
{"status":"ok"}curlfetchCheck 3: Nothing works → Guide user to install
If neither works, tell the user:
The Excalidraw canvas server is not running. To set up:
- Clone:
git clone https://github.com/yctimlin/mcp_excalidraw && cd mcp_excalidraw- Build:
npm ci && npm run build- Start canvas:
HOST=0.0.0.0 PORT=3000 npm run canvas- Open
in a browserhttp://localhost:3000- (Recommended) Install the MCP server for the best experience:
claude mcp add excalidraw -s user -e EXPRESS_SERVER_URL=http://localhost:3000 -- node /path/to/mcp_excalidraw/dist/index.js
MCP vs REST API Quick Reference
| Operation | MCP Tool | REST API Equivalent |
|---|---|---|
| Create elements | | |
| Get all elements | | |
| Get one element | | |
| Update element | | |
| Delete element | | |
| Clear canvas | | |
| Describe scene | | |
| Export scene | | |
| Import scene | | |
| Snapshot | | |
| Restore snapshot | | |
| Screenshot | | Only via MCP (needs browser) |
| Design guide | | Not available — see cheatsheet for guidelines |
| Viewport | | |
| Export image | | |
| Export URL | | Only via MCP |
REST API Gotchas (Critical — read before using REST API)
- Labels: Use (not
"label": {"text": "My Label"}). MCP tools auto-convert, REST API does not."text": "My Label" - Arrow binding: Use (not
"start": {"id": "svc-a"}, "end": {"id": "svc-b"}/"startElementId"). MCP tools accept"endElementId"and convert, REST API requires thestartElementId/startobject format directly.end - fontFamily: Must be a string (e.g. ) or omit it entirely. Do NOT pass a number like
"1".1 - Updating labels: When updating a shape via , include the full
PUT /api/elements/:idin the update body to preserve it. Omittinglabelfrom the update won't delete it, but re-sending ensures it renders correctly.label - Screenshot in REST mode: returns
POST /api/export/image. Save to file and read it back for visual verification. Requires browser open.{"data": "<base64>"}
Quality Gate (MANDATORY — read before creating any diagram)
After EVERY iteration (each batch of elements added), you MUST run a quality check before proceeding. NEVER say "looks great" unless ALL checks pass.
Quality Checklist — verify ALL before adding more elements:
- Text truncation: Is ALL text fully visible? Labels must fit inside their shapes. If text is cut off or wrapping badly → increase and/or
width.height - Overlap: Do ANY elements overlap each other? Check that no rectangles, ellipses, or text elements share the same space. Background zones must fully contain their children with padding.
- Arrow crossing: Do arrows cross through unrelated elements or overlap with text labels? If yes → use curved/elbowed arrows with waypoints to route around obstacles (see "Arrow Routing" section). Never accept crossing arrows.
- Arrow-text overlap: Do any arrow labels ("charge", "event", etc.) overlap with shapes? Arrow labels are positioned at the midpoint — if they overlap, either remove the label, shorten it, or adjust the arrow path.
- Spacing: Is there at least 40px gap between elements? Cramped layouts are unreadable.
- Readability: Can all labels be read at normal zoom? Font size >= 16 for body text, >= 20 for titles.
If ANY issue is found:
- STOP adding new elements
- Fix the issue first (resize, reposition, delete and recreate)
- Re-verify with a new screenshot
- Only proceed to next iteration after ALL checks pass
Sizing Rules (prevent truncation):
- Shape width: pixels. For multi-word labels like "API Gateway (Kong)", count all characters.
max(160, labelTextLength * 9) - Shape height: 60px for single line, 80px for 2 lines, 100px for 3 lines.
- Background zones: Add 50px padding on ALL sides around contained elements.
- Element spacing: 60px vertical between tiers, 40px horizontal between siblings.
- Side panels: Place at least 80px away from main diagram elements.
- Arrow labels: Keep labels short (1-2 words). Long arrow labels overlap with other elements.
Layout Planning (prevent overlap):
Before creating elements, plan your coordinate grid on paper first:
- Tier 1 (y=50-130): Client apps
- Tier 2 (y=200-280): Gateway/Edge
- Tier 3 (y=350-440): Services (spread wide: each service ~180px apart)
- Tier 4 (y=510-590): Data stores
- Side panels: x < 0 (left) or x > mainDiagramRight + 80 (right)
Do NOT place side panels (observability, external APIs) at the same x-range as the main diagram — they WILL overlap.
Quick Start
- Run Step 0 above to detect your connection mode.
- Open the canvas URL in a browser (required for image export/screenshot).
- MCP mode: Use MCP tools for all operations. REST mode: Use HTTP endpoints from cheatsheet.
- For full tool/endpoint reference, read .
references/cheatsheet.md
Workflow: Draw A Diagram
MCP Mode
- Call first to load design best practices.
read_diagram_guide - Plan your coordinate grid (see Quality Gate → Layout Planning) before writing any JSON.
- Optional: to start fresh.
clear_canvas - Use with shapes AND arrows in one call.
batch_create_elements - Assign custom to shapes (e.g.
id). Set"id": "auth-svc"field to label shapes.text - Size shapes for their text — use .
width: max(160, textLength * 9) - Bind arrows using /
startElementId— arrows auto-route.endElementId - with
set_viewportto auto-fit the diagram.scrollToContent: true - Run Quality Checklist — and critically evaluate. Fix issues before proceeding.
get_canvas_screenshot
REST API Mode
- Read for design guidelines.
references/cheatsheet.md - Plan your coordinate grid (see Quality Gate → Layout Planning) before writing any JSON.
- Optional:
curl -X DELETE http://localhost:3000/api/elements/clear - Create elements in one call (use for large payloads):
@file.jsonbashcurl -X POST http://localhost:3000/api/elements/batch \ -H "Content-Type: application/json" \ -d '{"elements": [ {"id": "svc-a", "type": "rectangle", "x": 0, "y": 0, "width": 160, "height": 60, "label": {"text": "Service A"}}, {"id": "svc-b", "type": "rectangle", "x": 0, "y": 200, "width": 160, "height": 60, "label": {"text": "Service B"}}, {"type": "arrow", "x": 0, "y": 0, "start": {"id": "svc-a"}, "end": {"id": "svc-b"}} ]}' - Use for shape labels (not
"label": {"text": "..."})."text": "..." - Bind arrows with /
"start": {"id": "..."}— server auto-routes edges."end": {"id": "..."} - Size shapes for their text — use .
width: max(160, labelTextLength * 9) - Run Quality Checklist — take screenshot, critically evaluate. Fix issues before adding more elements.
Arrow Binding (Recommended)
Bind arrows to shapes for auto-routed edges. The format differs between MCP and REST API:
MCP Mode — use / :
startElementIdendElementIdjson
{"elements": [
{"id": "svc-a", "type": "rectangle", "x": 0, "y": 0, "width": 120, "height": 60, "text": "Service A"},
{"id": "svc-b", "type": "rectangle", "x": 0, "y": 200, "width": 120, "height": 60, "text": "Service B"},
{"type": "arrow", "x": 0, "y": 0, "startElementId": "svc-a", "endElementId": "svc-b", "text": "calls"}
]}REST API Mode — use / and :
start: {id}end: {id}label: {text}json
{"elements": [
{"id": "svc-a", "type": "rectangle", "x": 0, "y": 0, "width": 120, "height": 60, "label": {"text": "Service A"}},
{"id": "svc-b", "type": "rectangle", "x": 0, "y": 200, "width": 120, "height": 60, "label": {"text": "Service B"}},
{"type": "arrow", "x": 0, "y": 0, "start": {"id": "svc-a"}, "end": {"id": "svc-b"}, "label": {"text": "calls"}}
]}Arrows without binding use manual , , coordinates.
xypointsArrow Routing — Avoid Overlaps (Critical for complex diagrams)
Straight arrows (2-point) cause crossing and overlap in complex diagrams. Use curved or elbowed arrows instead:
Option 1: Curved arrows — add intermediate waypoints + :
roundnessjson
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [50, -40], [200, 0]],
"roundness": {"type": 2},
"strokeColor": "#1971c2"
}The waypoint pushes the arrow upward to arc over elements. makes it a smooth curve.
[50, -40]roundness: {type: 2}Option 2: Elbowed arrows — right-angle routing (L-shaped or Z-shaped):
json
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [0, -50], [200, -50], [200, 0]],
"elbowed": true,
"strokeColor": "#1971c2"
}When to use which:
- Fan-out arrows (one source → many targets): Use curved arrows with waypoints spread vertically to avoid overlapping each other.
- Cross-lane arrows (connecting to side panels): Use elbowed arrows that route around the main diagram — go UP first, then ACROSS, then DOWN.
- Inter-service arrows (horizontal connections): Use curved arrows with a slight vertical offset to avoid crossing through adjacent elements.
Rule of thumb: If an arrow would cross through an unrelated element, add a waypoint to route around it. Never accept crossing arrows — always fix them.
Workflow: Iterative Refinement (Key Differentiator)
The feedback loop that makes this skill unique. Each iteration MUST include a quality check.
MCP Mode (full feedback loop)
- Add elements (,
batch_create_elements).create_element - with
set_viewport.scrollToContent: true - — critically evaluate against the Quality Checklist.
get_canvas_screenshot - If issues found → fix them (,
update_element, resize, reposition).delete_element - again — re-verify fix.
get_canvas_screenshot - Only proceed to next iteration when ALL quality checks pass.
REST API Mode (partial feedback loop)
- Add elements via .
POST /api/elements/batch - with
POST /api/viewport.{"scrollToContent": true} - Take screenshot: → save PNG → critically evaluate against Quality Checklist.
POST /api/export/image - If issues found → fix via or delete and recreate.
PUT /api/elements/:id - Re-screenshot and re-verify.
- Only proceed to next iteration when ALL quality checks pass.
How to critically evaluate a screenshot:
- Look at EVERY label — is any text cut off or overflowing its container?
- Look at EVERY arrow — does any arrow pass through an unrelated element?
- Look at ALL element pairs — do any overlap or touch?
- Look at spacing — is anything crammed together?
- Be honest. If you see ANY issue, say "I see [issue], fixing it" — not "looks great".
Example flow (MCP):
batch_create_elements → get_canvas_screenshot → "text truncated on 2 shapes"
→ update_element (increase widths) → get_canvas_screenshot → "overlap between X and Y"
→ update_element (reposition) → get_canvas_screenshot → "all checks pass"
→ proceed to next iterationWorkflow: Refine An Existing Diagram
- to understand current state.
describe_scene - Identify targets by id, type, or label text (not x/y coordinates).
- to move/resize/recolor,
update_elementto remove.delete_element - to verify changes visually.
get_canvas_screenshot - If updates fail: check element id exists (), element isn't locked (
get_element).unlock_elements
Workflow: File I/O (Diagrams-as-Code)
- Export to .excalidraw format: with optional
export_scene.filePath - Import from .excalidraw: with
import_sceneormode: "replace"."merge" - Export to image: with
export_to_imageorformat: "png"(requires browser open)."svg" - CLI export:
node scripts/export-elements.cjs --out diagram.elements.json - CLI import:
node scripts/import-elements.cjs --in diagram.elements.json --mode batch|sync
Workflow: Snapshots (Save/Restore Canvas State)
- with a name before risky changes.
snapshot_scene - Make changes, /
describe_sceneto evaluate.get_canvas_screenshot - to rollback if needed.
restore_snapshot
Workflow: Duplication
- with
duplicate_elementsand optionalelementIds/offsetX(default 20,20).offsetY - Useful for creating repeated patterns or copying existing layouts.
Points Format for Arrows/Lines
The field accepts both formats:
points- Tuple:
[[0, 0], [100, 50]] - Object:
[{"x": 0, "y": 0}, {"x": 100, "y": 50}]
Both are normalized to tuples automatically.
Workflow: Share Diagram (excalidraw.com URL)
- Create your diagram using any of the above workflows.
- — uploads encrypted scene, returns a shareable URL.
export_to_excalidraw_url - Share the URL — anyone can open it in excalidraw.com to view and edit.
Workflow: Viewport Control
- with
set_viewport— auto-fit all elements (zoom-to-fit).scrollToContent: true - with
set_viewport— center view on a specific element.scrollToElementId: "my-element" - with
set_viewport— manual camera control.zoom: 1.5, offsetX: 100, offsetY: 200
References
- : Complete MCP tool list (26 tools) + REST API endpoints + payload shapes.
references/cheatsheet.md
Related Skills
- See also: figure-generation, algorithm-design, slide-generation