Authoring Architecture Decision Records
Mindset
An ADR is a dated, immutable record of one decision and the forces that shaped it, not living documentation. Its value is archaeological: a reader six months from now must understand why a choice was made without asking anyone. Once accepted, an ADR is never edited to change its meaning. When the decision changes, you write a new ADR and mark the old one superseded, preserving the chain of reasoning.
Two rules make an ADR log trustworthy over time. First, numbering is append-only and gap-tolerant: the next number is always max(existing) + 1, never a count of files, so deleting or archiving a record never reuses an identifier. Second, status is the only mutable field: an accepted decision's Context and Decision text are frozen; only its Status flips to Superseded when a later ADR replaces it. The adr CLI enforces both rules, which is why you should reach for it rather than hand-writing files that drift from the template.
Treat the template's section order as a contract. Downstream tooling and reviewers scan for ## Context, ## Decision, and ## Consequences in that order. Reordering or renaming them breaks that expectation even when the prose is good.
Prerequisites
This skill drives the pantheon-adr CLI and is distributed by it
(pantheon-adr skill install). Every step below invokes that binary, so it must
be on PATH. Confirm before proceeding:
pantheon-adr --version
If it is not found, the skill was installed without its companion CLI. Install
the pantheon-adr CLI (its release binary, or cargo install) and retry; there
is no self-contained fallback for these commands.
When to Use
- The user asks to record, write, or draft an architectural or technical decision.
- A significant, hard-to-reverse choice was just made (framework, data store, protocol, boundary) and needs a durable rationale.
- An earlier decision is being replaced and the old record must be marked superseded while keeping its history.
- A repository needs an ADR log bootstrapped under
docs/adr.
- A decision already exists in an existing planning or review document (a design doc, a review, a retrospective) and needs to be captured as an ADR after the fact, rather than authored fresh — see Deriving an ADR from an Existing Document.
When Not to Use
- The change is routine and reversible (a dependency bump, a rename, a config tweak). Use a commit message, not an ADR.
- The user wants prose design documentation or a runbook. ADRs capture a single decision, not a system overview.
- A decision is still being debated with no chosen option. Reach a decision first, or record it with status
Proposed only if the team parks proposals as ADRs.
Principles
- One ADR records exactly one decision. If you are tempted to write "and also", split it into two records.
- Numbers are assigned by the tool from the highest existing record, never guessed or hand-typed.
- Accepted ADRs are immutable except for their Status line. Supersede, do not rewrite.
- The Context must state the forces at play so the decision reads as inevitable, not arbitrary.
- Alternatives Considered is mandatory evidence of due diligence, even when the answer was obvious.
Procedure
- Locate the ADR directory. Default is
docs/adr; a repository may override it with the ADR_DIR environment variable or a --dir flag. Confirm which applies before creating records. Verify: pantheon-adr list --dir <path> runs without error.
- Create the record. Run
pantheon-adr new "<Title>". The tool computes the next number, slugs the title into NNNN-kebab-title.md, and stamps today's date with status Proposed. Verify: the printed path matches the number you expected from pantheon-adr list.
- Fill the template in place. Replace the placeholder prose under Context, Decision, and Consequences. Keep every heading; delete only the placeholder bullet text. Stop if: you cannot articulate at least one entry under each of Positive, Negative, and Neutral consequences; that gap means the decision is not yet understood.
- Record alternatives honestly. For each option not chosen, give its pros, cons, and the specific reason it was rejected. An empty Alternatives section fails review.
- Set the final status. Change
Proposed to Accepted once the decision is ratified. Do not touch any other field after acceptance.
- Supersede when the decision changes. Run
pantheon-adr supersede <old-number> "<New Title>". This flips the old record's Status to Superseded by ADR-NNNN and creates a new Accepted record that references the old one. Verify: pantheon-adr list shows the old record as superseded and the new record directly after it.
Deriving an ADR from an existing document
Sometimes step 3 isn't a blank page: the decision was already made and
written down in a design doc, review, or planning note, and the task is to
capture it as an ADR rather than author it from scratch. The steps above
still apply — the record is still created with pantheon-adr new and still
goes through the same statuses — but recognizing that a document actually
contains a binding decision, and linking the new ADR back to it for
provenance, takes more care than filling in a decision you just made
yourself. See Deriving an ADR from an Existing Document
for how to spot the decision and record the source link.
Quick Commands
# Create the next-numbered ADR from the house template.
pantheon-adr new "Adopt OpenTelemetry for tracing"
Expected result: prints Created docs/adr/0001-adopt-opentelemetry-for-tracing.md (number varies with existing records).
# List every ADR with its number, status, and title.
pantheon-adr list
Expected result: one line per record, e.g. ADR-0001 Accepted Adopt OpenTelemetry for tracing.
# Supersede an earlier decision, marking it and linking the replacement.
pantheon-adr supersede 1 "Adopt Grafana Tempo for tracing"
Expected result: prints the superseded path and the new Created path; the old record's Status becomes Superseded by ADR-0002.
# Work against a non-default ADR directory.
pantheon-adr new "Split the monolith" --dir architecture/decisions
Expected result: the record is created under architecture/decisions.
# Find planning documents with a decision that has no ADR pointing back at it.
scripts/check-undocumented-decisions.sh
Expected result: exit 0 with a confirmation line when everything is covered, or exit 2 with a
list of undocumented files when it finds decision-shaped documents that no ADR's Source: line
references. See Deriving an ADR from an Existing Document.
Anti-Patterns
NEVER hand-number a new ADR
- WHY: Guessing the next number races with other records and reuses identifiers after deletions, corrupting cross-references. The tool derives the number from the highest existing record, which is gap-tolerant.
- BAD: creating
docs/adr/0003-...md by hand because "there are three files" when the highest existing number is 0005.
- GOOD:
pantheon-adr new "...", which assigns max(existing) + 1.
- Consequence: two decisions share ADR-0003 and every link to "ADR-0003" becomes ambiguous.
NEVER edit an accepted ADR to change its decision
- WHY: ADRs are an audit trail. Rewriting the Decision text erases the record that a different choice was once correct and severs the reasoning chain reviewers rely on.
- BAD: opening
0002-...md and replacing "We will use REST" with "We will use gRPC".
- GOOD:
pantheon-adr supersede 2 "Adopt gRPC for internal services", leaving ADR-0002 intact and marked superseded.
- Consequence: history lies; a future reader cannot tell the decision ever changed or why.
NEVER leave the Alternatives Considered section empty
- WHY: The section is the evidence that the decision was weighed against real options. An empty section reads as an unexamined default and fails review.
- BAD:
## Alternatives Considered followed by - N/A.
- GOOD: each rejected option with its pros, cons, and the concrete reason it lost.
- Consequence: reviewers cannot judge whether the decision was sound, so they either block it or rubber-stamp it.
NEVER rename or reorder the template headings
- WHY: Tooling and reviewers scan for the exact headings
## Context, ## Decision, ## Consequences in order. Renaming ## Consequences to ## Trade-offs or moving it breaks that contract.
- BAD: replacing
## Decision with ## What We Chose.
- GOOD: keep the heading text verbatim; put your prose beneath it.
- Consequence: automated ADR indexes and diff reviews silently skip your record's key sections.
NEVER record multiple unrelated decisions in one ADR
- WHY: A record that decides two things cannot be superseded independently. When one half changes you must either fork the record or supersede a still-valid decision.
- BAD: one ADR titled "Database and CI runner choices".
- GOOD: two records,
... Choose PostgreSQL and ... Adopt self-hosted runners.
- Consequence: the log tangles; superseding the database choice wrongly retires the CI decision too.
NEVER commit an ADR while its status is still Proposed as if it were final
- WHY:
Proposed signals an open question. Merging it as the decision of record makes readers act on a choice the team never ratified.
- BAD: merging
**Status:** Proposed and treating it as accepted in downstream work.
- GOOD: flip the Status to
Accepted (or Rejected) once the team decides, then merge.
- Consequence: teams build on a decision that was never actually agreed.
References
- ADR Lifecycle — status transitions, superseding chains, and why accepted records are immutable
- CLI Usage — every adr command, its flags, the ADR_DIR variable, and exit behaviour
- Deriving an ADR from an Existing Document — recognizing a binding decision already written down in a design doc, review, or planning note, and linking the new ADR back to it for provenance
- Documenting Architecture Decisions — Michael Nygard's original essay grounding the ADR practice
- MADR templates — widely used Markdown ADR template variants for comparison
1---2name: adr-creator3description: Creates, lists, and supersedes Architecture Decision Records with the adr CLI, following the house ADR template. Use when recording an architectural decision, writing an ADR, documenting a technical choice, superseding a prior decision, numbering a new decision record, bootstrapping an ADR log under docs/adr.4---56# Authoring Architecture Decision Records78## Mindset910An ADR is a dated, immutable record of one decision and the forces that shaped it, not living documentation. Its value is archaeological: a reader six months from now must understand *why* a choice was made without asking anyone. Once accepted, an ADR is never edited to change its meaning. When the decision changes, you write a new ADR and mark the old one superseded, preserving the chain of reasoning.1112Two rules make an ADR log trustworthy over time. First, **numbering is append-only and gap-tolerant**: the next number is always `max(existing) + 1`, never a count of files, so deleting or archiving a record never reuses an identifier. Second, **status is the only mutable field**: an accepted decision's Context and Decision text are frozen; only its Status flips to `Superseded` when a later ADR replaces it. The `adr` CLI enforces both rules, which is why you should reach for it rather than hand-writing files that drift from the template.1314Treat the template's section order as a contract. Downstream tooling and reviewers scan for `## Context`, `## Decision`, and `## Consequences` in that order. Reordering or renaming them breaks that expectation even when the prose is good.1516## Prerequisites1718This skill drives the `pantheon-adr` CLI and is distributed by it19(`pantheon-adr skill install`). Every step below invokes that binary, so it must20be on `PATH`. Confirm before proceeding:2122```bash23pantheon-adr --version24```2526If it is not found, the skill was installed without its companion CLI. Install27the `pantheon-adr` CLI (its release binary, or `cargo install`) and retry; there28is no self-contained fallback for these commands.2930## When to Use3132- The user asks to record, write, or draft an architectural or technical decision.33- A significant, hard-to-reverse choice was just made (framework, data store, protocol, boundary) and needs a durable rationale.34- An earlier decision is being replaced and the old record must be marked superseded while keeping its history.35- A repository needs an ADR log bootstrapped under `docs/adr`.36- A decision already exists in an existing planning or review document (a design doc, a review, a retrospective) and needs to be captured as an ADR after the fact, rather than authored fresh — see [Deriving an ADR from an Existing Document](references/context-extraction.md).3738## When Not to Use3940- The change is routine and reversible (a dependency bump, a rename, a config tweak). Use a commit message, not an ADR.41- The user wants prose design documentation or a runbook. ADRs capture a single decision, not a system overview.42- A decision is still being debated with no chosen option. Reach a decision first, or record it with status `Proposed` only if the team parks proposals as ADRs.4344## Principles45461. One ADR records exactly one decision. If you are tempted to write "and also", split it into two records.472. Numbers are assigned by the tool from the highest existing record, never guessed or hand-typed.483. Accepted ADRs are immutable except for their Status line. Supersede, do not rewrite.494. The Context must state the forces at play so the decision reads as inevitable, not arbitrary.505. Alternatives Considered is mandatory evidence of due diligence, even when the answer was obvious.5152## Procedure53541. **Locate the ADR directory.** Default is `docs/adr`; a repository may override it with the `ADR_DIR` environment variable or a `--dir` flag. Confirm which applies before creating records. **Verify:** `pantheon-adr list --dir <path>` runs without error.552. **Create the record.** Run `pantheon-adr new "<Title>"`. The tool computes the next number, slugs the title into `NNNN-kebab-title.md`, and stamps today's date with status `Proposed`. **Verify:** the printed path matches the number you expected from `pantheon-adr list`.563. **Fill the template in place.** Replace the placeholder prose under Context, Decision, and Consequences. Keep every heading; delete only the placeholder bullet text. **Stop if:** you cannot articulate at least one entry under each of Positive, Negative, and Neutral consequences; that gap means the decision is not yet understood.574. **Record alternatives honestly.** For each option not chosen, give its pros, cons, and the specific reason it was rejected. An empty Alternatives section fails review.585. **Set the final status.** Change `Proposed` to `Accepted` once the decision is ratified. Do not touch any other field after acceptance.596. **Supersede when the decision changes.** Run `pantheon-adr supersede <old-number> "<New Title>"`. This flips the old record's Status to `Superseded by ADR-NNNN` and creates a new Accepted record that references the old one. **Verify:** `pantheon-adr list` shows the old record as superseded and the new record directly after it.6061### Deriving an ADR from an existing document6263Sometimes step 3 isn't a blank page: the decision was already made and64written down in a design doc, review, or planning note, and the task is to65capture it as an ADR rather than author it from scratch. The steps above66still apply — the record is still created with `pantheon-adr new` and still67goes through the same statuses — but recognizing that a document actually68contains a binding decision, and linking the new ADR back to it for69provenance, takes more care than filling in a decision you just made70yourself. See [Deriving an ADR from an Existing Document](references/context-extraction.md)71for how to spot the decision and record the source link.7273## Quick Commands7475```bash76# Create the next-numbered ADR from the house template.77pantheon-adr new "Adopt OpenTelemetry for tracing"78```7980Expected result: prints `Created docs/adr/0001-adopt-opentelemetry-for-tracing.md` (number varies with existing records).8182```bash83# List every ADR with its number, status, and title.84pantheon-adr list85```8687Expected result: one line per record, e.g. `ADR-0001 Accepted Adopt OpenTelemetry for tracing`.8889```bash90# Supersede an earlier decision, marking it and linking the replacement.91pantheon-adr supersede 1 "Adopt Grafana Tempo for tracing"92```9394Expected result: prints the superseded path and the new `Created` path; the old record's Status becomes `Superseded by ADR-0002`.9596```bash97# Work against a non-default ADR directory.98pantheon-adr new "Split the monolith" --dir architecture/decisions99```100101Expected result: the record is created under `architecture/decisions`.102103```bash104# Find planning documents with a decision that has no ADR pointing back at it.105scripts/check-undocumented-decisions.sh106```107108Expected result: exit 0 with a confirmation line when everything is covered, or exit 2 with a109list of undocumented files when it finds decision-shaped documents that no ADR's `Source:` line110references. See [Deriving an ADR from an Existing Document](references/context-extraction.md).111112## Anti-Patterns113114### NEVER hand-number a new ADR115116- **WHY:** Guessing the next number races with other records and reuses identifiers after deletions, corrupting cross-references. The tool derives the number from the highest existing record, which is gap-tolerant.117- **BAD:** creating `docs/adr/0003-...md` by hand because "there are three files" when the highest existing number is 0005.118- **GOOD:** `pantheon-adr new "..."`, which assigns `max(existing) + 1`.119- **Consequence:** two decisions share ADR-0003 and every link to "ADR-0003" becomes ambiguous.120121### NEVER edit an accepted ADR to change its decision122123- **WHY:** ADRs are an audit trail. Rewriting the Decision text erases the record that a different choice was once correct and severs the reasoning chain reviewers rely on.124- **BAD:** opening `0002-...md` and replacing "We will use REST" with "We will use gRPC".125- **GOOD:** `pantheon-adr supersede 2 "Adopt gRPC for internal services"`, leaving ADR-0002 intact and marked superseded.126- **Consequence:** history lies; a future reader cannot tell the decision ever changed or why.127128### NEVER leave the Alternatives Considered section empty129130- **WHY:** The section is the evidence that the decision was weighed against real options. An empty section reads as an unexamined default and fails review.131- **BAD:** `## Alternatives Considered` followed by `- N/A`.132- **GOOD:** each rejected option with its pros, cons, and the concrete reason it lost.133- **Consequence:** reviewers cannot judge whether the decision was sound, so they either block it or rubber-stamp it.134135### NEVER rename or reorder the template headings136137- **WHY:** Tooling and reviewers scan for the exact headings `## Context`, `## Decision`, `## Consequences` in order. Renaming `## Consequences` to `## Trade-offs` or moving it breaks that contract.138- **BAD:** replacing `## Decision` with `## What We Chose`.139- **GOOD:** keep the heading text verbatim; put your prose beneath it.140- **Consequence:** automated ADR indexes and diff reviews silently skip your record's key sections.141142### NEVER record multiple unrelated decisions in one ADR143144- **WHY:** A record that decides two things cannot be superseded independently. When one half changes you must either fork the record or supersede a still-valid decision.145- **BAD:** one ADR titled "Database and CI runner choices".146- **GOOD:** two records, `... Choose PostgreSQL` and `... Adopt self-hosted runners`.147- **Consequence:** the log tangles; superseding the database choice wrongly retires the CI decision too.148149### NEVER commit an ADR while its status is still Proposed as if it were final150151- **WHY:** `Proposed` signals an open question. Merging it as the decision of record makes readers act on a choice the team never ratified.152- **BAD:** merging `**Status:** Proposed` and treating it as accepted in downstream work.153- **GOOD:** flip the Status to `Accepted` (or `Rejected`) once the team decides, then merge.154- **Consequence:** teams build on a decision that was never actually agreed.155156## References157158- [ADR Lifecycle](references/adr-lifecycle.md) — status transitions, superseding chains, and why accepted records are immutable159- [CLI Usage](references/cli-usage.md) — every adr command, its flags, the ADR_DIR variable, and exit behaviour160- [Deriving an ADR from an Existing Document](references/context-extraction.md) — recognizing a binding decision already written down in a design doc, review, or planning note, and linking the new ADR back to it for provenance161- [Documenting Architecture Decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions) — Michael Nygard's original essay grounding the ADR practice162- [MADR templates](https://adr.github.io/madr/) — widely used Markdown ADR template variants for comparison