Excalidraw Skill
Excalidraw canvas toolkit for creating, editing, and refining diagrams on a live canvas. Use when an agent needs to (1) draw or lay out diagrams, (2) iteratively refine them by describing the scene and screenshotting 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. Primary interface is the bundled CLI (npx -y mcp-excalidraw-server <command>) which auto-starts the canvas server; MCP tools and a REST API are equivalent alternatives.
- Skill ID
- yctimlin/mcp_excalidraw/excalidraw-skill
- Publisher
- yctimlin
- Repository
- mcp_excalidraw
- Installs
- 0
- Files
- 3
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
yctimlin/mcp_excalidraw/excalidraw-skillInstalls these files- SKILL.md
- evals/evals.json
- references/cheatsheet.md
What this skill tells the agent
Excalidraw Skill
Step 0: Pick an Interface
Three interfaces drive the same live canvas. Pick the first one that applies:
- MCP tools — if
excalidraw/*tools (e.g.batch_create_elements) are in your tool list, prefer them: results land directly in your context, and screenshots come back as images without touching disk. - CLI (default when no MCP tools are present): ``
bash npx -y mcp-excalidraw-server <command>`No setup needed — any canvas-touching command **auto-starts the canvas server** onhttp://127.0.0.1:3000(firstnpxrun downloads the package). If the CLI is installed globally (npm i -g mcp-excalidraw-server), the shorter aliasexcalidraw-canvas <command>` works too. - REST API (last resort, e.g. from application code): HTTP endpoints on
http://127.0.0.1:3000— seereferences/cheatsheet.mdfor payloads. The server must already be running.
The canvas URL comes from EXPRESS_SERVER_URL (default http://127.0.0.1:3000). Remind the user to open that URL in a browser — screenshots, image export, mermaid conversion, and viewport control need an open tab (CLI exits with code 4 when it's missing).
CLI Quick Reference
Results are JSON on stdout — except describe (plain text) and raw-content output when --out is omitted (export scene JSON, screenshot --format svg). Diagnostics on stderr. Exit codes: 0 ok, 1 error, 2 usage, 3 canvas unreachable, 4 browser tab required.
| Task | Command | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Start / stop / inspect server | start, stop, status | ||||||||
| Create elements (batch) | add elements.json or `echo '[...]' \ | add or add --one '{...}'` | |||||||
| Multi-op patch in one call | apply patch.json — {"create":[...],"update":[{"id":"a","set":{...}}],"delete":[...]} | ||||||||
| Read one / query many | get <id>, query [--type t] [--bbox x0,y0,x1,y1] [--filter k=v] [--filter-json '{...}'] | ||||||||
| Update / delete | update <id> --set '{...}', delete <id> [...] | ||||||||
| Understand the scene | describe (plain-text summary: ids, positions, labels, connections) | ||||||||
| See the scene | screenshot [--out f.png] (PNG without --out → temp file path in JSON; SVG without --out → raw SVG) | ||||||||
| Layout operations | `arrange align\ | distribute\ | group\ | ungroup\ | lock\ | unlock\ | duplicate --ids a,b,c [--to left\ | horizontal\ | ...]` |
| Scene files | export [--out scene.excalidraw], `import [scene.excalidraw | -] [--replace] — a .excalidraw.md` out path writes Obsidian's format (see File I/O) | |||||||
| Mermaid → canvas | `mermaid [diagram.mmd | -]` (or stdin) | |||||||
| Snapshots | `snapshot save\ | list\ | restore <name>` | ||||||
| Share link | share (encrypted upload → excalidraw.com URL) | ||||||||
| Wipe canvas | clear --yes | ||||||||
| Install / upgrade this skill | install-skill --dir <skills-root> (agent chooses project/global root) |
Element Format (CLI and MCP)
The CLI and MCP tools accept the same agent-friendly format and normalize it automatically:
- Labels: put
"text": "My Label"on any shape — converted to Excalidraw's bound-label format for you. - Arrow binding:
"startElementId": "a"/"endElementId": "b"— arrows auto-route to element edges. - fontFamily: pass a string name (
"helvetica","cascadia","excalifont", ...) or string number"1"–"8". - points: both
[[x,y], ...]tuples and[{"x":..,"y":..}]objects are accepted. - Patch updates: in
apply, update entries can use either direct fields ({"id":"a","x":120}) or asetobject ({"id":"a","set":{"x":120}}). Do not mix both forms in one update entry.
Raw REST is stricter: labels must be "label": {"text": "..."}, bindings must be "start": {"id": "..."} / "end": {"id": "..."}. Only worry about this when POSTing to the API directly.
Coordinate System
The canvas uses a 2D coordinate grid: (0, 0) is the origin, x increases rightward, y increases downward. Plan your layout before writing any JSON.
General spacing guidelines:
- Vertical spacing between tiers: 80–120px (enough that arrows don't crowd labels)
- Horizontal spacing between siblings: 40–60px minimum; give labeled arrows 120px+
- Shape width:
max(160, labelCharCount * 12)to keep the label on one line - Shape height: 60px single-line, 80px two-line labels
- Background/zone padding: 50px on all sides around contained elements
Styling for a professional look:
"fillStyle": "solid"on shapes gives crisp flat fills — the default is a sketchy hachure pattern- Pair pastel
backgroundColorfills with their darkerstrokeColor(palette in the cheatsheet) "strokeStyle": "dashed"on zone borders and async arrows reads as "boundary / background"
Layout Anti-Patterns (Critical for Complex Diagrams)
These are the most common mistakes that produce unreadable diagrams. Avoid all of them.
1. Do NOT use label.text (or text) on large background zone rectangles
When you put a label on a background rectangle, Excalidraw creates a bound text element centered in the middle of that shape — right where your service boxes will be placed. The text overlaps everything inside the zone and cannot be repositioned.
Wrong:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "text": "VPC (10.0.0.0/16)"}Right — use a free-standing text element anchored at the top of the zone:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "backgroundColor": "#e3f2fd"},
{"id": "vpc-label", "type": "text", "x": 70, "y": 60, "width": 300, "height": 30, "text": "VPC (10.0.0.0/16)", "fontSize": 18}The free-standing text element sits at the top corner of the zone and doesn't interfere with elements placed inside.
2. Avoid cross-zone arrows in complex diagrams
An arrow from an element in one layout zone to an element in a distant zone will draw a long diagonal line crossing through everything in between. In a multi-zone infra diagram this produces an unreadable tangle of spaghetti.
Design rule: Keep arrows within the same zone or tier. To show cross-zone relationships, use annotation text or separate the zones so their edges are adjacent (no elements between them), and route the arrow along the edge.
If you must connect across zones, use an elbowed arrow that travels along the perimeter — never through the middle of another zone.
3. Use arrow labels sparingly
Arrow labels are placed at the midpoint of the arrow. On short arrows, they overlap the shapes at both ends. On crowded diagrams, they collide with nearby elements.
- Only add an arrow label when the relationship name is genuinely essential (e.g., protocol, port number, data direction).
- If you're adding a label to every arrow, reconsider — it usually adds visual noise, not clarity.
- Keep arrow labels to ≤ 12 characters. Prefer omitting them entirely on dense diagrams.
Quality: Why It Matters (and How to Check)
Excalidraw diagrams are visual communication. If text is cut off, elements overlap, or arrows cross through unrelated shapes, the diagram becomes confusing and unprofessional — it defeats the whole purpose of drawing it. So after every batch of elements, verify before adding more.
Quality Checklist
After each add / apply / batch_create_elements, take a screenshot and check:
- Text truncation — Is all label text fully visible? Truncated text means the shape is too small. Increase
widthand/orheight. - Overlap — Do any shapes share the same space? Background zones must fully contain children with padding.
- Arrow crossing — Do arrows cut through unrelated elements? If yes, route them around using curved or elbowed arrows (see Arrow Routing below).
- Arrow-label overlap — Arrow labels sit at the midpoint. If they overlap a shape, shorten the label or adjust the arrow path.
- Spacing — At least 40px gap between elements. Cramped layouts are hard to read.
Use this skill in a project
Open any RiverX project, search the Skills panel for yctimlin/mcp_excalidraw/excalidraw-skill, and install it in one click.
