# D2: a diagram scripting language for architecture you can review in a pull request

> D2 turns plain text into SVG, PNG, PDF and PPTX diagrams, with bundled layout engines and a plugin pipeline. It fits teams that keep diagrams in version control, and it is a poor fit if you need a browser-only editor or a hosted service.

**d2lang/d2** — D2 is a modern diagram scripting language that turns text to diagrams.

- Repository: https://github.com/d2lang/d2
- Website: https://d2lang.com
- Stars: 25,450 · Forks: 752
- Language: Go
- License: MPL-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/d2lang-d2

## The problem D2 targets: diagrams that rot because the source is a canvas

Architecture diagrams drawn in a GUI editor age badly. The file is a binary or a JSON blob, a reviewer cannot see what changed, and the person who drew it is often the only one who knows how to edit it. D2 addresses that by making the diagram source a text file with a grammar, so a change to a service boundary shows up as a line in a diff.

The README frames the audience indirectly but clearly: it ships a parser that reports multiple errors from a broken program, an autoformatter, and syntax highlighting, and it says good language tooling is necessary for creating and maintaining large diagrams. That is a statement about scale. D2 is aimed at people who expect a diagram file to be maintained for years, not drawn once for a slide.

The repository layout backs this up. There are separate top-level packages for parsing (d2parser), the AST (d2ast), the intermediate representation (d2ir), the compiler (d2compiler), the graph model (d2graph), formatting (d2format), and export (d2exporter). A single-purpose drawing tool does not need that many layers. The cost of that structure is a larger surface to learn if you want to extend it; the benefit is that errors are caught before rendering rather than after.

## How a .d2 file becomes an SVG

The pipeline is a compiler, not a template engine. Text enters the parser, becomes an AST, is lowered into an intermediate representation, then into a graph of nodes and edges in d2graph. A layout engine assigns coordinates to that graph, and d2renderers draws the result, which d2exporter writes out as SVG, PNG, GIF, PDF or PPTX.

The layout step is pluggable, and this is where D2 differs most from tools that own their own renderer end to end. Three engines are listed in the README. Dagro is the default and is bundled; it is described as a native Go port of the Dagre directed graph layout engine producing layered or hierarchical layouts, based on Graphviz's DOT algorithm. elk-go is also bundled and is described as suited to node-link diagrams with an inherent direction and ports. TALA is bundled but opt-in, and the README describes it as a native layout and edge-routing engine designed specifically for software architecture diagrams.

That third engine is the interesting one for this audience, and also the one to be careful with. The README states it is selected with the --layout=tala flag, the D2_LAYOUT=tala environment variable, or a layout-engine: tala setting under vars.d2-config in the source. Because it is opt-in, diagrams written without that setting will not use it, and the README does not claim it is a drop-in replacement for Dagro.

The rest of the pipeline is extensible too. Plugins can either be bundled with the build or installed separately as a standalone binary, and the README says the plugin system allows you to change out layout engines and customize the rendering pipeline. So the architecture is a compiler with swappable back ends, and the practical consequence is that layout quality and layout engine choice are the variables you will actually tune.

## Installing D2 and rendering your first diagram

The README gives the install script as the easiest path. It also notes you can run it with --dry-run to see the commands that will be used without executing them, and it recommends using your OS package manager directly instead for improved security while stating the script is by no means insecure. If you are evaluating D2 rather than adopting it today, run the dry run first.

```bash
curl -fsSL https://d2lang.com/install.sh | sh -s -- --dry-run
```

If you have Go installed, the README gives a second route. It notes you will not get the manpage this way, and points at ./docs/INSTALL.md#source-release for an install from a release that does include manpages.

```bash
go install github.com/d2lang/d2@latest
```

With the binary on your PATH, the quickstart is two commands. The first writes a three-node chain to a file, the second renders it and opens a browser window that live-reloads when in.d2 changes.

```bash
echo 'x -> y -> z' > in.d2
d2 --watch in.d2 out.svg
```

What you should see is out.svg opened in a browser, with three boxes connected left to right, and the image redrawn each time you save in.d2. To remove it again, the README documents an uninstall path through the same script.

```bash
curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall
```

For anything beyond a first look, the README points at ./docs/examples for more examples and at the playground at play.d2lang.com, which renders D2 in the browser without installing anything.

## Where D2 gets in the way

The install path is the first friction point, and D2's own README acknowledges it. Piping a remote script into a shell is convenient and the project documents what the script does, but the README's own recommendation is to prefer your OS package manager. If your environment forbids curl-to-shell, you are on the Go install path or the source-release path, and the Go path costs you the manpage.

The second limitation is layout control. Because layout is delegated to an engine rather than hand-positioned, you are trading determinism for maintainability. A diagram that looks right with Dagro may route edges differently under elk-go or TALA, and the README does not present the three as interchangeable. If you need pixel-exact placement, a canvas tool will fight you less.

