Turn an architectural decision into a durable, reviewable record. The skill takes the decision the user describes, gathers the real constraints that shaped it from the repository, and writes a Nygard-style Architecture Decision Record — context and problem, the decision and its status, the consequences, and the alternatives that were considered and rejected. The result is a numbered, immutable document that explains why a choice was made to whoever reads the code in two years.
When to use this skill
- You made a consequential, hard-to-reverse choice (datastore, framework, auth model, sync vs. async, monorepo vs. polyrepo) and want the reasoning captured before it's forgotten.
- You're starting an ADR log in a repo that has none, or adding the next record to an existing
docs/adr/ directory.
- A pull request changes architecture and a reviewer asked "where is this written down?"
- You're revisiting an old decision and need to supersede it with a new record instead of silently editing history.
[!NOTE]
An ADR is immutable once merged. You don't edit a decision to change it — you write a new ADR that supersedes it and flip the old one's status to Superseded by ADR-NNNN. Editing the substance of a merged record erases the history the log exists to preserve.
Instructions
- Locate the ADR log. Search for an existing directory —
docs/adr/, docs/decisions/, doc/adr/, or adr/. Read one or two existing records to match the local heading set, status vocabulary, and front-matter (some logs use MADR, some Nygard, some carry a date:/deciders: block). If no log exists, default to docs/adr/.
- Assign the number and slug. Find the highest existing
NNNN-*.md and increment it, zero-padded to four digits (0001, 0002, ...). Build the filename as docs/adr/NNNN-kebab-title.md from a short, decision-focused title (0007-use-postgres-for-primary-store.md). Never reuse or renumber an existing file.
- Detect the real constraints — don't invent them. Mine the repo for evidence that shaped the decision instead of writing generic pros and cons:
- Read
package.json / requirements.txt / go.mod / Cargo.toml for the current stack and what's already a dependency.
- Grep for the systems in play (
grep -ri "mongoose\|prisma\|pg\|sqlalchemy") to see what's actually wired up.
- Check
docker-compose.yml, *.tf, CI config, and any README/CLAUDE.md for deployment targets, scale signals, and stated team conventions.
- Note the requirement that forces the decision (transactions, relational queries, a managed offering already in the cloud account, an existing team skillset).
- Write the record. Use the Nygard section order:
# NNNN. Title, then ## Status, ## Context, ## Decision, ## Consequences (split into positive and negative — be honest about the costs you're accepting), and ## Considered Alternatives (an added section not in Nygard's original — list each rejected option with the specific reason it lost). Write in past/decided tense, name concrete tradeoffs, and cite the constraints from step 3 rather than restating textbook definitions.
- Set the status deliberately. Use
Proposed for an open decision under review, Accepted once it's agreed, Deprecated for an outdated record, or Superseded by ADR-NNNN when replaced. If this record retires an older one, update that file's status line to point here.
- Verify and report. Confirm the filename number is unique, the title slug matches the heading, and every alternative has a stated reason for rejection. List the file you wrote, and flag any section you filled from assumption rather than repo evidence so the user can correct it before merging.
[!WARNING]
Don't pad the Consequences with only upsides. An ADR that lists no negative consequences is a sales pitch, not a decision record — the reviewer can't weigh a tradeoff you hid. Name the lock-in, the operational cost, or the capability you gave up.
Examples
For the decision "choose Postgres over MongoDB for the primary datastore," the skill detects no mongoose/prisma is wired yet, sees a managed Postgres already in the cloud account, and writes docs/adr/0001-use-postgres-as-primary-datastore.md:
# 0001. Use PostgreSQL as the primary datastore
## Status
Accepted — 2026-06-03
## Context
The billing and account services need ACID transactions across orders,
invoices, and ledger entries, and most read paths join three or more
entities. Our data is strongly relational with a stable schema. The team
already operates a managed Postgres instance in the existing cloud account
and knows SQL; no one has run MongoDB in production here.
## Decision
We will use PostgreSQL 16 as the primary datastore for all transactional
services, accessed through a single connection pool per service. Document-
shaped, schemaless data (audit blobs, webhook payloads) will live in
`jsonb` columns rather than a separate document database.
## Consequences
**Positive**
- Multi-row transactions and foreign keys enforce invariants in the
database instead of in application code.
- One datastore to operate, back up, and monitor — reuses the managed
instance and the team's existing SQL skills.
- `jsonb` covers the few semi-structured cases without a second system.
**Negative**
- Horizontal write scaling requires deliberate work (partitioning, read
replicas) if write volume outgrows a single primary.
- Schema changes need migrations and review; less forgiving than a
schemaless store during rapid early iteration.
## Considered Alternatives
- **MongoDB** — rejected: our access patterns are relational and need
cross-document transactions, which fight against its document model and
would push join logic into the application.
- **Postgres + a separate document DB** — rejected: doubles operational
surface for a small amount of semi-structured data that `jsonb` handles.
- **SQLite** — rejected: no managed multi-writer story for our concurrency
and availability needs.
After writing, report the path and note any section (e.g. projected write volume) that came from an assumption rather than a measured constraint, so the user can verify it before merging.
1---2name: adr-writer3description: Write an Architecture Decision Record capturing a decision the user describes, in Michael Nygard ADR format (Status, Context, Decision, Consequences) with an added Considered Alternatives section. Use when recording a significant architectural or technology choice.4---56Turn an architectural decision into a durable, reviewable record. The skill takes the decision the user describes, gathers the real constraints that shaped it from the repository, and writes a Nygard-style Architecture Decision Record — context and problem, the decision and its status, the consequences, and the alternatives that were considered and rejected. The result is a numbered, immutable document that explains *why* a choice was made to whoever reads the code in two years.78## When to use this skill910- You made a consequential, hard-to-reverse choice (datastore, framework, auth model, sync vs. async, monorepo vs. polyrepo) and want the reasoning captured before it's forgotten.11- You're starting an ADR log in a repo that has none, or adding the next record to an existing `docs/adr/` directory.12- A pull request changes architecture and a reviewer asked "where is this written down?"13- You're revisiting an old decision and need to supersede it with a new record instead of silently editing history.1415> [!NOTE]16> An ADR is immutable once merged. You don't edit a decision to change it — you write a new ADR that supersedes it and flip the old one's status to `Superseded by ADR-NNNN`. Editing the substance of a merged record erases the history the log exists to preserve.1718## Instructions19201. **Locate the ADR log.** Search for an existing directory — `docs/adr/`, `docs/decisions/`, `doc/adr/`, or `adr/`. Read one or two existing records to match the local heading set, status vocabulary, and front-matter (some logs use `MADR`, some `Nygard`, some carry a `date:`/`deciders:` block). If no log exists, default to `docs/adr/`.212. **Assign the number and slug.** Find the highest existing `NNNN-*.md` and increment it, zero-padded to four digits (`0001`, `0002`, ...). Build the filename as `docs/adr/NNNN-kebab-title.md` from a short, decision-focused title (`0007-use-postgres-for-primary-store.md`). Never reuse or renumber an existing file.223. **Detect the real constraints — don't invent them.** Mine the repo for evidence that shaped the decision instead of writing generic pros and cons:23 - Read `package.json` / `requirements.txt` / `go.mod` / `Cargo.toml` for the current stack and what's already a dependency.24 - Grep for the systems in play (`grep -ri "mongoose\|prisma\|pg\|sqlalchemy"`) to see what's actually wired up.25 - Check `docker-compose.yml`, `*.tf`, CI config, and any `README`/`CLAUDE.md` for deployment targets, scale signals, and stated team conventions.26 - Note the requirement that forces the decision (transactions, relational queries, a managed offering already in the cloud account, an existing team skillset).274. **Write the record.** Use the Nygard section order: `# NNNN. Title`, then `## Status`, `## Context`, `## Decision`, `## Consequences` (split into *positive* and *negative* — be honest about the costs you're accepting), and `## Considered Alternatives` (an added section not in Nygard's original — list each rejected option with the specific reason it lost). Write in past/decided tense, name concrete tradeoffs, and cite the constraints from step 3 rather than restating textbook definitions.285. **Set the status deliberately.** Use `Proposed` for an open decision under review, `Accepted` once it's agreed, `Deprecated` for an outdated record, or `Superseded by ADR-NNNN` when replaced. If this record retires an older one, update that file's status line to point here.296. **Verify and report.** Confirm the filename number is unique, the title slug matches the heading, and every alternative has a stated reason for rejection. List the file you wrote, and flag any section you filled from assumption rather than repo evidence so the user can correct it before merging.3031> [!WARNING]32> Don't pad the Consequences with only upsides. An ADR that lists no negative consequences is a sales pitch, not a decision record — the reviewer can't weigh a tradeoff you hid. Name the lock-in, the operational cost, or the capability you gave up.3334## Examples3536For the decision "choose Postgres over MongoDB for the primary datastore," the skill detects no `mongoose`/`prisma` is wired yet, sees a managed Postgres already in the cloud account, and writes `docs/adr/0001-use-postgres-as-primary-datastore.md`:3738```markdown39# 0001. Use PostgreSQL as the primary datastore4041## Status4243Accepted — 2026-06-034445## Context4647The billing and account services need ACID transactions across orders,48invoices, and ledger entries, and most read paths join three or more49entities. Our data is strongly relational with a stable schema. The team50already operates a managed Postgres instance in the existing cloud account51and knows SQL; no one has run MongoDB in production here.5253## Decision5455We will use PostgreSQL 16 as the primary datastore for all transactional56services, accessed through a single connection pool per service. Document-57shaped, schemaless data (audit blobs, webhook payloads) will live in58`jsonb` columns rather than a separate document database.5960## Consequences6162**Positive**6364- Multi-row transactions and foreign keys enforce invariants in the65 database instead of in application code.66- One datastore to operate, back up, and monitor — reuses the managed67 instance and the team's existing SQL skills.68- `jsonb` covers the few semi-structured cases without a second system.6970**Negative**7172- Horizontal write scaling requires deliberate work (partitioning, read73 replicas) if write volume outgrows a single primary.74- Schema changes need migrations and review; less forgiving than a75 schemaless store during rapid early iteration.7677## Considered Alternatives7879- **MongoDB** — rejected: our access patterns are relational and need80 cross-document transactions, which fight against its document model and81 would push join logic into the application.82- **Postgres + a separate document DB** — rejected: doubles operational83 surface for a small amount of semi-structured data that `jsonb` handles.84- **SQLite** — rejected: no managed multi-writer story for our concurrency85 and availability needs.86```8788After writing, report the path and note any section (e.g. projected write volume) that came from an assumption rather than a measured constraint, so the user can verify it before merging.