# Diagramming

> Render diagrams from text with Mermaid, Graphviz DOT, or D2: syntax, layout, and the CLI calls that produce images.

- Skill: `kohaku-lab/diagramming` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kohaku-lab/diagramming`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kohaku-lab/diagramming/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: kohaku-lab (https://skillmd.com/u/kohaku-lab)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kohaku-lab/diagramming

---


You are a visual thinker. Before you write syntax, you decompose the
problem into nodes, edges, containers, and layout intent. Then you pick
the right tool and emit clean source.

## Tool Selection

| Use case                                   | Tool     | Why                                         |
|--------------------------------------------|----------|---------------------------------------------|
| Flow / sequence / state in Markdown docs   | Mermaid  | Renders inline on GitHub, Notion, Obsidian. |
| Dense graphs, strict layout control        | Graphviz | Best layered/ranked layout; fine-grained.   |
| Architecture, containers, modern look      | D2       | Clean syntax, great containers and themes.  |
| Quick sketch, no render tools available    | Mermaid  | Easiest to preview in browser or docs.      |
| Deep auto-layout with many nodes/edges     | Graphviz | `dot`/`neato`/`fdp` are battle-tested.      |
| Nested systems / grouping by domain        | D2       | Containers are first-class.                 |

Default: emit a fenced code block. Users paste into their renderer. Only
go to local files when the user explicitly wants an SVG/PNG artifact.

## Mermaid Reference

Flowchart:
```mermaid
flowchart LR
  A[User] --> B{Authenticated?}
  B -- yes --> C[Dashboard]
  B -- no  --> D[Login]
  D --> B
```

Sequence:
```mermaid
sequenceDiagram
  autonumber
  participant U as User
  participant A as API
  participant DB as DB
  U->>A: POST /login
  A->>DB: SELECT user
  DB-->>A: row
  A-->>U: 200 + token
```

Class:
```mermaid
classDiagram
  class Agent {
    +id: str
    +run() None
  }
  class Tool
  Agent "1" o-- "*" Tool
```

State:
```mermaid
stateDiagram-v2
  [*] --> Idle
  Idle --> Running: start
  Running --> Idle: done
  Running --> Error: fail
  Error --> Idle: reset
```

ER:
```mermaid
erDiagram
  USER ||--o{ SESSION : has
  USER {
    uuid id
    string email
  }
  SESSION {
    uuid id
    uuid user_id
    timestamp created_at
  }
```

Gantt:
```mermaid
gantt
  title Launch plan
  dateFormat  YYYY-MM-DD
  section Build
  API        :a1, 2026-04-01, 14d
  Frontend   :a2, after a1, 10d
  section Ship
  Beta       :b1, after a2, 7d
```

## Graphviz (DOT) Reference

```dot
digraph G {
  rankdir=LR;
  node [shape=box, style=rounded, fontname="Inter"];
  edge [color="#555"];

  user  [label="User"];
  api   [label="API"];
  db    [label="Postgres", shape=cylinder];

  user -> api [label="HTTPS"];
  api  -> db  [label="SQL"];
}
```

Clusters (subgraphs named `cluster_*`):

```dot
digraph sys {
  rankdir=TB;
  subgraph cluster_web {
    label="Web tier"; style=dashed;
    nginx; app;
  }
  subgraph cluster_data {
    label="Data tier"; style=dashed;
    pg [label="Postgres"]; redis;
  }
  nginx -> app;
  app -> pg;
  app -> redis;
}
```

Useful knobs: `rankdir=LR|TB`, `splines=ortho|curved`, `concentrate=true`,
`node [shape=box|ellipse|diamond|cylinder|folder|note]`, `{rank=same; a b c;}`.

## D2 Reference

Containers and shapes:
```d2
users: User
api: API {
  shape: hexagon
}
db: Postgres {
  shape: cylinder
}
users -> api: HTTPS
api -> db: SQL
```

Nested / grouped:
```d2
web: Web tier {
  nginx
  app
}
data: Data tier {
  pg: Postgres {
    shape: cylinder
  }
  redis
}
web.app -> data.pg
web.app -> data.redis
web.nginx -> web.app
```

Styling:
```d2
svc: Service {
  style: {
    fill: "#1e293b"
    stroke: "#7aa2f7"
    stroke-width: 2
    border-radius: 8
  }
}
```

## Environment Setup

### Default: no install needed
Emit a fenced code block and stop. GitHub, GitLab, Obsidian, Notion, and
mermaid.live render Mermaid directly. Graphviz source pastes into
dreampuf.github.io/GraphvizOnline. D2 source pastes into play.d2lang.com.

### When the user wants a local artifact
Check what's available:
```bash
node --version       # for mermaid-cli
dot -V               # for graphviz
d2 --version         # for d2
```

Then install only what's missing.

Mermaid CLI (needs node):
- Install: `npm install -g @mermaid-js/mermaid-cli`
- Render: `mmdc -i diagram.mmd -o diagram.svg`
- Other formats: `-o diagram.png`, `-o diagram.pdf`.

Graphviz:
- macOS: `brew install graphviz`
- Debian / Ubuntu: `sudo apt install graphviz`
- Arch: `sudo pacman -S graphviz`
- Windows: `winget install Graphviz.Graphviz`
- Fedora: `sudo dnf install graphviz`
- Render: `dot -Tsvg diagram.dot -o diagram.svg`
  (also `-Tpng`, `-Tpdf`; engines: `dot`, `neato`, `fdp`, `circo`, `twopi`).

D2:
- macOS: `brew install d2`
- Linux / Windows: see https://d2lang.com (install script or binary).
- Render: `d2 diagram.d2 diagram.svg`
- Watch mode: `d2 --watch diagram.d2 diagram.svg`.

### Fallback when nothing is installed
You can always write a valid `.mmd`, `.dot`, or `.d2` file with `write`
and point the user at an online renderer. Do not block on missing tools.

## Workflow

1. Restate the system in your own words. What are the entities? What are
   the relations? What's the axis of the story (flow, time, structure)?
2. Pick the tool: Mermaid for docs/quick, Graphviz for dense/controlled,
   D2 for containers/modern.
3. Sketch nodes and edges on paper (mentally). Decide direction (`LR` vs
   `TB`) and any grouping.
4. Write the source. Keep labels short. Group related nodes into
   clusters / containers. Name nodes with stable ids.
5. If rendering locally, render once and check: readability, crossings,
   whether the eye lands on the right node first.
6. Offer variants on request: same graph in a different tool, different
   direction, simplified vs detailed.

## Style Notes

- Fewer nodes beats more nodes. If it doesn't fit on one screen, it
  doesn't fit in one diagram.
- Choose one primary direction (`LR` or `TB`) and stick with it.
- Label edges only when the label adds information the reader can't
  infer. "calls" on every arrow is noise.
- Group by domain, not by layer, when both are options.
- Reserve color for emphasis, not decoration. Two accent colors max.
- Shapes carry meaning: cylinder = datastore, hexagon = service,
  diamond = decision, note = annotation. Be consistent within a diagram.
- Prefer orthogonal edges (`splines=ortho` in Graphviz) for systems
  diagrams; curves for organic/relational diagrams.
- For sequence diagrams, cap at ~6 participants; split the flow if you
  need more.

