What diagram-design actually is (and isn't)
The first thing to get straight about diagram-design is that it is not a layout engine. It does not parse anything, compile anything, or solve for node positions. There is no Dagre, no Graphviz, no TALA underneath it computing where boxes should land. It is an Agent Skill — and in this context that phrase means something precise: a system prompt plus a ruleset that constrains what a coding agent emits. Install it into Claude Code, Codex, Pi, or Factory Droid, and you have handed the model a design grammar, not a rendering backend.
What the model emits is a self-contained HTML document with inline SVG. Every coordinate is hardcoded. Every viewBox, every x, every y, every path d="..." was chosen by the language model during generation, in the same forward pass that decided what the diagram means. That is the whole trick, and it is also the whole risk. You have replaced a deterministic layout solver with next-token prediction over pixel offsets.
The payoff for that trade is aesthetic control, and the skill is opinionated about it. It carries roughly 39 layout grammars — architecture, loops, flywheels, Sankey, fishbone, Wardley maps, UML, database schemas, and more — each one a set of instructions about how a particular class of diagram should be structured spatially. Alongside those grammars sits an editorial design philosophy: controlled color palettes, no heavy shadows or gradients, strict visual hierarchy, and a stated target density of 4 out of 10. The skill literally tells the model that the highest-quality move is deletion. That constraint is the point. Mermaid's problem was never that it couldn't draw a box — it's that the auto-layout engines produce tangled edge routing and a generic, dated look the moment a system gets multi-tiered. Anyone who has watched a coding agent confidently emit a technically valid Mermaid flowchart with awkward crossings and default purple fills knows the frustration.
So the insight worth internalizing: diagram-design trades engine determinism for aesthetic control, and the LLM becomes the layout engine. That reframing predicts almost every downstream property. Aesthetic output can be publication-grade, because a model fluent in design vocabulary can place a label with intent. But the same model is now responsible for collision avoidance, edge routing, and coordinate sanity — jobs that algorithms do reliably and token prediction does not. Diagrams come out looking like someone designed them, and they come out different every run.
I'd reach for this when the diagram is the deliverable — a customer-facing architecture overview, a blog post, a pitch deck, an RFC summary. I would not reach for it when the diagram is a debug artifact that needs to be regenerated in CI without an LLM in the loop. Those are different tools solving different problems, and the skill is honest about which one it is.
How the 39 layout grammars work under the hood
The grammars are where the skill earns its keep, and it's worth being precise about what they are. They are not parser rules. Nothing validates your input against a schema or rejects a malformed graph. Each grammar is a block of instructions about where elements go in x/y space and how to draw the connecting geometry.
A Sankey grammar, for example, doesn't compute flow widths from data. It tells the model to calculate each path's stroke width proportional to the flow magnitude it was given, to align source and sink nodes on vertical rails, and to route the ribbons so they fan without overlapping. A fishbone grammar instructs the model to place a horizontal spine and then attach category bones at consistent angles, with cause labels offset perpendicular to each bone so text doesn't collide with the line. An architecture grammar dictates layer ordering — presentation above application above data, or whatever the spec implies — and enforces that boxes within a layer share a baseline. The model is being told how to lay out, not what to draw. The semantics come from your prompt; the spatial primitives come from the grammar.
That's the semantic decoupling worth naming. A trust boundary becomes a dashed enclosure placed at a specific offset from the nodes it contains. A write-back loop becomes a curved arc with an arrowhead, routed on the outside of the node cluster rather than through it. A dependency flow becomes a directional path with a controlled stroke weight. Meaning is encoded as geometry, and the grammar is the vocabulary for that encoding.
Why this works at all — and it does work, up to a point — is that small-to-medium diagrams have enough spatial slack. Twelve nodes on a canvas have many valid arrangements, and a model that's seen thousands of well-composed diagrams can pick one. The failure comes when slack runs out.
flowchart TD
P[Prompt spec: nodes, edges, semantics] --> G{Grammar selection}
G -->|layered tiers| A[Architecture grammar]
G -->|flow magnitudes| S[Sankey grammar]
G -->|cause categories| F[Fishbone grammar]
A --> C[Coordinate placement: x/y, viewBox bounds, density 4/10 check]
S --> C
F --> C
C --> E[Emit raw SVG paths, lines, text nodes]
E -.->|LLM iterates on geometry| C
C -.->|constraint violated: overflow or overcrowding| P
P -.->|refine spec, re-select grammar| G
The back-and-forth arrows matter. The model doesn't produce a diagram in one clean pass; it reasons about placement, emits geometry, notices (sometimes) that a label overflows, and adjusts. When the density check fails — too many nodes for the editorial constraint — the honest move is to push back to the prompt and ask for a spec reduction. Whether the model actually does that versus quietly jamming boxes together is where the aesthetics start to degrade.
Where nice diagrams start to break: the geometry failure modes
The math problem underneath all of this is simple to state and hard to escape. Dagre and TALA solve layout with algorithms — rank assignment, crossing minimization, coordinate refinement. They are deterministic and they scale. diagram-design hands that job to a language model doing next-token prediction over coordinate values. At small node counts the two produce comparable results. Past a threshold, they diverge hard.
The threshold is roughly 50 interconnected nodes. Below it, the model has enough spatial room to place things sensibly. Above it, you start seeing the failure modes stack up. Path crossings over text are the most visible: a cross-layer connection in a microservice diagram forces the model to route a line from the application tier down to a data store while a VPC boundary box sits in between, and the resulting <path> cuts straight through a node label. The model knew the semantic relationship; it just couldn't find a clean corridor in the coordinate space it had already committed to.
Coordinate hallucination compounds it. Because the SVG has a fixed viewBox and the model places text at hardcoded x/y, any miscalculation of string width means a label runs past the canvas edge or overlaps its neighbor. There's no collision detection to catch it. The density 4/10 rule, which keeps small diagrams elegant, is precisely what breaks under real enterprise architecture — 50-plus services, detailed IAM graphs, exhaustive entity-relationship diagrams all directly violate the low-density paradigm. The skill will either silently drop technical detail to preserve the aesthetic or let the canvas crumble visually. Neither is what you wanted from an architecture diagram.
Then there's iteration. In Mermaid, adding a node is one line and the engine re-lays out the whole canvas cleanly. Here, adding a node means the model must recalculate hardcoded pixel offsets across the entire document. In practice that produces one of two outcomes: a full redraw that breaks visual consistency with the previous version, or a patch job where the new box overlaps an existing one. And the git diff is brutal — a small spatial shift touches hundreds of lines of SVG coordinates, which makes peer review of diagram changes genuinely tedious.
The token cost is the quieter tax. Each diagram runs 1,500 to 4,000-plus output tokens, because you're emitting full HTML, CSS, and inline SVG rather than ten lines of declarative syntax. Iterating on a diagram inside an agentic session multiplies that, and it's latency and API spend that a mmdc compile step would never incur. I'd plan for the fact that re-running the same prompt yields subtly different coordinates every time — fine for a one-off deck, painful if you need reproducible artifacts.
None of this makes the tool bad. It makes it a tool with a specific operating envelope, and the discipline is staying inside it.
Tokens, diffs, and the deep tradeoff against Mermaid and D2
Here's the number that should anchor every adoption decision: a 30-node Mermaid diagram is about fifteen lines of text. The same diagram through diagram-design is 1,500 to 4,000 output tokens of HTML, CSS, and inline SVG. You are paying two orders of magnitude more generation cost for the same semantic content, and you're paying it in the currency that matters most inside an agentic session — latency and context.
The asymmetry gets worse the moment you need to change something. Adding a node to a Mermaid graph is one line, and Dagre re-lays out the entire canvas cleanly, because the layout was never stored — it was computed. Adding a node to a diagram-design artifact means the model has to recalculate hardcoded pixel offsets across the whole document. In practice you get a full redraw that breaks visual consistency with the version you already approved, or a patch where the new box lands on top of an existing one. There is no third option, because there is no solver to fall back on.
Determinism is the deeper fault line. Mermaid's Dagre and D2's TALA are deterministic: same input, same layout, every time, no LLM in the loop. diagram-design is stochastic. Re-run the identical prompt and you get different coordinates, slightly different spacing, occasionally a different node hierarchy. For a one-off slide that's invisible. For an artifact you need to reproduce in CI, it's disqualifying — you cannot diff two runs and expect the geometry to match, because the geometry was never derived, it was predicted.
The git noise is where maintainability actually dies. A small spatial shift in an SVG touches hundreds of line-changed entries, because path data, transform matrices, and text anchors all move by a few pixels together. A reviewer opening that diff sees a wall of coordinate churn and no way to tell whether the semantics changed or the boxes just slid forty pixels left. In Mermaid, the diff is the semantics — you see the node added, the edge removed, and nothing else. That property is worth more than aesthetics in any repo where the diagram is reviewed like code.
D2 sits in an interesting middle. It gives you a real layout engine with far better edge routing than Dagre, keeps the clean text diff, and stays deterministic — but it requires installing the D2 binary and learning a syntax that isn't natively rendered by every markdown viewer. That's a real adoption tax, and it's why Mermaid still wins on pure ubiquity despite the tangled routing.
| Dimension | diagram-design |
Mermaid / PlantUML | D2 | Eraser / Excalidraw |
|---|---|---|---|---|
| Output format | Self-contained HTML + inline SVG | DSL rendered via JS/WASM | SVG/PNG compiled from DSL | JSON / canvas / SVG |
| Aesthetic ceiling | High — editorial, publication-grade | Low–medium, generic and dated | Medium–high, polished | High — hand-drawn or modern UI |
| Tooling dependency | Zero runtime; browser-native | Markdown renderer or Mermaid engine | D2 CLI / compiler | Web app or canvas renderer |
| Git diff maintainability | Low — raw SVG coordinates churn per edit | High — compact 5-line text diffs | High — human-readable DSL | Medium |
| Layout determinism | Variable — LLM-placed coordinates | Deterministic — engine computes layout | Deterministic — TALA engine | Semi-manual |
The honest summary: if the diagram needs to live in a repo and evolve, diagram-design is the wrong tool, and no amount of visual polish compensates for a diff nobody can review. If the diagram needs to be regenerated without an LLM in the pipeline, it's also the wrong tool, because there is no mmdc-equivalent compile step — generation is the LLM call. Reach for it when the artifact is terminal: rendered once, presented, and never edited again.
Where it shines and where to never use it
The rule I'd draw is this: if the diagram is a deliverable, diagram-design wins; if it's infrastructure, Mermaid or D2 wins. A deliverable is a thing you produce once and present — a customer-facing architecture overview, a pitch deck slide, a blog post figure, an RFC summary where a single static image carries the argument. The aesthetic ceiling is the entire point of those artifacts, and the fact that the geometry isn't reproducible doesn't matter because you're not going to reproduce it.
Infrastructure is the opposite. A repo diagram that gets edited every time a service is added is infrastructure, and its value is in being cheap to change and easy to review. Same for CI-generated schemas, auto-updated dependency graphs, and anything that has to rebuild identically on someone else's machine. Hand those to diagram-design and you've optimized the one property — how it looks — that nobody maintains.
There's a subtler constraint worth naming: the workflow is one diagram per prompt. That means there is no automation story. You can't hand it a config describing ten diagrams and get ten consistent outputs, because every output is a fresh generation with fresh coordinates. A page of related figures won't share a visual system unless you re-supply the same style instructions and accept that spacing will drift between them.
Then there's the embedding problem, which trips people up after they've generated something beautiful. GitHub and GitLab strip raw HTML and inline SVG in markdown for security, so a self-contained HTML diagram does not render in a README. To get it in front of people you either screenshare the standalone page, or you stand up a rasterization step — headless Chromium or Puppeteer screenshotting the HTML to PNG or WebP — and commit the image instead. That pipeline is entirely reasonable, and I'd plan for it from day one rather than discovering it at commit time. But it also means the source of truth becomes the prompt and the generated HTML in a dedicated diagrams folder, not an inline block of markdown.
stateDiagram-v2
[*] --> RawHTMLSVG: agent emits self-contained HTML + inline SVG
RawHTMLSVG --> StrippedByGitHub: embedded inline in markdown
StrippedByGitHub --> [*]: blocked, nothing renders
RawHTMLSVG --> Rasterized: headless Chromium / Puppeteer screenshot
Rasterized --> EmbeddablePNG: PNG or WebP committed to repo
EmbeddablePNG --> [*]
RawHTMLSVG --> StandalonePage: served as an .html artifact
StandalonePage --> [*]: viewable, not diffable as code
RawHTMLSVG --> Reprompted: user asks agent to add or move a node
Reprompted --> RawHTMLSVG: new coordinates, breaks visual consistency with prior version
The Reprompted loop is the one to internalize. Editing always returns you to raw geometry, and the new version will not align with the one you already shipped. If your workflow can tolerate that, you get the best-looking diagrams any coding agent will produce. If it can't, you're better served by a text DSL and a deterministic engine — and the ugliness you were trying to escape was never the real problem anyway.
The operational checklist your team needs
The first thing to internalize is that diagram-design is not a tool you install and invoke. There is no binary, no diagram-design build -i spec.md -o out.svg, no deterministic compile step you can drop into a Makefile. It is a workflow — an agent skill plus a set of conventions you have to build around it — and teams that treat it like a CLI discover this the hard way when they try to wire it into a pipeline and find there's nothing to call. Every generation requires an active LLM execution. That single fact shapes everything downstream.
The asset pipeline is the first thing to stand up, ideally before you generate a hundred artifacts you can't embed anywhere. Since the output is a self-contained HTML file with inline SVG, and GitHub and GitLab strip raw HTML in markdown, you need a rasterization step — headless Chromium or Playwright or Puppeteer loading the .html and screenshotting to WebP or PNG at the resolution you actually need. I'd build that early and treat it as the real deliverable format, because the HTML is an intermediate artifact and the image is what ships.
Then the source-of-truth convention. The generated HTML has hardcoded coordinates and no meaningful diff, so it is not the thing you maintain — the prompt spec is. Keep the specs and the generated .html files together in a dedicated /docs/diagrams/ folder rather than pasting raw SVG into markdown, and treat the prompt as the editable source and the HTML as build output you can regenerate (with drift) on demand.
Human review is not optional here. Before anything gets committed, someone has to open the rendered output and look for text overflowing the viewBox, labels colliding with edges, and connections that vanished during generation. None of that is caught by a linter, because there is no linter — the model is the only thing standing between you and a mangled diagram, and it doesn't always catch its own mistakes.
Dark mode is the sneaky one. The skill emits static inline colors from whatever palette it chose, so unless the generation explicitly handled prefers-color-scheme, your diagram will look fine in light mode and unreadable in dark. If your docs site switches themes, plan to generate a variant per mode or accept that the diagram only works in one.
And CI is where the abstraction leaks hardest. A mmdc compile runs deterministically with no model in the loop; regenerating a diagram-design artifact always means spending tokens and latency on an LLM call, with different coordinates every run. Plan your pipeline for that, or don't put it in the pipeline at all.
Wrapping up: the aesthetic it buys you and the maintenance it costs
My verdict is narrow and I'll state it plainly: diagram-design is the right call when you would never edit the diagram again, and the wrong call the moment the diagram becomes a living document. Every mechanic covered above points at the same conclusion. The aesthetic ceiling is real — an editorial, publication-grade figure that no auto-layout engine will match — but it's bought with stochastic geometry, hardcoded coordinates, hundred-line diffs, and a generation cost two orders of magnitude above a few lines of DSL. Those are acceptable taxes on a terminal artifact and unacceptable taxes on infrastructure.
So the discipline is refusing to blur the two. The diagrams you maintain — service topologies that change when a service is added, CI-generated schemas, anything that has to rebuild identically on a teammate's machine — belong in Mermaid or D2, where the diff is the semantics and the layout is computed. The diagrams with an audience — the customer-facing architecture overview, the pitch deck slide, the blog figure, the RFC summary where the image carries the argument — are where you spend the tokens and accept the drift. The hybridization I'd actually recommend to a team is exactly that split: a deterministic text DSL for everything internal and churning, diagram-design reserved for the surface that people outside the team actually look at.
If you want to test whether it fits your stack, the honest way is a scoped proof of concept rather than a wholesale migration. Pick one artifact with a real audience — a single architecture overview for a service you already understand well — and take it end to end: the prompt spec, the generation, the rasterization step, the review pass, the commit. What you're really measuring isn't the finished image, which will probably look genuinely good. You're measuring the friction around it — whether your team will tolerate a pipeline where the source of truth is a prompt, whether the review step gets skipped under deadline, whether the coordinate drift between runs bothers the people reviewing the diff. Run the same PoC through Mermaid for a second artifact and compare the total cost honestly. I'd bet the tiny scoped task makes the split obvious: one tool for things that live and change, the other for the thing you present once and move on from. Understand that boundary before you standardize on either, and you'll pick correctly for the right reasons instead of the prettiest one.
Resources
Updated 2026-09-08 by Mehran Mozaffari.
Related posts
5 September 2026
Ripwire: A Deterministic Call-Graph Primer for Coding Agents
3 September 2026
FFmpeg Skill: The Deterministic Control Plane for Media-Specific AI Agents
27 August 2026
Herdr Keeps Coding Agents Running Across Lids, Reboots, and SSH Hops: How the Client-Server Split Actually Works
27 August 2026
Stringing Skills Together: A Field Guide to Jeffrey's Skills.md (jsm)
27 August 2026
The Standard of Completion: How Factory's Three-Role Agent System Rebuilt gdal to 90 Percent Parity
21 August 2026
The Boss Sign-Off Gate: What agency-agents-zh's Orchestrator Actually Gets Right and Wrong About Human Checkpoints
