AgentStack
SKILL unreviewed MIT Self-run

D2 Diagram

skill-colbytimm-my-dev-tools-d2-diagram · by colbytimm

Author software- and cloud-architecture diagrams as code with d2

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add skill-colbytimm-my-dev-tools-d2-diagram

Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 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.

Are you the author of D2 Diagram? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

d2 Diagram

Generate architecture diagrams as text with d2, then render and embed them. Three scripts support the workflow:

  • scripts/icons.py — resolve exact icon: URLs for AWS/GCP/Azure services.
  • scripts/render.py — render/validate/format .d2 files and embed them in markdown.
  • scripts/title_pills.py — post-process an SVG to draw masking pills behind group

titles (also wired into render.py --title-pills).

Plus shared assets: assets/styles.d2 (importable layout + classes) and assets/themes.json (named render presets) — see Theming.

Workflow

  1. Write a .d2 file. Keep the source next to the doc it illustrates so it

stays re-renderable. Use containers for tiers/boundaries and classes for consistent styling.

  1. For cloud diagrams, resolve icons first with icons.py and paste the URLs

verbatim — never hand-write icons.terrastruct.com URLs (they're URL-encoded and unguessable).

  1. Validate, then render with render.py (SVG by default).
  2. Embed in markdown with render.py --md if the diagram belongs in docs.

Syntax cheat-sheet

# Objects (default shape is rectangle) and connections
user: User { shape: person }
api: API Gateway { shape: hexagon }
cache: Redis { shape: cylinder }     # cylinder = datastore
user -> api: HTTPS                    # -> directed, -- plain,  bidirectional

# Containers (nesting) + cross-container edges
backend: Backend {
  svc: Order Service
  db: Postgres { shape: cylinder }
}
api -> backend.svc
backend.svc -> backend.db: SQL

# Reusable styles via classes
classes: {
  service: { style: { fill: "#E6F4EA"; stroke: "#34A853" } }
}
backend.svc.class: service

# Inline style + icon (see icons.py for cloud URLs)
queue: Event Bus { shape: queue; style.fill: "#FEF7E0" }
lambda: Worker { icon: https://icons.terrastruct.com/aws%2FCompute%2FAWS-Lambda.svg }

# Database schema / ERD
orders: { shape: sql_table; id: uuid; total: int }

Useful shapes: rectangle (default), square, cylinder (datastores), person (actors), hexagon, cloud, queue, package, page, step, diamond, callout, sql_table. Icons render top-left on containers and centered on plain shapes; icon: decorates a shape, while shape: image makes the image be the shape.

Software architecture recipe

Group components into layered containers (client → edge → application → data), give each tier a class for visual consistency, and label connections with the protocol or action. Render with elk (--layout elk, or set layout-engine: elk) — its orthogonal routing keeps labels and edges from overlapping; raise --elk-node-spacing if it's still tight. See examples/software-arch.d2 for a complete 3-tier example (containers, classes, a sql_table, and a request flow). General guidance on architecture-diagram structure: Atlassian: architecture diagrams.

Cloud architecture recipe

  1. Resolve every service icon before writing the diagram:

``bash python scripts/icons.py search "lambda" --provider aws python scripts/icons.py search "cloud storage" --provider gcp python scripts/icons.py search "app service" --provider azure ``

Each result prints a paste-ready icon: line. --json for machine output; --limit N to widen; categories/providers to browse. The bundled index (assets/icons.csv) is a snapshot of the most common AWS/GCP/Azure services — if a service isn't found, try broader terms or a sibling service, or browse .

  1. Use one provider's icon set per diagram, and group resources by their real

boundaries (cloud account → region/VPC → subnet, or subscription → resource group). Style the cloud boundary to match the brand (e.g. AWS #FF9900).

  1. See examples/aws-arch.d2 for a complete, validated AWS example whose

icon URLs all came from icons.py.

Other diagram types

  • Sequence diagrams (auth flows, request/response): set shape: sequence_diagram

at the root; child objects become lifelines and connections become ordered messages. A self-edge is a self-call; a -> a: label. See examples/auth-flow.d2.

  • User-journey / flowcharts: oval start/end, plain steps, diamond decisions,

and edges labeled yes/no for branches and retry loops. See examples/user-flow.d2 (also shows sketch style).

Rendering & embedding

# SVG (default; no dependencies, ideal for web/markdown). Output path derived from input.
python scripts/render.py examples/software-arch.d2

# Options: format, theme, layout, spacing, sketch, padding.
# --layout elk + --elk-node-spacing is the go-to fix for a cramped/overlapping diagram.
python scripts/render.py examples/aws-arch.d2 -o out.svg \
  --theme 1 --layout elk --elk-node-spacing 100 --pad 40

# SVG with masking pills behind every group title (lines can't cross a title)
python scripts/render.py examples/software-arch.d2 --title-pills

# Apply a named theme preset (see Theming below); --list-presets to see them
python scripts/render.py examples/software-arch.d2 --preset c4

# Validate or autoformat before committing
python scripts/render.py examples/aws-arch.d2 --validate
python scripts/render.py examples/aws-arch.d2 --fmt

# Render and embed (or update) in a markdown file, between markers so re-runs
# replace the image in place rather than appending:
#     
python scripts/render.py examples/software-arch.d2 --md README.md --md-marker arch

Graceful degradation (both handled automatically, no crash):

  • PNG/PDF make d2 launch a headless Chromium (downloaded on first use). If it

can't be installed/launched (e.g. restricted network), render.py falls back to SVG and prints how to enable raster output.

  • Icon bundling: by default d2 inlines remote icons into the output for a

self-contained file. If the icon host is unreachable at render time, render.py retries with --no-bundle, keeping icons as remote refs that load when the image is viewed online. Pass --no-bundle explicitly to force this.

Readability — preventing label / icon / line overlap

Overlapping labels, edges, and icons are the most common quality problem. Apply these rules when authoring (they are baked into the examples):

  • Use the ELK layout for architecture & flow diagrams--layout elk (or

layout-engine: elk in vars.d2-config). ELK routes edges orthogonally and places labels with far less overlap than the default dagre. This is the single biggest win. If a diagram is still cramped, spread it out: --layout elk --elk-node-spacing 100 (and/or --elk-padding "[top=60,left=50,bottom=50,right=50]").

  • Keep edge labels short — ideally ≤ 3 words (3. GraphQL (Bearer), not

3. GraphQL query with bearer access token). Push detail into the node label or drop it. Wrap any unavoidably long label with \n.

  • Don't put icon: on a container that also carries an important label. A

container anchors both its label and its icon at the top, so on tight layouts they crowd each other. Put icons on leaf nodes; label grouping containers (VPCs, subnets, tiers) with text only.

  • Keep grouping-container labels off the routed edges. A container label

defaults to top-center, which is exactly where ELK routes edges into the box, so lines draw over it. Two good options:

  • Titled box (preferred for VPC/subnet/tier groups) — give the container a

fill, a stroke, a bold font, and label.near: top-left. The label then sits on a real background with a border, and d2 reserves a title band at the top of the box so edges route into the children below it — backgrounds and no lines over the title:

``d2 classes: { subnet: { label.near: top-left style: {fill: "#EDEFF5"; stroke: "#5B6B8C"; stroke-width: 2; stroke-dash: 3; bold: true; font-color: "#33415C"} } } vnet: VNet 10.0.0.0/16 { snet_app: snet-app 10.0.3.0/24 {class: subnet; api: API; worker: Worker} } ``

  • Outside labellabel.near: outside-top-left (or outside-top-center)

floats the label above the border, fully clear of edges, when you don't want a filled box. (d2 has no background behind an outside label.)

Either way, don't shrink these labels with a tiny font-size; the readable default is fine.

  • Title pills (SVG, strongest guarantee). d2 draws connections after shape

labels, so in a dense diagram a routed line can still clip a group title. Pass render.py --title-pills (SVG output only): it post-processes the SVG to draw an opaque, bordered pill behind every group/container title and re-renders it on top of the edges, so no line can show through. Pills inherit each container's own fill/border (override with --pill-fill / --pill-stroke). scripts/title_pills.py can also run standalone on any d2 SVG. This is the most robust way to satisfy "lines must never cross a group title."

  • One short label per icon'd node. A node with an icon and a long multi-line

label squeezes the icon — prefer a concise name plus the icon.

  • Give the diagram air with --pad 40 (or more) and split very large systems

into multiple focused diagrams.

  • Sequence diagrams ignore the layout engine, so readability there is all about

concise, \n-wrapped message labels. d2 masks the lifeline/arrow behind each label so lines don't strike through text — this is honored by d2's native SVG/PNG export (and any compliant SVG renderer). If you rasterize the SVG with a tool that ignores SVG masks (some rsvg/cairo builds), lines can appear to run through labels; prefer render.py's own PNG export, which uses d2 directly.

  • Always eyeball the rendered output. If labels still collide, in order: switch

to elk, raise --elk-node-spacing, shorten labels, then bump --pad.

Theming

d2 ships built-in themes selected by numeric id (--theme / --dark-theme, or in-file vars.d2-config.theme-id). Run d2 themes for the list — e.g. Neutral 0/1, Flagship 3, Aubergine 7, Origami 302, C4 303 (good for architecture); dark 200/201. Two skill assets make theming reusable:

  • Named render presetsassets/themes.json maps friendly names to a theme id

plus default render options (layout, pad, title-pills). Apply with render.py --preset (any explicit flag still wins); --list-presets shows them. Presets: default, neutral-grey, terrastruct, aubergine, origami, c4, dark, auto-dark, sketch. Add your own by editing the JSON.

  • Shared style partialassets/styles.d2 sets the elk layout default and

reusable classes (titled-box group/subnet; cloud aws/azure/gcp brand boundaries; service/datastore/queue/authz). Import it so every diagram shares one look: ``d2 ...@../assets/styles cloud: AWS Cloud {class: aws; web: Web {class: service}} ` See examples/aws-arch.d2`, which imports it.

  • Custom palette — d2 can't load a brand-new theme file, but you can recolor any

built-in theme's palette slots in your own vars (these are in-file, not a preset): ``d2 vars: {d2-config: {theme-overrides: {B1: "#0B5FFF"; B2: "#2E7D32"}}} ``

Best practices

  • Run --validate and --fmt before committing; commit the .d2 source, not just

the rendered image, so diagrams can be regenerated.

  • Prefer classes over repeating inline styles; keep labels short and action-oriented.
  • For very large systems, split into multiple focused diagrams.

Requirements

  • The d2 CLI on PATH:

``bash curl -fsSL https://d2lang.com/install.sh | sh -s -- # or: brew install d2 # or: go install oss.terrastruct.com/d2@latest # needs Go 1.20+ ``

  • Scripts are pure Python 3 stdlib (no pip installs).
  • PNG/PDF export additionally needs d2's headless Chromium (auto-downloaded on

first raster render; SVG needs nothing).

assets/icons.csv is bundled verbatim from the public tf2d2/terrastruct-icons project (columns Cloud,Title,URL). Terrastruct does not change or expire existing icon URLs, so the bundled values stay valid.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.