Dictim
d2's 'datafied' companion!
Install / Use
/learn @judepayne/DictimREADME
CI
Release
License
<small>d2 compatibility: 0.7.0</small>
dictim
d2's datafied companion
The dictim project is both a command line tool and clojure library that leverage the underlying power of d2 to transform your data into diagrams.
The command line tool (dict) converts structured data into d2 or beautiful diagrams directly. Generate diagrams from json or edn, parse existing d2 back into data, and automate diagram creation in your workflows.
# Transform data into a diagram in seconds with the '--image' option
dict -i '["app" "Web App"]["db" "Database"] \
["app" "->" "db" "queries"]' > diagram.svg
<img src="img/top-example.svg" style="max-width: 180px; height: 280px;">
Why dict?
🚀 Diagrams as Data
Generate diagrams programmatically from your data. No more manually updating diagrams when your architecture changes.
⚡ Lightning Fast
Native binaries for macOS, Linux, and Windows. No JVM startup time, no dependencies.
🔄 Round-trip Compatible
Parse existing d2 diagrams back into structured data for analysis, transformation, or migration.
🛠 CI/CD Ready
Perfect for documentation pipelines, automated architecture diagrams, and keeping visual documentation in sync with code.
Quick Start
Installation
macOS (Homebrew)
brew install judepayne/tap/dictim
Windows (Scoop)
scoop bucket add judepayne https://github.com/judepayne/scoop-judepayne
scoop install dictim
Note: d2 is installed as a dependency by Homebrew, but is not available on Scoop, so please install it as per the instructions.
Linux/Manual Installation
# Download from releases (amd64)
wget https://github.com/judepayne/dictim/releases/latest/download/dict-linux-amd64
chmod +x dict-linux-amd64
sudo mv dict-linux-amd64 /usr/local/bin/dict
# Or for ARM64
wget https://github.com/judepayne/dictim/releases/latest/download/dict-linux-arm64
chmod +x dict-linux-arm64
sudo mv dict-linux-arm64 /usr/local/bin/dict
Other Platforms
As a babashka uberjar with bbin, please see the Wiki page.
or
download the appropriate release and put on your path.
Check the releases page if none of these options work for you.
Your First Diagram
Create a simple json file:
echo '[
["user", "User", {"shape": "person"}],
["system", "System", {"shape": "rectangle"}],
["user", "->", "system", "interacts", {"style.stroke": "blue"}]
]' > simple.json
Transform it to d2:
dict -c simple.json
Output:
user: User {shape: person}
system: System {shape: rectangle}
user -> system: interacts {style.stroke: blue}
Render with d2:
dict -c < simple.json | d2 - simple.svg
Or just directly:
dict -i < simple.json > simple.svg
Real-World Examples
Transforming data from a REST API
# Try this now!
curl -s "https://restcountries.com/v3.1/region/europe?fields=name,capital" | \
jq -r '.[0:6] | map({country: .name.common, capital: (.capital // ["Unknown"])[0]}) |
[["Europe", "European Region"]] +
(map([.country, .country])) +
(map([.capital, .capital])) +
(map(["Europe", "->", .country, "contains"])) +
(map([.country, "->", .capital, "capital city"])) | @json' | \
dict -i > europe.svg && open europe.svg
<div style="text-align: center;">
<div style="width: 900px; margin: 0 auto;">
<img src="img/europe.svg" style="width: 900px;">
</div>
</div>
[!Tip] Point your AI tool to the dictim syntax page and the command line page and it should do great at authoring these little transformer scripts, jq statements. Build up a library!
System architecture
edn
[["frontend" "React Frontend" {"shape" "rectangle"}]
["api" "REST API" {"shape" "hexagon"}]
["cache" "Redis Cache" {"shape" "cylinder"}]
["database" "PostgreSQL" {"shape" "cylinder"}]
["frontend" "->" "api" "HTTP requests"]
["api" "->" "cache" "cache lookup"]
["api" "->" "database" "SQL queries"]]
<img src="img/system-architecture.svg" style="width: 450px;">
DevOps Pipeline
Generate deployment diagram from kubernetes infrastructure:
kubectl get services -o json | jq -r '
.items | map([.metadata.name, .spec.type]) | @json
' | dict -i > deployment.svg
Advanced: Comprehensive microservices architecture
infrastructure.json
[
["nginx-ingress", "Ingress Controller", {"shape": "diamond"}],
["frontend-service", "React Frontend", {"shape": "rectangle"}],
["api-gateway", "API Gateway", {"shape": "hexagon"}],
["user-service", "User Service", {"shape": "rectangle"}],
["order-service", "Order Service", {"shape": "rectangle"}],
["payment-service", "Payment Service", {"shape": "rectangle"}],
["notification-service", "Notification Service", {"shape": "rectangle"}],
["user-db", "User Database", {"shape": "cylinder"}],
["order-db", "Order Database", {"shape": "cylinder"}],
["redis-cache", "Redis Cache", {"shape": "cylinder"}],
["message-queue", "RabbitMQ", {"shape": "queue"}],
["monitoring", "Prometheus", {"shape": "cloud"}],
["logging", "ELK Stack", {"shape": "cloud"}],
["nginx-ingress", "->", "frontend-service", "routes traffic"],
["nginx-ingress", "->", "api-gateway", "API requests"],
["frontend-service", "->", "api-gateway", "AJAX calls"],
["api-gateway", "->", "user-service", "authenticates"],
["api-gateway", "->", "order-service", "order requests"],
["api-gateway", "->", "payment-service", "payment processing"],
["order-service", "->", "user-service", "validates user"],
["order-service", "->", "payment-service", "process payment"],
["payment-service", "->", "notification-service", "payment events"],
["order-service", "->", "message-queue", "order events"],
["notification-service", "<-", "message-queue", "consumes events"],
["user-service", "->", "user-db", "stores user data"],
["order-service", "->", "order-db", "stores orders"],
["user-service", "->", "redis-cache", "caches sessions"],
["order-service", "->", "redis-cache", "caches inventory"],
["user-service", "->", "monitoring", "metrics"],
["order-service", "->", "monitoring", "metrics"],
["payment-service", "->", "monitoring", "metrics"],
["notification-service", "->", "logging", "logs"]
]
Generate an infrastructure diagram:
dict -i --theme 3 < infrastructure.json > devops-pipeline.svg
<img src="img/devops-pipeline.svg">
Git Branch Analysis
Use a babashka script to transform git output..
git-dict.bb
#!/usr/bin/env bb
(require '[cheshire.core :as json]
'[clojure.string :as str])
(let [branches (->> (slurp *in*) str/split-lines)
clean-branches (map #(-> % str/trim (str/replace #"origin/" "")) branches)
main-branch "main"
;; Create branch nodes
branch-nodes (for [branch clean-branches
:when (not= branch "HEAD")]
(if (= branch main-branch)
[branch "Main Branch" {"shape" "hexagon"}]
[branch "Feature Branch" {"shape" "rectangle"}]))
;; Create connections from main to feature branches
connections (for [branch clean-branches
:when (and (not= branch "HEAD")
(not= branch main-branch))]
[main-branch "->" branch "branched from"])
dictim-data (concat '({"direction" "right"}) branch-nodes connections)]
(println (json/generate-string dictim-data)))
Generate a branch visualization:
git branch -r | bb git-to-dictim.bb | dict -c | d2 - branches.svg
<img src="img/git-branches.svg" style="width: 900px;">
Database Schema
[["objects"
{"shape" "sql_table"}
["id" "int" {"constraint" "primary_key"}]
["disk" "int" {"constraint" "foreign_key"}]
["json" "jsonb" {"constraint" "unique"}]
["last_updated" "timestamp with time zone"]]
["disks"
{"shape" "sql_table"}
["id" "int" {"constraint" "primary_key"}]]
["objects.disk" "->" "disks.id"]]
<img src="img/database-schema.svg" style="width: 700px;">
Distributed Tracing Sequence Diagrams
Visualize microservice interactions from Jaeger trace data using a babashka script:
jaeger-to-sequence.bb
#!/usr/bin/env bb
(require '[cheshire.core :as json])
(let [jaeger-data (json/parse-string (slurp *in*))
spans (get-in jaeger-data ["data" 0 "spans"])
span-map (into {} (map #(vector (get % "spanID") %) spans))
services (distinct (map #(get-in % ["process" "serviceName"]) spans))
service-declarations (map #(vector % {"shape" "sequence_diagram"}) services)
interactions
(for [span spans
:let [references (get span "references" [])]
ref references
:when (= "CHILD_OF" (get ref "refType"))
:let [parent-span-id (get ref "spanID")
parent-span (get span-map parent-span-id)
parent-service (get-in parent-span ["process" "serv
