| name | diagram |
| description | Generate interactive HTML diagrams (flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, Gantt charts, etc.) using Mermaid.js. Opens the result in the browser. Use when the user says "/diagram", "draw a flowchart", "make a diagram", "show me a flow", "sequence diagram", "class diagram", "state diagram", or any request for a visual diagram.
|
| args | [{"name":"args","type":"string","description":"Description of the diagram to generate. Can be natural language (\"the auth flow\") or raw Mermaid syntax. Optional flags: --title \"Custom Title\", --theme dark|light.\n"}] |
Diagram Skill Invoked
User has requested: /diagram {{args}}
Steps
1. Parse arguments
Parse {{args}} into:
2. Determine diagram type and generate Mermaid syntax
Based on the description, choose the appropriate Mermaid diagram type:
| User intent | Mermaid type |
|---|
| Flow, process, pipeline, steps | flowchart TD or flowchart LR |
| Sequence, interaction, API calls | sequenceDiagram |
| Class, object model, schema | classDiagram |
| State machine, lifecycle | stateDiagram-v2 |
| Entity relationship, data model | erDiagram |
| Timeline, schedule | gantt |
| Git branching | gitgraph |
| Mindmap, brainstorm | mindmap |
| Pie/donut breakdown | pie |
If the description IS already valid Mermaid syntax (starts with a known diagram keyword), use it directly.
Otherwise, translate the natural language description into valid Mermaid syntax. Guidelines:
- Keep node labels concise (3-5 words max)
- Use meaningful node IDs (not A, B, C — use
auth_check, validate_input, etc.)
- Add descriptive edge labels where they clarify the flow
- Group related nodes with
subgraph when there are logical clusters
- For flowcharts: use standard shapes (rounded
(), diamond {}, etc.)
3. Generate the HTML file
Create a slug from the title: lowercase, spaces to hyphens, strip non-alphanumeric.
Output path: ~/.claude/diagrams/<slug>.html
If a file with the same slug already exists, append a numeric suffix (-2, -3, etc.).
Write the HTML file using the Write tool. The file must be fully self-contained with:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{title}}</title>
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #0f1117; color: #e2e8f0;
display: flex; flex-direction: column; align-items: center;
min-height: 100vh; padding: 2rem 1rem;
}
h1 { font-size: 1.4rem; margin-bottom: 1.5rem; color: #f8fafc; }
.diagram-container {
background: #1e2330; border-radius: 12px; padding: 2rem;
max-width: 95vw; overflow-x: auto;
box-shadow: 0 4px 24px rgba(0,0,0,0.4);
}
.controls {
margin-top: 1.5rem; display: flex; gap: 0.75rem; align-items: center;
}
.controls button {
padding: 0.4rem 1rem; border-radius: 6px; border: 1px solid #4a5568;
background: #2d3748; color: #e2e8f0; cursor: pointer; font-size: 0.85rem;
}
.controls button:hover { background: #4a5568; }
.meta { margin-top: 1rem; font-size: 0.75rem; color: #64748b; }
body.light {
background: #f8fafc; color: #1e293b;
}
body.light h1 { color: #0f172a; }
body.light .diagram-container {
background: #ffffff; box-shadow: 0 4px 24px rgba(0,0,0,0.08);
}
body.light .controls button {
background: #e2e8f0; color: #1e293b; border-color: #cbd5e1;
}
body.light .controls button:hover { background: #cbd5e1; }
body.light .meta { color: #94a3b8; }
</style>
</head>
<body{{BODY_CLASS}}>
<h1>{{title}}</h1>
<div class="diagram-container">
<pre class="mermaid">
{{MERMAID_SYNTAX}}
</pre>
</div>
<div class="controls">
<button onclick="zoomIn()">+ Zoom</button>
<button onclick="zoomOut()">- Zoom</button>
<button onclick="resetZoom()">Reset</button>
<button onclick="toggleTheme()">Toggle Theme</button>
<button onclick="exportSVG()">Export SVG</button>
</div>
<div class="meta">Generated by Claude Code · {{DATE}}</div>
<script>
mermaid.initialize({
startOnLoad: true,
theme: document.body.classList.contains('light') ? 'default' : 'dark',
themeVariables: document.body.classList.contains('light') ? {} : {
primaryColor: '#6366f1',
primaryTextColor: '#f8fafc',
primaryBorderColor: '#818cf8',
lineColor: '#94a3b8',
secondaryColor: '#1e2330',
tertiaryColor: '#2d3748',
background: '#1e2330',
mainBkg: '#2d3748',
nodeBorder: '#6366f1',
clusterBkg: '#1a1f2e',
clusterBorder: '#4a5568',
titleColor: '#f8fafc',
edgeLabelBackground: '#1e2330',
},
flowchart: { curve: 'basis', padding: 20 },
sequence: { mirrorActors: false },
});
let scale = 1;
const container = document.querySelector('.diagram-container');
const svg = () => container.querySelector('svg');
function zoomIn() {
scale = Math.min(scale + 0.2, 3);
if (svg()) svg().style.transform = `scale(${scale})`;
}
function zoomOut() {
scale = Math.max(scale - 0.2, 0.3);
if (svg()) svg().style.transform = `scale(${scale})`;
}
function resetZoom() {
scale = 1;
if (svg()) svg().style.transform = `scale(1)`;
}
function toggleTheme() {
document.body.classList.toggle('light');
const el = document.querySelector('.mermaid');
const code = el.getAttribute('data-original') || el.textContent;
el.setAttribute('data-original', code);
el.removeAttribute('data-processed');
el.innerHTML = code;
mermaid.initialize({
startOnLoad: false,
theme: document.body.classList.contains('light') ? 'default' : 'dark',
});
mermaid.run({ nodes: [el] });
scale = 1;
}
function exportSVG() {
const s = svg();
if (!s) return;
const blob = new Blob([s.outerHTML], { type: 'image/svg+xml' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = '{{SLUG}}.svg';
a.click();
URL.revokeObjectURL(a.href);
}
</script>
</body>
</html>
Template variables to fill:
{{BODY_CLASS}}: class="light" if theme is light, empty string if dark
{{title}}: the diagram title
{{MERMAID_SYNTAX}}: the generated Mermaid code (properly indented, no HTML-special chars unescaped)
{{DATE}}: today's date in YYYY-MM-DD format
{{SLUG}}: the filename slug (for SVG export filename)
Important: Escape any <, >, & in node labels to their HTML entities within the Mermaid block.
4. Open in browser
if [[ "$OSTYPE" == darwin* ]]; then
open "<output_path>"
elif [[ "$OSTYPE" == msys* || "$OSTYPE" == cygwin* || -n "${WINDIR:-}" ]]; then
start "" "<output_path>"
else
xdg-open "<output_path>" 2>/dev/null || echo "Open manually: <output_path>"
fi
5. Report
Print:
Diagram written to <output_path>
Then show the Mermaid source in a fenced code block so the user can iterate:
```mermaid
<the mermaid syntax>
```
If the user wants changes, edit the existing HTML file — don't create a new one.