The third is the rendering target. D2 produces static files. The --watch mode opens a browser and live-reloads, but that is a local development convenience, not a collaborative editing surface. There is a playground, and the README lists a Discord community, but the README does not describe a hosted multi-user editor with presence or comments. Teams whose diagram workflow depends on non-engineers editing in a browser will find D2's centre of gravity in the wrong place.

Finally, the language is the interface. D2's own README example opens with a vars block containing d2-config, layout-engine and theme-id. Configuration lives inside the diagram source, which keeps it versioned alongside the diagram, but it also means a config change and a content change arrive in the same diff.

## D2 compared with Mermaid, and what the comparison actually turns on

Mermaid is the obvious alternative, and the useful difference is not syntax. Mermaid was designed to be embedded in Markdown and rendered by the host, which is why it spread through README files and wikis. D2 is a compiler you run, with a plugin pipeline and selectable layout engines.

That shows up in what each tool optimizes for. Mermaid optimizes for zero-install rendering inside a document. D2 optimizes for a maintained diagram artifact: a parser that reports multiple errors, an autoformatter, syntax highlighting, and a repository layout with distinct compiler stages. The README states D2 is designed with language tooling in mind and mentions plans for LSPs, so the tooling story is explicitly in progress rather than finished.

On export, the README lists SVG, PNG, GIF, PDF and PPTX. PPTX matters more than it looks: it means the diagram can land in a deck without a screenshot step. A tool that only emits SVG pushes that conversion onto you.

The honest framing is that these solve overlapping problems with different defaults. If your diagrams are decoration inside documentation, Mermaid's rendering model is less work. If your diagrams are deliverables that get reviewed and regenerated, D2's compiler structure is the reason to pick it.

## Maintenance, release cadence and the MPL-2.0 licence

The repository is not archived, and the last push was on 2026-09-10. That is recent, so describing the project as maintained is supported by the facts rather than assumed. The release history tells a more textured story: v0.9.0 was tagged on 2026-09-07, v0.8.2 on 2026-08-28, and the release before that, v0.7.1, on 2025-08-19. There is a gap of roughly a year between v0.7.1 and the v0.8.x line, followed by two releases eleven days apart. Cadence is not steady, so pinning a version and reading CHANGELOG.md before upgrading is the practical approach. The repository also carries a weekly race test workflow, which is a signal that concurrency is exercised on a schedule rather than only at release time.

Upgrade cost depends on how much of the language you use. Diagram source is the stable surface; the Go library API is not, and the README points at ./docs/examples/lib for library usage without promising stability. If you embed D2 as a library, treat minor version bumps as something to test.

The licence is MPL-2.0, file-level copyleft. Modifying D2's own files carries obligations that using it unmodified does not, and the distinction between linking against the library and modifying the source matters here. This is a description of the licence, not legal advice; if you are redistributing a modified D2, read LICENSE.txt and THIRD_PARTY_NOTICES.txt, both of which are in the repository root.

## Conclusion

Adopt D2 if your diagrams live next to the code they describe and you want them reviewable as diffs; skip it if you need a hosted collaborative editor or a renderer that runs entirely in the browser. Verify the install script against your OS package manager before piping it to a shell, and check whether the TALA layout engine suits your diagram before committing to it, since it is documented as opt-in rather than the default.

## FAQ

### What is the D2 format?

D2 is a diagram scripting language: you write text in a .d2 file and the CLI compiles it into a diagram. The README's quickstart writes 'x -> y -> z' to in.d2 and renders it to out.svg.

### What is D2 software?

It is a Go program that runs as a CLI and can also be used as a library from Go programs. The README describes it as a modern diagram scripting language that turns text to diagrams, and it exports SVG, PNG, GIF, PDF and PPTX.

### Can GitHub render D2?

The README does not state that GitHub renders .d2 files. It presents D2 as a CLI you run to produce SVG or other exports, and links to a separate playground at play.d2lang.com for browser rendering.

### What are the key differences between D2 and Mermaid?

Mermaid is designed to render inside the document that contains it, while D2 is a compiler with selectable layout engines and a plugin pipeline. D2's README emphasizes language tooling such as multi-error parsing, an autoformatter and syntax highlighting, and lists SVG, PNG, GIF, PDF and PPTX as export targets.

## Sources

- [d2lang/d2 on GitHub](https://github.com/d2lang/d2)
- [License: MPL-2.0](https://github.com/d2lang/d2/blob/master/LICENSE)
- [Project website](https://d2lang.com)
- [README](https://github.com/d2lang/d2/blob/master/README.md)
- [Releases](https://github.com/d2lang/d2/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/d2lang-d2
