---
name: drawio-skill
trigger: /drawio
description: >
  Generate diagrams programmatically using the draw.io desktop CLI — flowcharts,
  swimlanes, sequence diagrams, architecture diagrams, ERDs, UML class diagrams,
  ML/DL model figures, and more. Exports PNG, SVG, PDF, or JPG headlessly from
  mxGraph XML. Use when you need polished, precise diagrams with custom styling,
  rich shape vocabulary, or exportable images. NOT for hand-drawn/whiteboard
  looks (use Excalidraw), diagrams-as-code in Markdown (use Mermaid), or
  freeform sketching.
user_invocable: true
---

> **Public / shared version** — trimmed from a private Claude Code setup and
> posted at smereski.com as a reusable pattern.

# drawio-skill — generate diagrams with the draw.io CLI

Generate `.drawio` XML files and export to PNG/SVG/PDF/JPG locally using the
native draw.io desktop app CLI. No browser automation needed.

## When to use / when NOT to use

**Use for:** polished, precise diagrams (architecture, network, strict UML,
ERD), anything needing solid opaque fills, 10,000+ stock/branded shapes,
swimlanes, or custom geometry; export as editable PNG/SVG/PDF.

**Do NOT use — route elsewhere — for:**
- Casual hand-drawn / whiteboard look → **Excalidraw** or **tldraw**.
- Diagrams-as-code that live in git / render in Markdown → **Mermaid** (general)
  or **PlantUML** (UML).
- Freeform infinite-canvas sketching → **tldraw**.

## Prerequisites

Ensure **draw.io desktop** is installed and accessible from the command line,
and optionally **Graphviz** (`dot`) is on PATH for auto-layout of large graphs.

Install draw.io desktop from the official releases:
<https://github.com/jgraph/drawio-desktop/releases>
- macOS: `brew install --cask drawio` (binary: `drawio`)
- Windows: download the installer (binary: `draw.io.exe`)
- Linux: download `.deb`/`.rpm` — **do not use snap** (AppArmor sandbox issues)

Install Graphviz (optional, for auto-layout):
- macOS: `brew install graphviz`
- Windows/Linux: download from <https://graphviz.org/download/>

After installation, verify:
```bash
drawio --version       # macOS/Linux (Homebrew)
draw.io --version      # older installs or some Linux packages
"draw.io.exe" --version  # Windows (full path if not on PATH)
```

**Resolve which binary name works on your system** in Step 1 and use that
name consistently throughout every command in this workflow.

## Workflow

### Step 0 — Clarify (if needed)

If these are unclear, ask 1-3 questions before generating:
- Diagram type (ERD, UML, sequence, architecture, ML/DL, flowchart)?
- Output format (PNG default, SVG, PDF, JPG)?
- Approximate scope (how many nodes/components)?

Skip clarification if the request already specifies these.

### Step 1 — Resolve binary

Try in order: `drawio --version` → `draw.io --version` → macOS app path →
Windows `.exe` path. Use the first that prints a version; remember the exact
name/path for every export command.

### Step 2 — Plan

Identify shapes, relationships, layout direction (LR or TB), and logical
groupings before writing XML. Sketch mentally or on paper first.

### Step 3 — Generate `.drawio` XML

Write the XML file to disk. For small/styled diagrams, hand-place coordinates.
For large or layout-heavy diagrams (> ~15 nodes), use auto-layout via Graphviz.

### Step 4 — Export draft PNG (no `-e`)

```bash
drawio -x -f png --width 2000 -o diagram.png input.drawio
```

Do NOT pass `-e` at this step — the embedded XML chunk it adds causes vision
APIs to return "Could not process image."

### Step 5 — Self-check (vision)

Read the exported PNG with the agent's vision capability. Check for:
- Overlapping shapes → shift apart by ≥200px
- Clipped labels → increase shape size
- Missing connections → verify `source`/`target` ids
- Off-canvas shapes → move to positive coordinates
- Edge-shape overlap → add waypoints (`<Array as="points">`)
- Stacked edges → distribute entry/exit points across perimeter

Max 2 self-check rounds. If issues remain after 2 fixes, show the user anyway.

### Step 6 — Review loop

Show the image and collect feedback. Apply targeted XML edits:
- Change color → update `fillColor`/`strokeColor` in `style`
- Add node → append new `mxCell` vertex
- Remove node → delete `mxCell` and its edges
- Move shape → update `x`/`y` in `mxGeometry`
- Layout-wide changes → regenerate full XML

Loop until the user approves. After 5 iterations, suggest opening the `.drawio`
file in draw.io desktop for fine-grained adjustments.

### Step 7 — Final export

```bash
# Final PNG with embedded diagram (editable in draw.io)
drawio -x -f png -e -s 2 -o diagram.drawio.png input.drawio

# SVG
drawio -x -f svg -e -o diagram.svg input.drawio

# PDF
drawio -x -f pdf -e -o diagram.pdf input.drawio
```

**After `-e` PNG export, run the repair script** — draw.io CLI truncates the
IEND chunk in embedded PNGs. The `repair_png.py` script (from the full
drawio-skill bundle) fixes the 8-byte truncation; vision APIs and strict PNG
decoders reject the truncated file.

