# Technical Documentation: d2lang/d2

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/d2lang/d2)

### Overview (README.md)

<div align="center">
  <img src="./docs/assets/banner.png" alt="D2" />
  <h2>
    A modern diagram scripting language that turns text to diagrams.
  </h2>

[Docs](https://d2lang.com) | [Cheat sheet](./docs/assets/cheat_sheet.pdf) | [Comparisons](https://text-to-diagram.com) | [Playground](https://play.d2lang.com)

[](https://github.com/d2lang/d2/actions/workflows/ci.yml)
[](https://github.com/d2lang/d2/actions/workflows/weekly-race.yml)
[](https://github.com/d2lang/d2/releases)
[](./CHANGELOG.md)
[](https://www.npmjs.com/package/@d2lang/d2)
[](https://discord.gg/NF6X8K4eDq)
[](./LICENSE.txt)

<a href="https://play.d2lang.com">
<img src="./docs/assets/playground_button.png" alt="D2 Playground button" width="200" />
</a>

https://user-images.githubusercontent.com/3120367/206125010-bd1fea8e-248a-43e7-8f85-0bbfca0c6e2a.mp4

</div>

# Table of Contents


- [What does D2 look like?](#what-does-d2-look-like)
- [Quickstart](#quickstart)
- [Install](#install)
- [D2 as a library](#d2-as-a-library)
- [Themes](#themes)
- [Fonts](#fonts)
- [Export file types](#export-file-types)
- [Language tooling](#language-tooling)
- [Layout engines](#layout-engines)
- [Comparison](#comparison)
- [Contributing](#contributing)
- [License](#license)
- [Related](#related)
  - [Official plugins](#official-plugins)
  - [Community plugins](#community-plugins)
  - [Misc](#misc)
- [FAQ](#faq)
- [Notable open-source projects documenting with D2](#notable-open-source-projects-documenting-with-d2)

## What does D2 look like?

```d2
vars: {
  d2-config: {
    layout-engine: elk
    # Terminal theme code
    theme-id: 300
  }
}
network: {
  cell tower: {
    satellites: {
      shape: stored_data
      style.multiple: true
    }

    transmitter

    satellites -> transmitter: send
    satellites -> transmitter: send
    satellites -> transmitter: send
  }

  online portal: {
    ui: {shape: hexagon}
  }

  data processor: {
    storage: {
      shape: cylinder
      style.multiple: true
    }
  }

  cell tower.transmitter -> data processor.storage: phone logs
}

user: {
  shape: person
  width: 130
}

user -> network.cell tower: make call
user -> network.online portal.ui: access {
  style.stroke-dash: 3
}

api server -> network.online portal.ui: display
api server -> logs: persist
logs: {shape: page; style.multiple: true}

network.data processor -> api server
```

<p align="center">
    <img width="400px" src="./docs/assets/example.svg" alt="D2 render example" />
</p>

> Open in [playground](https://play.d2lang.com/?script=rVLLTsQwDLznKyJxbrWwtyLxFdyR1Zg2ahpHibvLCvXfcdqGfSHthVv8yIxn7APE1OhvpbV5qVryn7ZbQ60dnGjiCn1nPTYa3bCkn_Q7xtF6cJp7HFG3ZHCpLGFlTaP3u51kZjUrj3ykOKyYLTr5REeMhSMBS84yppKRXA9B-BJTRPNhgKEU-OSwHifHNjjp4DitxLNa-SP4NFpmjOoGXVdvl2VBR2_-sWeZgLwTp3SgyOCKnsnKa5PU4xd05OfyIWvTIVKLKdHZExEOHd4Z0p4E3oi2h25s8Ge764uZs4Rr4vqXMfQkAhx1SVanplQWtU0QMCbyEh-t4b7Rz_td6cuo267ryzWPMMiFgHN3XVdu1dkmaPM8K-EiLnGkASsDScj2mQqCFcvj4RGUsSnI_d70Z2GrCptYrVHZTRADXv80VWgL0bVvGfJMoH4A)

> For more examples, see [./docs/examples](./docs/examples).

## Quickstart

The most convenient way to use D2 is to just run it as a CLI executable to
produce SVGs from `.d2` files.

```sh
# First, install D2
curl -fsSL https://d2lang.com/install.sh | sh -s --

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

A browser window will open with `out.svg` and live-reload on changes to `in.d2`.

## Install

The easiest way to install is with our install script:

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

You can run the install script with `--dry-run` to see the commands that will be used
to install without executing them.

Or if you have Go installed you can install from source though you won't get the manpage:

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

You can also install a release from source which will include manpages.
See [./docs/INSTALL.md#source-release](./docs/INSTALL.md#source-release).

To uninstall with the install script:

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

For detailed installation docs, see [./docs/INSTALL.md](./docs/INSTALL.md).
We demonstrate alternative methods and examples for each OS.

As well, the functioning of the install script is described in detail to alleviate any
concern of its use. We recommend using your OS's package manager directly instead for
improved security but the install script is by no means insecure.

## D2 as a library

In addition to being a runnable CLI tool, D2 can also be used to produce diagrams from
Go programs.

For examples, see [./docs/examples/lib](./docs/examples/lib).

## Themes

D2 includes a variety of official themes to style your diagrams beautifully right out of
the box. See [./d2themes](./d2themes) to browse the available themes and make or
contribute your own creation.

## Fonts

D2 ships with "Source Sans Pro" as the font in renders. If you wish to use a different
one, please see [./d2renderers/d2fonts](./d2renderers/d2fonts).

## Export file types

D2 supports SVG, PNG, GIF, PDF, and PPTX exports.

## Language tooling

D2 is designed with language tooling in mind. D2's parser can parse multiple errors from a
broken program, has an autoformatter, syntax highlighting, and we have plans for LSP's and
more. Good language tooling is necessary for creating and maintaining large diagrams.

The extensions for VSCode and Vim can be found in the [Related](#related) section.

## Layout engines

D2 bundles three layout engines. Select one with `--layout=dagre`, `--layout=elk`, or
`--layout=tala`. You can also set `D2_LAYOUT` or `vars.d2-config.layout-engine` in D2 source.
Run `d2 layout` to list the engines or `d2 layout <name>` for their configuration options.

- [Dagro](https://github.com/d2lang/dagro) (default, bundled): A native Go port of the
  Dagre directed graph layout engine that produces layered/hierarchical layouts. Based
  on Graphviz's DOT algorithm.
- [elk-go](https://github.com/d2lang/elk-go) (bundled): A native Go port of the ELK
  directed graph layout engine, particularly suited for node-link diagrams with an
  inherent direction and ports.
- [TALA](./d2layouts/d2talalayout) (bundled, opt-in): Native layout and edge-routing engine designed
  specifically for software architecture diagrams. Select it with `--layout=tala`,
  `D2_LAYOUT=tala`, or a `layout-engine: tala` setting under `vars.d2-config` in D2 source.

D2 also handles specialized layouts such as sequence diagrams and grids. Go applications
can use the [layout packages](./d2layouts) directly or provide layout and routing functions
through [d2lib](./d2lib).

Sketch-mode rendering uses [rough-go](https://github.com/d2lang/rough-go), a native Go
compatibility port of the Rough.js 4.6.6 rendering surface used by D2.

LaTeX labels use [mathjax-go](https://github.com/d2lang/mathjax-go), a native Go port of
the MathJax 3.2.2 TeX-to-SVG pipeline.

## Comparison

For a comparison against other popular text-to-diagram tools, see
[https://text-to-diagram.com](https://text-to-diagram.com).

## Contributing

Contributions are welcome! See [./docs/CONTRIBUTING.md](./docs/CONTRIBUTING.md).

## License

Open sourced under the Mozilla Public License 2.0. See [./LICENSE.txt](./LICENSE.txt).

## Related

We are constantly working on new plugins, integrations, extensions. Contributions are
welcome in any official or community plugins. If you have somewhere in your workflow that
you want to use D2, feel free to open a discussion. We have limited bandwidth and usually
choose the most high-demand ones to work on. If you make something cool with D2 yourself,
let us know and we'll be happy to include it here!

### Official plugins

- **VSCode extension**: [https://github.com/d2lang/d2-vscode](https://github.com/d2lang/d2-vscode)
- **Vim extension**: [https://github.com/d2lang/d2-vim](https://github.com/d2lang/d2-vim)
- **Obsidian plugin**: [https://github.com/d2lang/d2-obsidian](https://github.com/d2lang/d2-obsidian)

### Community plugins

- **Tree-sitter grammar**: [https://github.com/ravsii/tree-sitter-d2](https://github.com/ravsii/tree-sitter-d2)
- **Emacs major mode**: [https://github.com/andorsk/d2-mode](https://github.com/andorsk/d2-mode)
- **Goldmark extension**: [https://github.com/FurqanSoftware/goldmark-d2](https://github.com/FurqanSoftware/goldmark-d2)
- **Telegram bot**: [https://github.com/meinside/telegram-d2-bot](https://github.com/meinside/telegram-d2-bot)
- **Postgres importer**: [https://github.com/zekenie/d2-erd-from-postgres](https://github.com/zekenie/d2-erd-from-postgres)
- **Structurizr to D2 exporter**: [https://github.com/goto1134/structurizr-d2-exporter](https://github.com/goto1134/structurizr-d2-exporter)
- **MdBook preprocessor**: [https://github.com/danieleades/mdbook-d2](https://github.com/danieleades/mdbook-d2)
- **ROS2 D2 Exporter**: [https://github.com/Greenroom-Robotics/ros-d2](https://github.com/Greenroom-Robotics/ros-d2)
- **D2 org-mode support**: [https://github.com/xcapaldi/ob-d2](https://github.com/xcapaldi/ob-d2)
- **Python D2 diagram builder**: [https://github.com/MrBlenny/py-d2](https://github.com/MrBlenny/py-d2)
- **Clojure D2 transpiler**: [https://github.com/judepayne/dictim](https://github.com/judepayne/dictim)
- **JavaScript D2 diagram builder**: [https://github.com/Kreshnik/d2lang-js](https://github.com/Kreshnik/d2lang-js)
- **C# & dotnet SDK**: [https://github.com/Stephanvs/d2lang-cs](https://github.com/Stephanvs/d2lang-cs)
- **Maven plugin**: [https://github.com/andrinmeier/unofficial-d2lang-maven-plugin](https://github.com/andrinmeier/unofficial-d2lang-maven-plugin)
- **Confluence plugin**: [https://github.com/andrinmeier/unofficial-d2lang-confluence-plugin](https://github.com/andrinmeier/unofficial-d2lang-confluence-plugin)
- **CIL (C#, Visual Basic, F#, C++ CLR) to D2**: [https://github.com/HugoVG/AppDiagram](https://github.com/HugoVG/AppDiagram)
- **D2 Snippets (for text editors)**: [https://github.com/Paracelsus-Rose/D2-Language-Code-Snippets](https://github.com/Paracelsus-Rose/D2-Language-Code-Snippets)
- **Mongo to D2**: [https://github.com/novuhq/mongo-to-D2](https://github.com/novuhq/mongo-to-D2)
- **Pandoc filter (TypeScript)**: [https://github.com/ram02z/d2-filter](https://github.com/ram02z/d2-filter)
- **Pandoc filter (Python)**: [https://github.com/fliiiix/pandoc-d2-filter](https://github.com/fliiiix/pandoc-d2-filter)
- **Logseq-D2**: [https://github.com/b-yp/logseq-d2](https://github.com/b-yp/logseq-d2)
- **ent2d2**: [https://github.com/tmc/ent2d2](https://github.com/tmc/ent2d2)
- **MkDocs Plugin**: [https://github.com/landmaj/mkdocs-d2-plugin](https://github.com/landmaj/mkdocs-d2-plugin)
- **Remark Plugin**: [https://github.com/mech-a/remark-d2](https://github.com/mech-a/remark-d2)
- **VitePress Plugin**: [https://github.com/BadgerHobbs/vitepress-plugin-d2](https://github.com/BadgerHobbs/vitepress-plugin-d2)
- **Zed extension**: [https://github.com/gabeidx/zed-d2](https://github.com/gabeidx/zed-d2)
- **Hexo blog extension**: [https://github.com/leverimmy/hexo-d2](https://github.com/leverimmy/hexo-d2)
- **Rehype Plugin**: [https://github.com/stereobooster/beoe/tree/main/packages/rehype-d2](https://github.com/stereobooster/beoe/tree/main/packages/rehype-d2)
- **AsyncAPI to D2**: [https://github.com/holydocs/messageflow](https://github.com/holydocs/messageflow)
- **Database Schemas to D2**: [https://github.com/holydocs/dberd](https://github.com/holydocs/dberd)

### Misc

- **Comparison site**: [https://github.com/d2lang/text-to-diagram-site](https://github.com/d2lang/text-to-diagram-site)
- **Playground**: [https://github.com/d2lang/d2-playground](https://github.com/d2lang/d2-playground)
- **Language docs**: [https://github.com/d2lang/d2-docs](https://github.com/d2lang/d2-docs)
- **Hosted icons**: [https://icons.d2lang.com](https://icons.d2lang.com)

## FAQ

- Does D2 collect telemetry?
  - No, D2 does not use an internet connection after installation, except to check for
    version updates from Github periodically.
- Does D2 need a browser to run?
  - No, D2 can run entirely server-side.
- What's coming in the next release?
  - See [./ci/release/changelogs/next.md](./ci/release/changelogs/next.md).
- I have a question or need help.
  - The best way to get help is to ask on [D2 Discord](https://discord.gg/NF6X8K4eDq)
- I have a feature request, proposal, or bug report.
  - Please open up a Github Issue.
- I have a private inquiry.
  - Please reach out at [hi@d2lang.com](hi@d2lang.com).

## Notable open-source projects documenting with D2

Do you have or see an open-source project with `.d2` files? Please submit a PR adding to
this selected list of featured projects using D2.

- [ElasticSearch](https://github.com/elastic/beats/blob/main/libbeat/publisher/queue/proxy/diagrams/broker.d2)
- [Sourcegraph](https://handbook.sourcegraph.com/departments/engineering/managed-services/telemetry-gateway/#dev-architecture-diagram)
- [Temporal](https://github.com/temporalio/temporal/blob/0be2681c994470c7c61ea88e4fcef89bb4024e58/docs/_assets/matching-context.d2)
- [Tauri](https://v2.tauri.app/concept/inter-process-communication/)
    - Rust GUI framework (78.5k stars)
- [Intellij](https://github.com/JetBrains/intellij-community/blob/45bcfc17a3f3e0d8548bc69e922d4ca97ac21b2b/platform/settings/docs/topics/overview.md)
- [Coder](https://coder.com/blog/managing-templates-in-coder)
- [UC
  Berkeley](https://github.com/ucb-bar/hammer/blob/2b5c04d7b7d9ee3c73575efcd7ee0698bd5bfa88/doc/Hammer-Use/hier.d2)
- [Coronacheck](https://github.com/minvws/nl-covid19-coronacheck-app-ios/blob/e1567e9d1633b3273c537a105bff0e7d3a57ecfe/Diagrams/client-side-datamodel.d2)
  - Official app of the Netherlands for coronavirus entry passes.
- [Block
  Protocol](https://github.com/blockprotocol/blockprotocol/blob/db4cf8d422b881e52113aa52467d53115270e2b3/libs/%40blockprotocol/type-system/crate/assets/overview.d2)
  - The Block Protocol is an open standard for building and using data-driven blocks (1.2k
    stars).
- [Dagger](https://github.com/dagger/dagger/tree/main/cmd/dagger-graph)
  - A programmable CI/CD engine that runs your pipelines in containers (8k stars).
- [Ivy
  Wallet](https://github.com/Ivy-Apps/ivy-wallet/blob/8062624bfa65175ec143cdc4038de27a84d38b57/assets/calc_algo.d2)
  - Open-source money manager app for Android (1.1k stars).
- [LocalStack](https://docs.localstack.cloud/references/network-troubleshooting/)
  - Cloud service emulator (46k stars)
- [Queue Library](https://github.com/golang-queue/queue/tree/master/images)
  - Queue is a Golang library for spawning and managing a Goroutine pool

---

### Examples Lib README (`docs/examples/lib/README.md`)

# D2 library examples

We have a few examples in this directory on how to use the D2 library to turn D2 scripts
into rendered svg diagrams and more.

Each example is runnable though does not include error handling for readability.

### [./1-d2lib](./1-d2lib)

A minimal example showing you how to compile the diagram `x -> y` into an svg.

### [./2-d2oracle](./2-d2oracle)

D2 is built to be hackable -- the language has an API built on top of it to make edits
programmatically.

Modifying the previous example, this example demonstrates how
[d2oracle](../../../d2oracle) can be used to create a new shape, style it programmatically
and then output the modified d2 script.

This makes it easy to build functionality on top of D2. Terrastruct uses the
[d2oracle](../../../d2oracle) API to implement editing of D2 from mouse actions in a
visual interface.

### [./3-lowlevel](./3-lowlevel)

`d2lib` from the first example is just a wrapper around the lower level APIs. They
can be used directly and this example demonstrates such usage.

This shouldn't be necessary for most use cases.

---

### CONTRIBUTING (`docs/CONTRIBUTING.md`)

# Contributing


- [Welcome](#welcome)
- [CI](#ci)
- [Logistics](#logistics)
- [Dev](#dev)
  - [Content](#content)
  - [Tests](#tests)
  - [Documentation](#documentation)
  - [Questions](#questions)

## Welcome

D2's [long-term mission](https://d2lang.com/tour/future/) is to significantly reduce the
amount of time and effort it takes to create and maintain high-quality diagrams for every
software team. We started this because we love the idea of creating diagrams with text --
but it was clear the existing solutions were inadequete in their state and speed of
execution for this idea to be widely usable.

We've tried our best to avoid the mistakes of the past and take inspiration from the most
successful modern programming and configuration languages. D2 has built up each step of
the text-to-diagram pipeline from scratch, rethinking each one from first principles, from
the dead simple syntax, to the readable compiler, our own SVG renderer, etc.

D2 is committed to making something people want to use. That means contributions don't
only have to be in the form of pull requests. Your bug reports, plugins, examples,
discussions of new ideas, help a great deal.

If you'd like to get involved, we're also committed to helping you merge that first pull
request. You should be able to freely pick up Issues tagged as "good first issue". Those
will usually include notes on getting started, but if they're missing or insufficient,
just leave a comment and we'll add more detail. If you need help getting started, please
don't hesitate to pop into Discord -- as long as you want to help, we'll find the perfect
task (complexity matches your appetite and programming experience, in an area you're
interested in, etc).

## CI

Most of D2's CI is open sourced in its own
[repository](https://github.com/d2lang/ci), included as a submodule. After you clone
D2, make sure you initialize the submodules:

```sh
git submodule update --init --recursive
```

`./make.sh` runs the standard checks, including JS and Go WASM tests. Install the
Go version from `go.mod`, the Bun version from `d2js/js/package.json`, and Node.js
24 with npm. Subcommands to run individual parts of the CI:

- `./make.sh fmt`
- `./make.sh lint`
- `./make.sh test`
- `./make.sh test-wasm`
- `./make.sh race`
- `./make.sh build`

Here's what a successful run should look like:

<img width="1582" alt="Screen Shot 2023-02-19 at 7 46 34 PM" src="https://user-images.githubusercontent.com/3120367/220004975-7a218b82-c5c1-4a71-b2bb-8695bbfd600c.png">


Please make sure CI is passing for any PRs submitted for review.

Be sure to update the submodule whenever there are changes:

```sh
git submodule update --recursive
```

## Logistics

- Use Go 1.22.
- Please sign your commits
  ([https://github.com/terrastruct/d2/pull/557#issuecomment-1367468730](https://github.com/terrastruct/d2/pull/557#issuecomment-1367468730)).
- D2 uses Issues as TODOs. No auto-closing on staleness.
- Branch off `master`.
- If there's an Issue related, include it by adding "[one-word] #[issue]", e.g. "Fixes
  #123" somewhere in the description.
- Whenever possible and relevant, include a screenshot or screen-recording.

## Dev

### Content

Unless you've contributed before, it's safest to choose an Issue with a "good first issue"
label. If you'd like to propose new functionality or change to current functionality,
please create an Issue first with a proposal. When you start work on an Issue, please
leave a comment so others know that it's being worked on.

### Tests

D2 has extensive tests, and all code changes must include tests.

With the exception of changes to the renderer, all code should include a package-specific
test. If it's a visual change, an end-to-end (e2e) test should accompany.

Let's say I make some code changes. I can easily see how this affects the end result by
running:

```
./ci/e2ereport.sh -delta
```

This gives me a nice HTML output of what the test expected vs what it got (this was a PR
fixing multi-byte character labels):



Run `./ci/e2ereport.sh -help` for flags, including how to get deltas for a single test.

If you're testing labels and strings, it's encouraged to use 1-letter strings (`x`) in small
functional tests to minimally pinpoint issues. If you are testing something that exercises
variations in strings, or want to mimic more realistic diagram text, it's encouraged you
generate random strings and words from `fortune`. It gives a good range of the English
language. (Sometimes it gives controversial sentences -- don't use those.)

Script to generate one line of random text:
```
ipsum1() {
  fortune | head -n1 | sed 's/^ *//;s/ *$//' | tr -d '\n' | tee /dev/stderr | pbcopy
}
```

#### Running tests

Run: `./ci/test.sh`

The weekly CI workflow runs tests with `-race -count=1` to catch race conditions
without using cached test results. Run the same check locally with
`./ci/test.sh -race -count=1 ./...`, or use `./make.sh race` during development.

If you add a new test and run, it will show failure. That's because the vast majority of
D2's tests are comparing outputs. You don't define the expected output manually. The
testing library generates it and it's checked into version control if it looks right. So
for the first run of a new test, it has no expected output, and will fail. To accept the
  result as the expected, run the test with environment variable `TESTDATA_ACCEPT=1`.

#### Chaos tests

D2 has [chaos tests](https://en.wikipedia.org/wiki/Chaos_engineering) which produce random
configurations of diagrams. It can be helpful to run a few iterations (N~=100) to spot
cover your manual tests.

`D2_CHAOS_MAXI=100 D2_CHAOS_N=100 ./ci/test.sh ./d2chaos`

### Documentation

The code itself should be documented as appropriate with Go-style comments. No rules here,
`GetX()` doesn't need a `// GetX gets X`.

If it's some new functionality, please submit a pull request to document it in the
language docs:
[https://github.com/d2lang/d2-docs](https://github.com/d2lang/d2-docs).

### Questions

If you have any questions or would like to get more involved, feel free to open an issue
to discuss publicly, or chat in [Discord](https://discord.gg/NF6X8K4eDq)! If you have a
private inquiry, feel free to email us at hi@d2lang.com.

---

### INSTALL (`docs/INSTALL.md`)

# install

You may install `d2` through any of the following methods.


- [install.sh](#installsh)
  - [Security](#security)
- [macOS (Homebrew)](#macos-homebrew)
- [Linux](#linux)
  - [Void Linux](#void-linux)
- [Standalone](#standalone)
  - [Manual](#manual)
  - [PREFIX](#prefix)
- [From source](#from-source)
  - [Source Release](#source-release)
- [Windows](#windows)
  - [Release archives](#release-archives)
  - [WSL](#wsl)
  - [Native Package managers](#native-package-managers)
- [Docker](#docker)
- [Coming soon](#coming-soon)

## install.sh

The recommended and easiest way to install is with our install script, which will detect
the OS and architecture you're on and use the best method:

```sh
# With --dry-run the install script will print the commands it will use
# to install without actually installing so you know what it's going to do.
curl -fsSL https://d2lang.com/install.sh | sh -s -- --dry-run
# If things look good, install for real.
curl -fsSL https://d2lang.com/install.sh | sh -s --
```

For help on the terminal run, including the supported package managers and detection
methods:

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

### Security

The install script is not the most secure way to install d2. We recommend that if
possible, you use your OS's package manager directly or install from source with `go` as
described below.

But this does not mean the install script is insecure. There is no major flaw that
the install script is more vulnerable to than any other method of manual installation.
The most secure installation method involves a second independent entity, i.e your OS
package repos or Go's proxy server.

We're careful shell programmers and are aware of the many footguns of the Unix shell. Our
script was written carefully and with detail. For example, it is not vulnerable to partial
execution and the entire script runs with `set -eu` and very meticulous quoting.

It follows the XDG standards, installs `d2` properly into a Unix hierarchy path
(`/usr/local` unless `/usr/local` requires sudo in which case `~/.local` is used) and
allows for easy uninstall. You can easily adjust the used path with `--prefix`.

Some other niceties are that it'll tell you if you need to adjust `$PATH` or `$MANPATH` to
access `d2` and its manpages. For releases that bundle TALA, select it with
`d2 --layout=tala`; run `d2 layout` to check the installed engines.
This installer installs only D2 and rejects the obsolete `--tala` option before
installation. Omit that option when installing D2. Older D2 releases require the
separate plugin available from the [legacy TALA releases](https://github.com/terrastruct/TALA/releases).
You can install a specific version of `d2` with `--version`. Run the script with
`--help` for detailed docs on its options and features.

If you're still concerned, remember you can run with `--dry-run` to avoid writing anything.

For standalone installations, the script obtains the selected archive's SHA-256 digest
from the GitHub Releases API and, when GitHub provides one, verifies both cached and newly
downloaded archives before extracting them. Historical releases for which GitHub reports
no digest remain installable with a warning. Releases produced by the current release
workflow also include `SHA256SUMS` and GitHub artifact attestations. You can verify build
provenance separately with:

```sh
gh attestation verify d2-v0.0.0-linux-amd64.tar.gz --repo d2lang/d2
```

## macOS (Homebrew)

D2 binaries built with Go 1.27 require macOS 13 Ventura or newer.

If you're on macOS, you can install with `brew`.

```sh
brew install d2
```

> The install script above does this automatically if you have `brew` installed and
> are running it on macOS.

You can also install from source with:

```d2
brew install d2 --HEAD
```

## Linux

The following distributions have packages for d2:

### Void Linux

All supported platforms:

```sh
xbps-install d2
```

## Standalone

We publish standalone release archives for every release on Github.

Here's a minimal example script that downloads a standalone release, extracts it into the
current directory and then installs it.
Adjust VERSION, OS, and ARCH as needed.

```sh
VERSION=v0.0.13 OS=macos ARCH=amd64 curl -fsSLO \
    "https://github.com/d2lang/d2/releases/download/$VERSION/d2-$VERSION-$OS-$ARCH.tar.gz" \
    && tar -xzf "d2-$VERSION-$OS-$ARCH.tar.gz" \
    && make -sC "d2-$VERSION" install
```

To uninstall:

```sh
VERSION=v0.0.13 make -sC "d2-$VERSION" uninstall
```

### Manual

You can also manually download the `.tar.gz` release for your OS/ARCH combination and then
run the following inside the extracted directory to install:

```sh
make install
```

Run the following to uninstall:

```sh
make uninstall
```

### PREFIX

You can control the Unix hierarchy installation path with `PREFIX=`. For example:

```sh
# Install under ~/.local.
# Binaries will be at ~/.local/bin
# And manpages will be under ~/.local/share/man
# And supporting data like icons and fonts at ~/.local/share/d2
make install PREFIX=$HOME/.local
```

The install script places the standalone release into `$PREFIX/lib/d2/d2-<version>`
and we recommend doing the same with manually installed releases so that you
know where the release directory is for easy uninstall.

## From source

You can always install from source:

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

You need at least Go v1.27

### Source Release

To install a release from source clone the repository and then:

```sh
./ci/release/build.sh --install
# To uninstall:
# ./ci/release/build.sh --uninstall
```

Installing a real release will also install manpages and in the future other assets like
fonts and icons. Furthermore, when installing a non versioned commit, installing a release
will ensure that `d2 --version` works correctly by embedding the commit hash into the `d2`
binary.

Remember, you need at least Go v1.27

## Windows

We have prebuilt [releases](https://github.com/d2lang/d2/releases) of d2 available for Windows via `.msi` installers. The installer
will add the `d2` binary to your `$PATH` so that you can execute `d2` in `cmd.exe` or
`pwsh.exe`.

### Release archives

We also have release archives for Windows structured in the same way as our Unix releases
for use with MSYS2.

<img width="1680" alt="Screenshot 2022-12-06 at 2 55 27 AM" src="https://user-images.githubusercontent.com/10180857/205892927-6f3e116c-1c4a-440a-9972-82c306aa9779.png">

See [MSYS2](https://www.msys2.org/) or [Git Bash](https://gitforwindows.org/#bash) (Git
Bash is based on MSYS2).

MSYS2 provides a unix style shell environment that is native to Windows (unlike
[Cygwin](https://www.cygwin.com/)). MSYS2 allows `install.sh` to work, enables automatic
installation of our standalone releases via `make install` and makes the manpage
accessible via `man d2`.

The MSYS2 terminal also enables `d2` to display colors like in the above screenshot.

In addition, all of our development and CI scripts work under MSYS2 whereas they do not
under plain Windows.

### WSL

`d2` works perfectly under [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)
aka Windows Subsystem for Linux if that's what you prefer. Installation is just like any
other Linux system.

### Native Package managers

The following are community-managed Windows releases of d2 on popular package managers

#### Scoop

[](https://scoop.sh/#/apps?q=d2&id=06d1259ce6446dd25dafa1a6c57285159ec927b0)
```sh
scoop install main/d2
```

#### Chocolatey
[](https://community.chocolatey.org/packages/d2)
```sh
choco install d2
```

## Docker

The canonical image is [`d2lang/d2`](https://hub.docker.com/r/d2lang/d2).
`terrastruct/d2` remains available as a maintained compatibility mirror for existing
installations, but new usage should use `d2lang/d2`.

We publish `amd64` and `arm64` images based on `debian:latest` for each release.

Example usage:

```sh
echo 'x -> y' >helloworld.d2
docker run --rm -it -u "$(id -u):$(id -g)" -v "$PWD:/home/debian/src" \
  -p 127.0.0.1:8080:8080 d2lang/d2:v0.1.2 --watch helloworld.d2
# Visit http://127.0.0.1:8080
```

## Coming soon

- rpm and deb packages
    - with repositories and standalone
- homebrew core

---

--- METRICS ---
- Files Extracted: 4
- Estimated Token Budget: ~7586 tokens
- Canonical Reference: https://codewiki.google/github.com/d2lang/d2
