engineer-design-diagram
"Generate production-grade engineering design diagrams (architecture,\
Allowed Tools
Provided by Plugin
engineer-design-diagram
Generate production-grade engineering design diagrams (architecture, sequence, delta, drift) as self-contained dark-themed HTML files with accessible inline SVG. Grounds every diagram in real repo topology via DCI — package manifests, docker-compose, k8s, terraform, import graph.
Installation
This skill is included in the engineer-design-diagram plugin:
/plugin install engineer-design-diagram@claude-code-plugins-plus
Click to copy
Instructions
Engineer Design Diagram
Generates production-grade engineering design diagrams as single-file HTML with inline SVG, grounded in real repository topology. Credit: design palette + arrow-masking pattern inspired by Cocoon AI's architecture-diagram-generator (MIT). See THIRDPARTYLICENSES.md.
Overview
Most diagramming tools produce pretty pictures disconnected from reality. This skill does the opposite: it reads the actual repo (package manifests, docker-compose, k8s, terraform, import graph) and emits a diagram that reflects the real system. It also knows how the system changed — PR-diff mode highlights structural deltas, trace mode turns a stack/log into a sequence diagram, and drift mode detects when the architecture has wandered from a stored fingerprint.
Four modes share a common pipeline (DCI grounding → node/edge graph → template fill → fingerprint write). Output is a single self-contained HTML file that opens in any browser, plus a Mermaid text block for copy-paste into docs. Dark theme with semantic OKLCH color coding by component role. Accessible by default (ARIA, /, reduced-motion, keyboard navigation).
Layout Philosophy — pick the shape before you draw
Dense technical systems want to render wide. This is how Anthropic docs, Linear docs, and Vercel architecture pages present multi-component systems: a sticky left rail for context (nav, invariants, legend) and a generous main column for the diagram itself. Mimic that pattern when your content is dense, and use the simpler single-SVG hero when it isn't.
Two supported output shapes, one decision up front:
| Shape | Use when | Template |
|---|---|---|
| Single-SVG hero (classic) | ≤8 nodes, one-screen takeaway, no sub-grouping, no accompanying explanation needed | templates/base.html |
| Docs-layout page (widescreen) | ≥8 nodes, multiple planes/groupings/sub-blocks, want invariants + detail cards + legend alongside the diagram | templates/docs-layout.html |
Widescreen-first for docs-layout. Target min-width: 1024px; do not add mobile breakpoints for docs-layout output — it's architecture documentation, not a landing page. The diagram needs horizontal breathing room. On narrow viewports the diagram stage scrolls horizontally inside its card while the sidebar stays visible.
Hybrid rendering in docs-layout mode: HTML/CSS for all node cards (easier to maintain, free hover states, content edits don't trigger collision math), SVG overlay positioned absolutely over the node grid for arrows only. Arrows are the one place SVG still wins — fixed pixel coords, clean arrowheads, no brittle CSS-line math. Pure-SVG stays the default for the single-hero shape because the payoff of HTML flex doesn't materialize at small node counts.
Layout-decision signal: if during Step 2 the graph has any of — (a) more than one semantic lane/plane, (b) subcomponent lists of 4+ items per node, (c) the user asks for "docs page" / "architecture page" / references Anthropic/Linear/Vercel docs as exemplars — pick docs-layout. Otherwise stay with single-SVG.
See docs-layout.md for the full widescreen spec (grid geometry, design tokens, sidebar anatomy, arrow overlay placement, hover states).
Prerequisites
- Git repository (for generate/diff/watch modes)
- At least one of:
package.json,pyproject.toml,Cargo.toml,go.mod,docker-compose.yml,k8s/.yaml,terraform/.tf - Python 3.9+ (for
scripts/fingerprint.py) - A browser to view output
- Optional:
kubectl(cluster introspection),terraform(state parsing),jq(manifest parsing)
Environment Detection (DCI)
!git rev-parse --show-toplevel 2>/dev/null || echo "not a git repo"
!git rev-parse --short HEAD 2>/dev/null || echo "no-head"; git branch --show-current 2>/dev/null || echo "no-branch"
!ls package.json pyproject.toml Cargo.toml go.mod requirements.txt docker-compose.yml Dockerfile 2>/dev/null | head -10 || echo "no manifests"
!command -v jq >/dev/null 2>&1 && jq -r '.name,(.dependencies // {} | keys[]?)' package.json 2>/dev/null | head -20 || echo "no package.json / no jq"
!docker compose config --services 2>/dev/null | head -30 || echo "no docker-compose"
!find . -maxdepth 3 -type d \( -name k8s -o -name kubernetes -o -name manifests \) 2>/dev/null | head -5 || echo "no k8s dir"
!find . -maxdepth 3 -name '*.tf' 2>/dev/null | head -10 || echo "no terraform"
Instructions
Step 1: Mode Detection
Parse the first token of $ARGUMENTS:
| Invocation | Mode | Playbook |
|---|---|---|
/design:generate or empty |
generate | mode-playbooks.md#generate |
/design:diff |
diff | mode-playbooks.md#diff |
/design:trace |
trace | mode-playbooks.md#trace |
/design:watch |
watch | mode-playbooks.md#watch |
All modes share Steps 2-5. Mode-specific variations documented in the per-mode playbook.
Step 2: Build the Node/Edge Graph
Use the DCI block output + targeted reads to populate a working graph:
- Nodes from: docker-compose service names, k8s
kind: Deployment/Service/StatefulSet, terraform resource blocks, package manifest names (for standalone apps), detected binaries inbin/orcmd/. - Edges from: docker-compose
depends_on+ exposed ports, k8s Service selectors + NetworkPolicy, terraform resource references, import-graph via Grep (import.*from,require(,use crate::), exposed HTTP/gRPC routes. - Role classification per node using drawing-rules.md § Role inference. Defaults to
slate(external/unknown) when heuristics don't match. - Groups from: k8s namespaces, terraform modules, docker-compose networks, directory boundaries for monorepos.
For graphs with >50 nodes, fall back to Mermaid (see Step 3 template selection).
Step 3: Choose Template and Render
Apply the layout-selection rule from Layout Philosophy first, then pick the template for the chosen mode:
| Mode | Layout shape | Template | Output |
|---|---|---|---|
| generate / diff | single-SVG hero (simple graphs) | templates/base.html | Centered SVG on dark canvas, cards row below |
| generate / diff | docs-layout page (dense graphs) | templates/docs-layout.html | Two-column widescreen page: sticky sidebar + main column with diagram card + detail grid |
| diff (any shape) | — | selected template + delta classes | delta-added / delta-removed / delta-changed CSS markers on changed nodes/edges |
| trace | sequence | templates/sequence.html | Sequence diagram with lifelines and message arrows |
| watch | — | none — markdown drift report | Markdown only; no HTML render |
For single-SVG hero: fill placeholders per drawing-rules.md — color palette, SVG arrow-masking, z-order, 40px spacing, dashed boundaries, legend placement. Keep the grid , #020617 canvas, pulsing header dot (with reduced-motion guard).
For docs-layout page: fill placeholders per docs-layout.md — GitHub-inspired palette (#0f1117 / #161b22 / #1c2128), Inter + JetBrains Mono, 260px sticky sidebar, fixed-pixel node stage with SVG arrow overlay, hover states on node cards. No mobile breakpoints. Populate the sidebar with: (a) version badge, (b) "On this page" nav, (c) "Architectural invariants" list (surface up to 5 load-bearing constraints you inferred from the code/config — e.g. "Kernel owns durable state", "All ops return Result
If node count >50 OR the model signals layout failure (overlapping boxes, arrows crossing through nodes), switch to templates/mermaid-fallback.html regardless of layout shape.
Step 4: Update Fingerprint State
For generate/diff/watch modes, write structural state to ${CLAUDEPLUGINDATA}/arch-state.json (or ~/.claude-state/arch-state.json fallback if the env var is unset):
python3 ${CLAUDE_SKILL_DIR}/scripts/fingerprint.py write --input /tmp/graph.json
Schema documented in fingerprint-spec.md. Fingerprint persists across sessions so watch mode can detect drift.
Step 5: Validate and Open
Run the HTML validator before presenting output:
python3 ${CLAUDE_SKILL_DIR}/scripts/validate_html.py $CWD/.arch/<mode>-<timestamp>.html
Validator confirms: ARIA labels present, reduced-motion rule exists, no unexpected external script sources beyond Google Fonts. If validation fails, iterate on the template fill — don't ship an inaccessible diagram.
Open the result via ${CLAUDESKILLDIR}/scripts/openinbrowser.sh (OS-aware: xdg-open on Linux, open on macOS, wslview on WSL). Echo the Mermaid equivalent to the chat as a copy-pasteable text block.
Feedback Loop
- Run
validate_html.pyafter Step 5. - If ARIA or contrast checks fail → fix template fill → re-validate.
- If >50 nodes rendered as overlapping boxes → restart Step 3 with Mermaid fallback.
- (docs-layout only) If arrows cross non-endpoint nodes OR text overflows a node box → re-run layout math (see docs-layout.md § verification) before re-screenshotting. Don't eyeball it; collision math is cheap and catches what a thumbnail hides.
- Maximum 3 iterations before falling back to Mermaid and flagging for manual review.
Output
- generate / diff / trace modes: one HTML file at
$CWD/.arch/(self-contained, offline-capable, Google Fonts as the sole external dep) + one Mermaid text block echoed to chat.- .html - watch mode: markdown drift report with sections
Added,Removed,Changed, each line citing the source file that justified the delta. - All modes: updated fingerprint at
${CLAUDEPLUGINDATA}/arch-state.json.
Detailed output contracts in mode-playbooks.md.
Examples
Example 1 — Generate architecture view from a monorepo
Input:
/design:generate
Behavior: DCI auto-loads docker-compose.yml services (web, api, db, cache), classifies roles (frontend/backend/db/db), reads web/src/lib/api-client.ts for the HTTP edge to api, reads docker-compose.yml depends_on for api→db and api→cache edges. Fills templates/base.html, writes ~/.arch/generate-2026-04-19T12-00.html, writes fingerprint with 4 nodes + 3 edges.
Output excerpt (Mermaid block):
flowchart TB
web["Web Frontend"]:::frontend --> api["API Service"]:::backend
api --> db["Postgres"]:::db
api --> cache["Redis"]:::db
Example 2 — PR delta on a branch that adds Redis
Input:
/design:diff
Behavior: Loads prior fingerprint, re-runs DCI on working tree, computes set-diff. Renders architecture view with class="delta-added" on the cache node and the api→cache edge. Summary line: Added 1 node (cache), 1 edge (api→cache).
Example 3 — Sequence diagram from a Sentry event
Input:
/design:trace ./incidents/sentry-2026-04-18-payment-timeout.json
Behavior: Parses Sentry JSON (exception frames + transaction spans), infers 4 lifelines (checkout-api, payment-service, stripe-webhook-listener, fraud-check), renders sequence diagram with the timeout marked on the final arrow. No fingerprint write in trace mode.
Example 4 — Drift watch after a quiet sprint
Input:
/design:watch
Behavior: Loads prior fingerprint, re-runs DCI, diffs. Output:
## Drift report — 2026-04-19 vs 2026-04-12
### Added
- Node `recommendations-service` (backend) — source: docker-compose.yml:services.recommendations
- Edge `api` → `recommendations-service` — source: api/src/handlers/product.ts:44
### Removed
- Edge `api` → `legacy-search` — source: api/src/handlers/search.ts removed in f8a2c91
Edge Cases
- No package manifests: DCI returns empty. Ask the user to describe the system in prose, fall back to prompt-only generation without DCI grounding.
- >150 components: Hard cap at 150 rendered nodes. Overflow bucket labeled
… +N more; full list preserved in fingerprint. - Stack trace format unknown: Three parsers (Sentry JSON, OTel span, raw text). Unknown formats emit Mermaid-only sequence rather than failing.
- No
mainbranch for diff: Probeorigin/HEAD→main→master→trunk. If none found, fall back toHEAD~1. - Docker compose binary naming: Probe both
docker compose(modern) anddocker-compose(legacy). - ${CLAUDEPLUGINDATA} unset: Fallback chain
${CLAUDEPLUGINDATA}→${XDGSTATEHOME}/claude/arch→~/.claude-state/arch. - iOS Safari large-diagram rendering: Avoid SVG paths with >10k points per element; fall back to Mermaid for graphs that approach this limit.
- k8s manifests with CRDs: Role defaults to
slate(external/unknown) when no heuristic matches; document in the legend.
Error Handling
| Error | Cause | Solution |
|---|---|---|
not a git repo |
Running outside git | Init a repo or cd to one; DCI handles the empty case but diff/watch require git |
no manifests |
No package files found | Use prose-only mode; skill will ask user to describe the system |
fingerprint schema mismatch |
State file from older schema version | fingerprint.py refuses cross-version diff and emits baseline-restart guidance |
ARIA validation failed |
Template fill omitted / |
Re-fill with role-appropriate labels from accessibility.md |
overlapping boxes detected |
Too many nodes for SVG layout | Auto-switch to Mermaid fallback (node count >50 trigger) |
no diff base |
main/master/trunk all missing |
Use HEAD~1 as base, warn user in output |
kubectl not installed |
Live cluster introspection unavailable | Skip cluster overlay; diagram still renders from static manifests |
trace parser unknown format |
Input file matches no known schema | Emit Mermaid-only sequence with best-effort parsing, flag for user review |
Resources
- drawing-rules.md — color palette, z-order, arrow-masking, spacing, legend placement (single-SVG hero — Cocoon-AI-inspired patterns)
- docs-layout.md — widescreen two-column layout spec (grid geometry, design tokens, sidebar anatomy, HTML+SVG hybrid arrow overlay, verification math) — mirrors Anthropic / Linear / Vercel docs patterns
- mode-playbooks.md — per-mode workflows with inputs, steps, outputs
- fingerprint-spec.md — JSON schema for structural state + diff algorithm
- accessibility.md — ARIA patterns, reduced-motion, keyboard nav
- dci-block.md — DCI command catalog with output-size budgets
- troubleshooting.md — iOS Safari, large graphs, schema drift
- templates/base.html — single-SVG hero shell (≤8 nodes, simple graphs)
- templates/docs-layout.html — widescreen docs-page shell (≥8 nodes, planes, sub-groupings, detail cards)
- templates/sequence.html — sequence diagram variant (trace mode)
- templates/mermaid-fallback.html — Mermaid-only render for >50 nodes
- scripts/fingerprint.py — write / read / diff structural state
- scripts/validatehtml.py — ARIA + no-external-deps checker
- scripts/collectdci.sh — bounded DCI harvester for large repos
- scripts/openinbrowser.sh — OS-aware opener
- THIRDPARTYLICENSES.md — Cocoon-AI attribution + MIT notice
- examples/ — Cocoon-AI sample diagrams (web-app, aws-serverless, microservices) kept as visual reference
- External: Cocoon-AI/architecture-diagram-generator (inspiration source, MIT)
- External: Mermaid diagram syntax