Skip to content
Back to skills

Excalidraw

ASecurity

Use when creating new Excalidraw diagrams or reading, modifying, or comparing existing .excalidraw or .excalidraw.json files. Also use when the user asks for hand-drawn style diagrams, whiteboard sketches, architecture diagrams in Excalidraw format, or wants to export Excalidraw to SVG/PNG. Use this skill even if the user doesn't say "Excalidraw" — for example when they ask for a system diagram, flowchart, or architecture sketch that should look hand-drawn or informal.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 11, 2026
ai-agentspythongobashnodedocumentation

Works with

  • claude code
  • cli
  • mcp

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 8 files and shows the line behind each finding

Scanned September 11, 2026

npx -y skills add atc-net/atc-agentic-toolkit --skill excalidraw --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Excalidraw?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Excalidraw
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/atc-net-excalidraw/badge)](https://www.skillsdirectory.com/skills/atc-net-excalidraw)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: excalidraw
description: Use when creating new Excalidraw diagrams or reading, modifying, or comparing existing .excalidraw or .excalidraw.json files. Also use when the user asks for hand-drawn style diagrams, whiteboard sketches, architecture diagrams in Excalidraw format, or wants to export Excalidraw to SVG/PNG. Use this skill even if the user doesn't say "Excalidraw" — for example when they ask for a system diagram, flowchart, or architecture sketch that should look hand-drawn or informal.
---

# Excalidraw

## Excalidraw MCP Server (optional)

The official Excalidraw MCP server (`https://mcp.excalidraw.com`) supports natural-language diagram generation. It uses Streamable HTTP transport, which isn't supported by the plugin MCP system — users who want it must add it manually to their Claude Code settings.

If the Excalidraw MCP tools are available in the current session, use them for quick one-shot diagrams. Otherwise, use direct JSON generation as described below.

---

## References

This skill includes detailed reference files. Read them when you need deeper guidance:

| Reference | When to read |
|-----------|-------------|
| [references/element-reference.md](references/element-reference.md) | Need exact properties for a specific element type (text fields, arrow points, image embedding, frames, groups, freedraw) |
| [references/diagram-patterns.md](references/diagram-patterns.md) | Building a flowchart, sequence diagram, mind map, architecture diagram, ERD, or DFD — includes layout patterns and shape conventions |
| [references/color-palette.md](references/color-palette.md) | Choosing colors — semantic fills/strokes, text hierarchy, evidence-artifact palette. **Single source of truth for all colors.** |
| [references/design-methodology.md](references/design-methodology.md) | Diagram needs to teach or argue (technical architectures, tutorials, documentation). Covers evidence artifacts, multi-zoom, visual patterns, container discipline, and section-by-section authoring for large diagrams |

For most simple diagrams the information in this SKILL.md is sufficient. Consult the references for complex or specific diagram types.

---

## Creating a New Diagram (Direct JSON)

Generate the JSON directly. No subagent needed for creation.

### File Envelope

Every `.excalidraw` file is a JSON object:

```json
{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [],
  "appState": {
    "gridSize": null,
    "viewBackgroundColor": "#ffffff"
  },
  "files": {}
}
```

### Element Types

| Type        | Use for                          |
|-------------|----------------------------------|
| `rectangle` | Boxes, nodes, containers         |
| `ellipse`   | Circles, ovals                   |
| `diamond`   | Decision / branching nodes       |
| `arrow`     | Connections between shapes       |
| `line`      | Non-connecting line segments     |
| `text`      | Standalone labels                |

### Required Fields Per Element

Every element needs all of these:

```json
{
  "id": "V1StGXR8_Z5jdHi6B-myT",
  "type": "rectangle",
  "x": 100,
  "y": 100,
  "width": 200,
  "height": 80,
  "angle": 0,
  "strokeColor": "#1e1e1e",
  "backgroundColor": "transparent",
  "fillStyle": "solid",
  "strokeWidth": 2,
  "strokeStyle": "solid",
  "roughness": 1,
  "opacity": 100,
  "groupIds": [],
  "frameId": null,
  "roundness": null,
  "seed": 1482348421,
  "version": 1,
  "versionNonce": 391154490,
  "isDeleted": false,
  "boundElements": null,
  "updated": 1700000000000,
  "link": null,
  "locked": false
}
```

IDs must be random alphanumeric strings (~21 chars, nanoid-style). Never use sequential integers — duplicate or predictable IDs corrupt the file silently.

`seed` and `versionNonce` must be random positive integers. Using `0` causes rendering glitches.

### Arrow Bindings

When an arrow connects two shapes, three elements need updating:

**Arrow:**
```json
{
  "type": "arrow",
  "startBinding": { "elementId": "<source-id>", "focus": 0, "gap": 1 },
  "endBinding":   { "elementId": "<target-id>", "focus": 0, "gap": 1 },
  "points": [[0, 0], [200, 0]]
}
```

**Source shape's `boundElements`:**
```json
"boundElements": [{ "type": "arrow", "id": "<arrow-id>" }]
```

**Target shape's `boundElements`:**
```json
"boundElements": [{ "type": "arrow", "id": "<arrow-id>" }]
```

All three must be in sync. A broken binding renders as a disconnected floating arrow.

Arrow `points` always start at `[0, 0]` — coordinates are relative to the arrow's x,y position.

### Text in Shapes

To place text inside a shape, create a separate `text` element with `containerId` set to the parent shape's ID, and add the text to the parent's `boundElements`:

**Parent shape:**
```json
"boundElements": [{ "type": "text", "id": "<text-id>" }]
```

**Text element:**
```json
"containerId": "<parent-shape-id>"
```

The text element's `strokeColor` IS the text color — omitting it can cause invisible text on white backgrounds.

---

## Editing an Existing Diagram

**Never use the Read tool on `.excalidraw` files.** Excalidraw JSON consumes 4k-22k tokens — nearly all visual metadata. Always delegate to a subagent.

### Pattern

```
Main agent                    Subagent
-------------------------------------------------------------
Receive edit request
Create subagent task -------> Read .excalidraw file
                              Return semantic summary:
                              - element labels + types
                              - connection topology
                              - NO raw JSON
Specify changes ------------> Apply changes to JSON
                              Write updated file
                              Confirm: added/changed/removed
```

### Subagent Task Templates

**Understand a diagram:**
> Read `<path>`. Return: a list of all elements with their text labels and types, and which elements are connected to which. Do not return any JSON.

**Modify a diagram:**
> Read `<path>`. Make these changes: `<plain-language changes>`. Write the updated file. Confirm which elements were added, changed, or removed.

**Compare two diagrams:**
> Read `<file-a>` and `<file-b>`. Return the architectural differences — which elements exist in one but not the other, and how the connection topology differs. Do not return any JSON.

---

## Best Practices

### Spacing and Layout

- Minimum 40px between any elements
- 100-120px gap for unlabeled arrows, 150-200px for labeled
- Container/zone padding: 50-60px inside edges

### Styling

- Use `roughness: 0` for technical/formal diagrams (hand-drawn feel only when explicitly requested)
- Use `fontFamily: 2` (Helvetica) for professional diagrams, `1` (Virgil) for casual/sketch, `3` (Cascadia) for code-heavy diagrams
- Pull colors from [`references/color-palette.md`](references/color-palette.md) — don't invent ad-hoc hex values. Edit that file to customize for a brand.
- For containers with children, use `opacity: 25-40` on the background to avoid obscuring contents

### Large Diagrams

For comprehensive/technical diagrams that would exceed a single output response, build section by section instead of all at once — see the *Section-by-Section for Large Diagrams* section in [`references/design-methodology.md`](references/design-methodology.md).

### Font Sizing

| Purpose     | Size |
|-------------|------|
| Title       | 28px |
| Section     | 24px |
| Label       | 20px |
| Description | 16px |
| Notes       | 14px |

### Element Sizing from Text

Calculate width: `max(160, charCount * 9)` for Latin text. Height: 60px for single-line, +24px per additional line.

---

## Render & Validate

You cannot judge a diagram from JSON alone. For anything beyond a trivial sketch, render the file to PNG and read the image back so you can see what you produced.

### Running the renderer

From the skill's `scripts/` directory:

```bash
python render_excalidraw.py <path-to-file.excalidraw>
```

The PNG is written next to the `.excalidraw` file. **Use the Read tool on the PNG** to actually see the result — the JSON output alone doesn't tell you whether text is clipped, arrows overlap shapes, or spacing is unbalanced.

### First-time setup

```bash
pip install -r requirements.txt
playwright install chromium
```

Both commands run from the skill's `scripts/` directory. Python 3.11+ is required.

### The render-view-fix loop

After rendering:

1. **Audit against intent** — does the structure match what you designed? Does the eye flow in the intended order? Is hierarchy correct (hero elements dominant)?
2. **Check for visual defects** — text clipped or overflowing, shapes overlapping, arrows crossing through elements or landing in empty space, uneven spacing, whitespace lopsided between sections, text too small.
3. **Fix** — widen containers when text is clipped, adjust x/y for spacing, add waypoints to arrow `points` arrays to route around elements, rebalance sizes across sections.
4. **Re-render, re-read, repeat.** Typically 2–4 iterations. Don't stop after one pass just because nothing is broken — improve composition if it can be improved.

## Exporting

Drag and drop any `.excalidraw` file into [excalidraw.com](https://excalidraw.com) to open, edit, and export to PNG/SVG. Or use the renderer above for programmatic PNG export.

---

## Common Pitfalls

| Pitfall | Fix |
|---------|-----|
| `seed` or `versionNonce` is `0` | Use random positive integers |
| Arrow added but endpoint shapes not updated | Update `boundElements` on both source and target shapes |
| `containerId` set but container missing entry | Keep `containerId` and `boundElements` in sync |
| IDs are sequential integers (`1`, `2`, `3`) | Use nanoid-style random strings (~21 chars) |
| Main agent reads file to "quickly check" | No exceptions — delegate to subagent |
| Text invisible on white background | Set `strokeColor` on text element (it IS the text color) |
| Text on container overlaps children | Use a free-standing text at the top, not bound text |
| `boundElements` set to `[]` | Use `null` for empty — `[]` can cause issues |
| Cross-zone diagonal arrows look messy | Route arrows along zone perimeters instead |

Files in this skill

  • SKILL.md10 KB
  • references/color-palette.md2.3 KB
  • references/design-methodology.md9.4 KB
  • references/diagram-patterns.md12.3 KB
  • references/element-reference.md8.2 KB
  • scripts/render_excalidraw.py5.9 KB
  • scripts/render_template.html1.5 KB
  • scripts/requirements.txt19 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…