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
⚠ 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 Diagram
Generate architecture diagrams as text with d2, then render and embed them. Three scripts support the workflow:
scripts/icons.py— resolve exacticon:URLs for AWS/GCP/Azure services.scripts/render.py— render/validate/format.d2files 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
- Write a
.d2file. Keep the source next to the doc it illustrates so it
stays re-renderable. Use containers for tiers/boundaries and classes for consistent styling.
- For cloud diagrams, resolve icons first with
icons.pyand paste the URLs
verbatim — never hand-write icons.terrastruct.com URLs (they're URL-encoded and unguessable).
- Validate, then render with
render.py(SVG by default). - Embed in markdown with
render.py --mdif 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
- 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 .
- 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).
- See
examples/aws-arch.d2for 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:
ovalstart/end, plain steps,diamonddecisions,
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 label —
label.near: outside-top-left(oroutside-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 presets —
assets/themes.jsonmaps 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 partial —
assets/styles.d2sets 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
--validateand--fmtbefore committing; commit the.d2source, not just
the rendered image, so diagrams can be regenerated.
- Prefer
classesover repeating inline styles; keep labels short and action-oriented. - For very large systems, split into multiple focused diagrams.
Requirements
- The
d2CLI onPATH:
``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.
- Author: colbytimm
- Source: colbytimm/my-dev-tools
- License: MIT
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.