Install
$ agentstack add skill-jonmagic-skills-d2-diagrams Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Pipes remote content directly into a shell (remote code execution).
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
D2 Diagrams
Create, modify, and render diagrams using the D2 declarative diagramming language.
Overview
D2 (Declarative Diagramming) is a text-to-diagram scripting language. You write what you want diagrammed, and the D2 CLI generates SVG or PNG images. This skill covers:
- Installing the D2 CLI
- Writing D2 source files (
.d2) - Rendering diagrams to SVG/PNG
- All D2 features: shapes, connections, containers, SQL tables, UML classes, sequence diagrams, grid diagrams, icons, themes, styles, variables, globs, layers, scenarios, and steps
When to Use
- User asks to create or modify any kind of diagram
- Architecture diagrams, system designs, network topologies
- Entity-relationship diagrams (ERDs) with SQL tables
- UML class diagrams
- Sequence diagrams for API flows or protocols
- Flowcharts and process diagrams
- Grid layouts for dashboards or comparison tables
- Any request mentioning "d2", "diagram", "visualize", "draw", "architecture"
Prerequisites: Installing D2
Before creating diagrams, verify D2 is installed:
d2 version
If not installed, install using one of these methods:
macOS (Recommended: Homebrew)
brew install d2
Any platform (Install script)
curl -fsSL https://d2lang.com/install.sh | sh -s --
From source (requires Go 1.20+)
go install oss.terrastruct.com/d2@latest
Verify installation
d2 version
Workflow
Step 1: Write D2 Source
Create a .d2 file with the diagram definition. Use the language reference in references/D2_LANGUAGE_REFERENCE.md for syntax details.
Step 2: Render the Diagram
# Render to SVG (default, with padding)
d2 --pad=40 input.d2 output.svg
# Verify width is reasonable ( b: forward
b b: bidirectional
a -- b: undirected
# Chaining
a -> b -> c -> d
# Repeated connections create parallel edges
a -> b: first
a -> b: second
Containers (Nesting)
server: Backend Server {
api: REST API
db: Database {shape: cylinder}
api -> db: queries
}
Styles
x: Shape {
style: {
fill: "#f0f0f0"
stroke: "#333333"
stroke-width: 2
stroke-dash: 5
border-radius: 8
shadow: true
opacity: 0.9
font-size: 16
font-color: "#000"
bold: true
italic: false
animated: true
3d: true
multiple: true
double-border: true
fill-pattern: dots
}
}
Icons
server: Backend {
icon: https://icons.terrastruct.com/essentials%2F112-server.svg
}
# Standalone icon shape
github: GitHub {
shape: image
icon: https://icons.terrastruct.com/dev%2Fgithub.svg
}
SQL Tables
users: {
shape: sql_table
id: int {constraint: primary_key}
name: varchar(255)
email: varchar(255) {constraint: unique}
created_at: timestamp
}
Sequence Diagrams
shape: sequence_diagram
alice -> bob: Hello
bob -> alice: Hi back
alice -> bob: How are you?
bob -> alice: Good, thanks!
Grid Diagrams
grid: {
grid-rows: 2
grid-columns: 3
cell1: A
cell2: B
cell3: C
cell4: D
cell5: E
cell6: F
}
Variables
vars: {
primary-color: "#4A90D9"
server-icon: https://icons.terrastruct.com/essentials%2F112-server.svg
}
server: Backend {
icon: ${server-icon}
style.fill: ${primary-color}
}
Globs (Global Patterns)
# Style all shapes
*.style.fill: "#f0f0f0"
*.style.border-radius: 8
# Style all connections
(* -> *)[*].style.stroke-dash: 3
# Recursive glob
**.style.font-size: 14
Direction
direction: down # Recommended default — narrower diagrams
# Options: up, down, left, right
# Use 'right' only for explicitly horizontal flows (timelines, pipelines)
a -> b -> c
Themes
Use d2 themes to list available themes. Common theme IDs:
0- Default1- Neutral default3- Mixed berry blue4- Grape soda5- Aubergine6- Colorblind clear8- Vanilla nitro cola100- Origami200- Dark Mauve (terminal-style)300- Terminal (dark, monospace, caps)301- Terminal Grayscale302- Retro
Dark themes:
200- Dark Mauve201-208- Various dark themes
Composition (Multi-board)
# Root board
a -> b
# Layers (independent boards)
layers: {
detail: {
x -> y -> z
}
}
# Scenarios (inherit from base)
scenarios: {
error: {
a.style.fill: red
a -> c: error path
}
}
# Steps (each inherits from previous)
steps: {
step1: {
a -> b
}
step2: {
b -> c
}
}
Classes (Reusable Styles)
classes: {
server: {
shape: rectangle
style: {
fill: "#dceefb"
stroke: "#4A90D9"
border-radius: 8
}
}
database: {
shape: cylinder
style: {
fill: "#e8f5e9"
stroke: "#66bb6a"
}
}
}
api: API Server {class: server}
db: PostgreSQL {class: database}
api -> db
Arrowheads
a -> b: {
source-arrowhead: {
shape: diamond
}
target-arrowhead: {
shape: arrow
label: "1..*"
}
}
# Arrowhead shapes: triangle, arrow, diamond, circle, cf-one, cf-one-required, cf-many, cf-many-required
Markdown and Code in Labels
explanation: |md
# Architecture Overview
- **Frontend**: React SPA
- **Backend**: Go microservices
- **Database**: PostgreSQL
|
code_block: |go
func main() {
fmt.Println("Hello")
}
|
Width Control
Diagram width is the most common problem. D2's dagre layout places sibling nodes side-by-side, so diagrams easily exceed screen width. **Always target b -> c`) instead of declaring them as siblings.
- After every render, verify the SVG width. D2 doesn't warn about wide output:
``bash # Check viewBox width (first number after "0 0" is width) rg -o 'viewBox="0 0 ([0-9]+)' -r '$1' output.svg ``
The Container Width Problem
Nested containers with multiple children are the #1 source of width explosion. Dagre lays out children horizontally within a container, so a container with 4 children produces 4 columns of width.
Bad — 4 children side-by-side, very wide:
services: Backend {
api: API Gateway
auth: Auth Service
core: Core API
worker: Worker
}
Better — use the "titled container + transparent markdown child" pattern. The container label acts as the heading with proper border-radius, and a single invisible child holds markdown body text:
services: Backend Services {
style.fill: "#e8f5e9"
style.stroke: "#4caf50"
style.border-radius: 10
details: |md
- API Gateway (:3000)
- Auth Service (JWT)
- Core API (business logic)
- Background Worker (cron)
| {
style.fill: transparent
style.stroke: transparent
}
}
This pattern keeps the rounded-corner container visual while collapsing all content into a single narrow box.
Markdown Labels and border-radius
Gotcha: When a node's label is markdown (|md ... |), D2 renders the content inside a foreignObject and the SVG ` gets rx="0" — meaning **border-radius is ignored on the outer shape** even if set via class or inline style. Plain-text labels render border-radius` correctly.
Workaround: Use the titled container pattern above. The parent container uses a plain-text label (which gets proper border-radius), and the markdown goes in a transparent child node inside it.
Sequence Diagram Width
Sequence diagram width is proportional to actor count and cannot be controlled by direction or layout. The only way to reduce width is to merge related actors:
# Wide — 5 actors
shape: sequence_diagram
user: User
ios: iOS App
llm: On-Device LLM
server: Server
db: Database
# Narrower — 3 actors (merge ios+llm, server+db)
shape: sequence_diagram
user: User
ios: iOS (App + LLM)
server: Server (+ DB)
Other Width Tactics
- Shorten labels. Every character counts. Use abbreviations.
- Use
--pad=40to add breathing room without changing layout width. - Chain nodes linearly (
a -> b -> c) to force dagre to stack them vertically rather than placing them side-by-side. - If a diagram is still too wide after all optimizations, split it into two diagrams rather than fighting the layout engine.
Known Gotchas
@prefix is D2 import syntax. Labels like@github/copilot-sdkor@MainActorwill be interpreted as imports. Wrap in quotes or rephrase:"@github/copilot-sdk"or justCopilot SDK.- Sequence diagrams don't support
styleblocks on connections. Unlike regular diagrams, you cannot style individual arrows in a sequence diagram — the render will fail. Remove anystyle.stroke,style.stroke-width, etc. from sequence diagram connections. - Markdown labels lose
border-radiuson the outer SVG rect (see Width Control above). - Dagre layout is non-deterministic for peer nodes. Re-rendering the same
.d2file can produce slightly different widths. Always verify after re-rendering.
Best Practices
- Use meaningful keys:
api_servernotbox1. Keys become default labels. - Default to
direction: down: Vertical layouts fit screens better. Only userightfor explicitly horizontal flows (timelines, pipelines). - Use the titled container + transparent md child pattern: For nodes that need both rounded corners and rich content (see Width Control section).
- Use classes for consistency: Define reusable styles with
classes:. - Use globs for defaults: Set
*.style.border-radius: 8instead of styling each shape. - Use variables for colors: Define a palette in
vars:for easy theme changes. - Use icons: Add icons from https://icons.terrastruct.com for professional diagrams.
- Choose the right layout:
dagre(default) for hierarchical,elkfor complex graphs. - Keep it readable: Use nested syntax and indentation for complex diagrams.
- Use composition: Split complex diagrams into layers, scenarios, or steps.
- Always render with
--pad=40: Gives diagrams breathing room. Default padding is too tight. - Verify width after every render: Check the SVG viewBox. Target <1400px for laptop screens.
Rendering Tips
- Always use
--pad=40for comfortable whitespace around diagrams. The default is too tight. - Always verify width after rendering:
``bash d2 --pad=40 input.d2 output.svg rg -o 'viewBox="0 0 ([0-9]+)' -r '$1' output.svg # should be <1400 ``
- SVG is the default and best format for web embedding and scalability.
- PNG is good for embedding in documents, Slack, etc.
- Use
--themefor professional presentation-ready output. - Use
--sketchfor informal, hand-drawn appearance. - Animated SVGs: Use
--animate-interval=1200with composition for animated diagrams.
Troubleshooting
- "d2: command not found": D2 is not installed. Follow install instructions above.
- Layout issues: Try a different layout engine (
--layout=elkor--layout=tala). - Overlapping labels: Shorten labels, adjust
font-size, or use a different layout. - Missing icons: Ensure icon URLs are accessible. Use https://icons.terrastruct.com for reliable icons.
- Diagram too wide: See the Width Control section. Most likely cause is nested containers with many sibling children.
- Square corners on markdown boxes:
border-radiusdoesn't apply to|md ... |labels. Use the titled container + transparent md child pattern instead. - Render fails on sequence diagram styles: Sequence diagrams don't support
styleblocks on connections. Remove them. @interpreted as import: Quote or rephrase labels containing@(e.g.,"@MainActor").
Additional References
references/D2_LANGUAGE_REFERENCE.md- Complete language syntax referencereferences/D2_PATTERNS.md- Common diagram patterns and templatesassets/- Example.d2template files ready to use- Official docs: https://d2lang.com/tour/intro/
- Playground: https://play.d2lang.com
- Icons: https://icons.terrastruct.com
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jonmagic
- Source: jonmagic/skills
- License: ISC
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.