From Excalidraw Diagrams
Create or edit Excalidraw diagrams (.excalidraw files) for ANY subject — system architectures, pipelines, flowcharts, research papers and ML methods, decisions being discussed, business processes, data models, timelines, comparisons, abstract concepts. Hand-drawn whiteboard style; files open on excalidraw.com. Renders locally to PNG and self-reviews the image. Use when the user asks to diagram, visualize, sketch, draw, map out, or "excalidraw" anything.
How this skill is triggered — by the user, by Claude, or both
Slash command
/excalidraw:excalidrawThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You create **hand-drawn visual explanations** — the whiteboard sketch a senior engineer draws while explaining something. Not "a flowchart": a picture that makes someone *understand*.
examples/example_1.excalidrawreferences/arrows.mdreferences/decomposition.mdreferences/format.mdreferences/mermaid.mdreferences/patterns.mdreferences/style.mdscripts/excal.pyscripts/vendor/excalidraw/__init__.pyscripts/vendor/excalidraw/__main__.pyscripts/vendor/excalidraw/cli.pyscripts/vendor/excalidraw/colors.pyscripts/vendor/excalidraw/fonts/JetBrainsMono.ttfscripts/vendor/excalidraw/fonts/Virgil.ttfscripts/vendor/excalidraw/parser.pyscripts/vendor/excalidraw/renderer.pyscripts/vendor/excalidraw/shapes.pyscripts/vendor/excalidraw/text.pyYou create hand-drawn visual explanations — the whiteboard sketch a senior engineer draws while explaining something. Not "a flowchart": a picture that makes someone understand.
Diagrams ARGUE, they don't display. Every element earns its place by contributing to an argument about how something works. The shape of the diagram should BE the meaning.
The bar, before you deliver:
excalidraw/<name>.excalidraw (create the folder in the project root; kebab-case name). Build in z-order: zones → shapes → standalone text → bound text & arrows (array order = stacking order). Use the helpers (§4) for bound text and arrows — they compute the fiddly geometry.excal.py check (§4) → fix every warning.excal.py render (§4) → then Read the PNG. Actually look at it..png (embed-ready), the .excalidraw (drag onto excalidraw.com to edit), and offer a share link (excal.py share). The user's feedback in chat continues the loop — treat every comment as another audit pass.| Subject | Approach |
|---|---|
| Codebase / system architecture | C4-ish views; identifiers Grep'd from the code; zones per deployment boundary |
| Research paper / ML method | Method pipeline input → stages → output; dims/equations as evidence panels (§7); training vs inference as separate flows or zones; results as a small comparison panel |
| A decision being discussed (in this chat) | Options as columns × criteria as aligned rows, or a decision tree; the chosen path highlighted with the accent color; arguments pulled from the conversation |
| Business / human process | Swimlanes: one horizontal zone per actor, time flowing L→R |
| Data model | ER diagram; crowfoot_* arrowheads; ≤8 entities per view |
| Incident, history, roadmap | Timeline pattern (§7) with phases as zones above/below the line |
| Comparison ("X vs Y") | Side-by-side panels with row-aligned aspects; differences accented, sameness greyed |
| Abstract concept / mental model | Free-form via the creativity engine (§7): metaphor, show-don't-tell |
The conversation itself is a valid source — when the user says "diagram what we just decided", the content is the chat: extract the real options weighed, constraints named, and the conclusion. Confirm anything fuzzy rather than decorating a guess.
Same subject, three legitimate diagrams. Depth changes how much you explain — never how clearly.
When torn between two depths, take the more explanatory one. A reader who understands fast forgives an extra annotation; one who's lost forgives nothing.
Skeleton (this is the whole file format):
{"type":"excalidraw","version":2,"source":"https://excalidraw.com",
"elements":[ ... ],
"appState":{"viewBackgroundColor":"#ffffff","gridSize":20}}
Author terse elements — omit anything Excalidraw defaults on load (seed, version, versionNonce, updated, index, angle:0, isDeleted, groupIds:[], frameId, link, locked...). A shape needs only:
{"id":"api","type":"rectangle","x":300,"y":200,"width":180,"height":90,
"strokeColor":"#1971c2","backgroundColor":"#a5d8ff","fillStyle":"solid",
"strokeWidth":2,"roughness":1,"roundness":{"type":3}}
{"id":"title","type":"text","x":280,"y":40,"width":340,"height":35,
"text":"Payment Flow","fontSize":28,"fontFamily":5,"strokeColor":"#1e1e1e"}
auth-db, auth-arrow-1). Never duplicated.angle.references/format.md.Helper CLI — every command is uv run --python 3.12 "${CLAUDE_SKILL_DIR}/scripts/excal.py" <subcommand> ... (quote the path; works from any cwd; rewrites the file in place):
textbox <file> <containerId> "Label text" centered bound text in a shape [--size 16 --font 5 --color HEX]
connect <file> <fromId> <toId> edge-to-edge arrow + bindings [--label TXT --style dashed --elbow --color HEX --end-head triangle --from-side auto]
check <file> geometric lint: overlaps, overflow, broken refs, floating arrows
render <file> PNG preview [-o out.png --scale 2]
share <file> encrypted upload → excalidraw.com link
Hand-author bound text / arrows only when you need something the helpers can't do — mechanics in references/arrows.md and references/format.md.
Setup hiccups: helpers need uv (brew install uv); the renderer needs system cairo once (brew install cairo / apt-get install libcairo2-dev). If rendering is impossible on this machine, keep authoring + check (still valid diagrams — you just lose the visual pass; say so to the user).
One flow axis per diagram. L→R for pipelines/processes/sequences; T→B for hierarchies/decisions; radial for hub-and-spoke. Never mix axes in one view.
Rank discipline (mental Sugiyama): rank = hops from the entry point. Same rank ⇒ same column (L→R) or row (T→B), sharing the exact coordinate. Reorder nodes within a rank to minimize arrow crossings — target zero crossings; feedback/return edges go dashed, routed around the outside.
Size = importance. Three tiers, one hero:
| Tier | Size | Use |
|---|---|---|
| HERO | ~300×150 | THE thing the diagram is about — exactly one, given the most whitespace (≥200px isolation) |
| PRIMARY | ~180×90 | main flow participants |
| SECONDARY | ~120×60 | supporting pieces |
| marker | 16–20 | dots, ticks, step badges, connection points |
Box size comes from its text: width ≥ longest-line-chars × fontSize × 0.6 + 30; height ≥ lines × fontSize × 1.25 + 30. (The textbox helper warns/grows for you.)
Spacing: ~40px between related elements; ≥2× that between groups. Crowding next to voids reads as broken — distribute.
Grouping = enclosure (the strongest visual cue). Zone recipe — draw FIRST (lowest z):
{"id":"zone-auth","type":"rectangle","x":260,"y":140,"width":520,"height":300,
"strokeColor":"#868e96","backgroundColor":"transparent","strokeStyle":"dashed",
"strokeWidth":1,"roughness":1,"roundness":{"type":3}}
plus a 14–16px UPPERCASE grey label inside top-left (x+15, y+12). 20px padding around children (+30 top for the label). Nesting ≤2 deep. Never use type:"frame" — invisible in local preview (§9).
≤20 elements per view. More → decompose (§10).
Semantic colors — dark stroke (shade idx4) paired with light fill (idx1) of the SAME hue:
| Role | Stroke | Fill |
|---|---|---|
| neutral / default | #1e1e1e | transparent |
| primary / data flow | #1971c2 | #a5d8ff |
| process / success | #2f9e44 | #b2f2bb |
| storage / state | #e8590c | #ffd8a8 |
| error / critical | #e03131 | #ffc9c9 |
| AI / special | #6741d9 | #d0bfff |
| decision / warning | #f08c00 | #ffec99 |
| secondary / annotation | #868e96 | #f8f9fa |
Rules: ≤3 semantic hues + neutrals per diagram (add a small legend if ≥3 carry meaning) · 60-30-10 balance — the most saturated color on ≤10% of elements (your focal accent) · color encodes meaning, never decoration · full 12-hue ramp + cloud-vendor palettes (AWS orange etc.): references/style.md.
Typography (4 levels, consistent):
fontFamily:5 (or 7 for display) — no box around titles#868e96fontFamily:8. No emoji (won't render).Texture: one roughness for the whole diagram — 1 (default sketch) or 0 (precise/technical). strokeWidth 2 default, 1 for fine structure lines, 4 only for the hero's emphasis. Line semantics: solid=sync/primary flow · dashed=async/optional/zones · dotted=weak reference. Arrowheads: arrow flow (default) · triangle inheritance/strong typed · bar terminator · circle connection · crowfoot_one/crowfoot_many/crowfoot_one_or_many ER cardinality. Opacity 20–40 for translucent overlap/highlight layers.
Each major concept gets a DIFFERENT visual treatment. Uniform same-size box grids are a failure mode. Map concepts to patterns:
| Concept | Pattern |
|---|---|
| one-to-many | fan-out: arrows radiating to a spread of targets |
| many-to-one | funnel/convergence |
| hierarchy | tree of lines + free text (not nested boxes) |
| cycle / retry | circular arrow loop |
| transformation | assembly line: in → process → out |
| multiplicity ("many X") | offset stack: 3 copies at +8x/+4y, fading opacity |
| same thing over time | copies linked by dotted lines |
| overlap / intersection | overlapping translucent ellipses |
| timeline | horizontal line + dot markers + free text above/below |
| layers | stacked full-width rounded rects |
Show, don't tell. For anything hard to caption, ask "how could I SHOW this?" — a queue is a long rect with small rects inside it; a shard is a cylinder split by lines; a stream is a dashed arrow with little squares riding it. Full recipe library: references/patterns.md.
Text is seasoning, not structure. The drawing explains; words only name. If a region makes sense only because of a sentence sitting next to it, that region is undrawn — replace the sentence with a visual device before reaching for prose:
Free text first. Default to free-floating text; box text only when the shape means something (a component, a store, a boundary) or must receive an arrow. Target: <30% of text elements live in containers. Lines beat boxes for structure (timelines, trees, dividers).
Annotation layers (what makes it feel like notes, not a chart):
term* then a smaller grey *explanation nearby.#1e293b bg) with 14px fontFamily:8 code/payload text in #b2f2bb — show the REAL event/payload/equation/tensor shape.#868e96) next to the thing they explain.After check passes: render, Read the PNG, audit:
--scale 3 to verify tight cases)Common fixes: widen box / re-run textbox · shift x/y on the 20-grid · re-run connect after moving shapes (arrows don't follow automatically) · add a waypoint to route an arrow around an obstacle · move a label next to its owner · resize to restore hierarchy.
Stop when you'd show it without caveats — usually 2–3 passes. Then deliver; the user's chat feedback drives further passes.
The bundled renderer is fast and faithful for layout QA, with known gaps — author around them:
type:"frame" renders nothing → always use zone rectangles (§5). Frames are fine on the web, but you'd be blind locally.fillStyle:"hachure"/"cross-hatch" render solid locally (correct on web). Don't rely on texture to encode meaning.connect computes edge-to-edge geometry; re-run it after moving endpoints' shapes.textbox pre-centers it. Don't hand-place bound text without the centering math.Trigger (from §1.2): >12 major elements / multiple subsystems / multiple zoom levels → offer the user (in the same AskUserQuestion as the depth dial when both trigger):
(A) one high-level overview · (B) a deep-dive of one component · (C) both — overview + a detail file per component
For (C), C4-style: excalidraw/<system>-overview.excalidraw (what talks to what, no internals) + excalidraw/<component>-detail.excalidraw per component (internals + immediate neighbors as greyed, dashed, 50-opacity context anchors at the edges). Keep names IDENTICAL across files. Overview boxes with a detail file get a 14px grey → see <component>-detail note. Every file: title + one-line grey subtitle. Run the full check+render loop per file. Works for non-code too (paper → method overview + per-stage detail; process → end-to-end + per-actor detail). Full protocol: references/decomposition.md.
Read the file first. Preserve the author's ids, palette, and style — match it, don't impose yours. After edits: check, re-connect any arrows whose endpoints moved, render, view. Append new elements at the right z-position (zones near the front of the array, arrows/text at the end).
Before delivering, confirm: unique ids · strict JSON · one flow axis · one focal point · ≤3 semantic hues, same-hue stroke/fill pairs · <30% boxed text · all text ≥14px · annotations ≤12 words and no canvas paragraphs · squint test passes (structure teaches without the words) · no frame elements · depth honored (§3) · check clean · you looked at the final PNG and would show it without caveats.
npx claudepluginhub sidfeels/excalidraw-diagrams --plugin excalidrawProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.