## Key CLI flags

| Flag | Meaning |
|------|---------|
| `-x` | Export mode (required) |
| `-f png/svg/pdf/jpg` | Output format |
| `-e` | Embed diagram XML in output (PNG/SVG/PDF) — skip for preview, use for final |
| `-s 2` | Scale factor (2 = 2x resolution; for final PNG only) |
| `--width 2000` | Max width in px (use for preview to stay under vision API ceiling) |
| `-o path` | Output file path |
| `-b 10` | Border width in pixels |
| `-t` | Transparent background (PNG only) |

## draw.io XML structure

### File skeleton

```xml
<?xml version="1.0" encoding="UTF-8"?>
<mxfile host="drawio" version="26.0.0">
  <diagram name="Page-1">
    <mxGraphModel>
      <root>
        <mxCell id="0" />
        <mxCell id="1" parent="0" />
        <!-- user shapes start at id="2" -->
      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
```

Rules:
- `id="0"` and `id="1"` are required root cells — never omit them.
- User shapes start at `id="2"` and increment sequentially.
- All shapes have `parent="1"` (unless inside a container).
- All text uses `html=1` in style.
- Never use `--` inside XML comments (illegal per XML spec).
- Escape special chars: `&amp;`, `&lt;`, `&gt;`, `&quot;`.
- Multi-line labels: use `&#xa;` for line breaks (not literal `\n`).

### Common shape styles

| Style keyword | Use for |
|--------------|---------|
| `rounded=0` | Plain rectangle |
| `rounded=1` | Rounded rectangle — services, modules |
| `ellipse;` | Circles/ovals — start/end nodes |
| `rhombus;` | Diamond — decision points |
| `shape=cylinder3;` | Cylinder — databases |
| `swimlane;` | Container with title bar |

### Edge (CRITICAL)

Every edge `mxCell` must contain a `<mxGeometry relative="1" as="geometry" />`
child element. Self-closing edge cells are **invalid** and will not render.

```xml
<mxCell id="10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;
  orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1"
  source="2" target="3">
  <mxGeometry relative="1" as="geometry" />
</mxCell>
```

Always include `rounded=1;orthogonalLoop=1;jettySize=auto` for smart routing.
Pin `exitX/exitY/entryX/entryY` on every edge when a node has 2+ connections.

### Color palette (default)

| Color | fillColor | strokeColor | Use for |
|-------|-----------|-------------|---------|
| Blue | `#dae8fc` | `#6c8ebf` | Services, clients |
| Green | `#d5e8d4` | `#82b366` | Success, databases |
| Yellow | `#fff2cc` | `#d6b656` | Queues, decisions |
| Orange | `#ffe6cc` | `#d79b00` | Gateways, APIs |
| Red/Pink | `#f8cecc` | `#b85450` | Errors, alerts |
| Grey | `#f5f5f5` | `#666666` | External/neutral |
| Purple | `#e1d5e7` | `#9673a6` | Security, auth |

### Layout tips

- Snap all `x`, `y`, `width`, `height` to multiples of 10.
- Leave ~80px empty corridors between rows/columns for edge routing.
- Place hub nodes centrally so edges radiate outward instead of crossing.
- For event-bus patterns: place the bus/queue node in the center of the
  service row (not below) so services on either side reach it with short
  horizontal arrows.

## Gotchas

- **Windows headless:** if the export hangs or dies silently, append
  `--no-sandbox` at the END of the command (placing it earlier makes draw.io
  treat it as the input filename).
- **Linux as root (CI/Docker):** append `--no-sandbox` at the very end.
- **Linux headless:** prefix with `xvfb-run -a --server-args="-screen 0 1280x1024x24"`.
- **macOS sandboxed environments:** the draw.io CLI may crash. Use the XML-only
  or browser-fallback output instead.
- **`-e` PNG truncation:** the CLI truncates the IEND chunk in embedded PNGs —
  run the repair script after every `-e` PNG export.
- **Vision API ceiling:** images > 2576×2576px are rejected. Use `--width 2000`
  for preview exports.
- **WSL2 / Windows:** `cmd.exe` drops URL `#fragment`s — write a `.url`
  shortcut file when opening browser-fallback links.

## Browser fallback (no CLI needed)

When the CLI is unavailable, encode the diagram as a diagrams.net URL:
```bash
python3 scripts/encode_drawio_url.py input.drawio       # read-only viewer
python3 scripts/encode_drawio_url.py --edit input.drawio # editable editor URL
```

The XML is `encodeURIComponent`-encoded, deflate-compressed, and base64'd
into the URL fragment — nothing is uploaded to the server.

## Diagram type quick-reference

| User says | Approach |
|---|---|
| "ER diagram", "schema diagram" | ERD: use cylinder for tables, diamond for relationships |
| "UML class diagram" | Boxes with `<<stereotype>>`, dashed arrows for dependencies |
| "Sequence diagram" | Lifelines (vertical lines), activation boxes, dashed return arrows |
| "Architecture diagram" | Swimlanes by tier, icons for services, orthogonal edges |
| "Flowchart", "decision tree" | Rectangles + diamonds + arrows, TB layout |
| "ML model", "neural network" | Layered nodes, directional edges, custom grouping |
