Record a design decision as an Architecture Decision Record (ADR) in the project's `docs/adr/` directory. Use this skill whenever the user says "let's ADR this", "record this decision", "write an ADR for X", or when context-sync Phase 3 needs to extract a buried decision. The skill resolves the target ADR directory from cwd, picks the next sequence number with no collision, delegates 7-section body generation (incl. `Review-when` expiry conditions) to the adr-writer agent, and updates the ADR...
Scanned 9/4/2026
Install to Claude Code
npx -y skills add shimo4228/claude-harness --skill adr-writer --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Adr Writer?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/shimo4228-adr-writer)More formats (shields.io, HTML) on the badges page.
---
name: adr-writer
description: Record a design decision as an Architecture Decision Record (ADR) in the project's `docs/adr/` directory. Use this skill whenever the user says "let's ADR this", "record this decision", "write an ADR for X", or when context-sync Phase 3 needs to extract a buried decision. The skill resolves the target ADR directory from cwd, picks the next sequence number with no collision, delegates 7-section body generation (incl. `Review-when` expiry conditions) to the adr-writer agent, and updates the ADR index. Works across any repo — auto-detects or creates `docs/adr/` from the repo root.
user-invocable: true
origin: shimo4228
---
# ADR Writer
Capture a design decision as a numbered ADR with consistent structure. The skill handles the boilerplate (directory detection, sequence numbering, index update); the `adr-writer` agent handles the prose.
## Why a Skill + Agent Split
The skill owns deterministic concerns: where the ADR goes, what number it gets, which index needs updating. These are easy to get wrong silently (number collisions, sub-directory cwd confusion, index drift) so they live in scripted steps.
The agent owns **rendering**, not deciding: given a frozen, already-approved decision packet, it re-expresses each section into the template, calibrates against neighbouring ADRs' house style, resolves links, and writes the file. What the ADR *means* — the real Context, the actual Decision, why each Alternative was rejected, which Consequences follow — is a **semantic decision that stays with the caller (the main loop)**. The agent has no authority to infer or invent it; it refuses to write when the packet is incomplete. See [ADR-0016](../../docs/adr/0016-writer-agents-render-not-decide.md) — writer agents render, they do not decide. (This split does not exist merely to isolate context: rendering to a fixed house-style template is low-authority and cheaply verifiable, which is exactly what makes delegation safe here — unlike translation, whose prose carries the author's non-convergent voice and stays in the main loop.)
## When to Use
- The user says "let's ADR this", "record this decision", "write an ADR for X"
- `context-sync` Phase 3 has extracted a decision from CLAUDE.md / README that needs ADR form
- The user is about to merge a PR with an irreversible architectural change and wants a record
- A debate concluded in chat and the user wants the outcome durable
## When NOT to Use
- Bug fix records (use the commit message)
- Reversible refactors (commit message is enough)
- Personal preferences ("I like spaces over tabs") — those go in a style guide, not an ADR
## Workflow
### Step 1: Resolve the ADR directory
```bash
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || REPO_ROOT="$(pwd)"
ADR_DIR="$REPO_ROOT/docs/adr"
```
If `$ADR_DIR` does not exist, create it — the ADR request itself covers the directory, and
git makes it reversible. Mention the creation in your final report. Write a minimal
`README.md` index alongside:
````markdown
# Architecture Decision Records
## Index
| ADR | Title | Status | Date |
|-----|-------|--------|------|
## Template
ADRs in this repository use the 7-section template
(`scripts/adr_lint.py` checks section presence mechanically):
```markdown
# ADR-NNNN: [Title]
## Status
accepted | superseded | deprecated
## Date
YYYY-MM-DD
## Context
[what was the problem]
## Decision
[what was decided]
## Review-when
[expiry conditions — an ADR is a dated hypothesis, not a permanent constraint]
## Alternatives Considered
[rejected options and why]
## Consequences
[what becomes easier / harder]
```
File name: `NNNN-kebab-case-title.md` (zero-padded 4-digit sequence).
Index rows link the number: `| [NNNN](NNNN-slug.md) | Title | status | YYYY-MM-DD |`.
````
(インデックス行は番号を相対リンクにする — harness / CA 等の既存 index と同形。
`adr_lint.py` はこの README の Template fenced block から期待節セットを読むので、
README を置くことが lint のテンプレ宣言を兼ねる。)
If the user declines, stop and explain that ADRs need a directory.
### Step 2: Pick the next sequence number
```bash
LAST_NUM=$(ls "$ADR_DIR"/[0-9]*-*.md 2>/dev/null | sort -V | tail -1 | sed -E 's|.*/([0-9]+)-.*|\1|')
if [ -z "$LAST_NUM" ]; then
NEXT_NUM="0001"
else
NEXT_NUM=$(printf "%04d" $((10#$LAST_NUM + 1)))
fi
```
Verify uniqueness right before writing (race safety):
```bash
[ -e "$ADR_DIR/$NEXT_NUM-"*.md ] && echo "COLLISION" || echo "OK"
```
If `COLLISION`, recompute `NEXT_NUM` from the latest state.
### Step 3: Gather the 7 inputs
Ask the user (or accept from caller) for:
1. **Title** — short, kebab-case-friendly (e.g., `context-sync-cascade-and-writer-agents`). The skill will compose the filename.
2. **Status** — `proposed | accepted | superseded | deprecated`. Default `accepted`.
3. **Context** — what problem prompted this decision (raw text OK).
4. **Decision** — what was decided (raw text OK).
5. **Review-when** — the expiry conditions (失効条件): which observation or premise failure would void or weaken this decision, 1-3 lines. It can only be captured at write time (ADR-0021); an ADR without it reads as permanent. If there genuinely is none, say so explicitly — the agent renders 「無し — 恒久判断ではなく記録」.
6. **Alternatives** — what else was considered and why rejected, or, for an alternative that stays live, 「未決 — 再訪条件: …」 (raw text or list). Keeping a rival open is allowed; a straw man is not.
7. **Consequences** — what becomes easier / harder (raw text or list).
If 3-7 are missing, request them — do not proceed. ADRs without these sections are noise.
**予防チェック(packet 確定前).** [references/review-findings.md](references/review-findings.md)
(レビュー頻出指摘の日付つき事例集)を読み、該当パターンを自己点検する — 引用 ADR の
実在と内容一致、surviving scope の置き場所、造語の出所、full/partial supersede の判定根拠、
gitignored パス参照、数値の出典と分母、カウント条件の固定対象。これは書き時の予防であって
意味的レビューの代替ではない — commit 前の adr-reviewer は省略しない。
**Assemble and approve the decision packet before delegating.** The main loop holds the semantic authority for this ADR, so it — not the agent — must settle the actual content: the real Context, the decision as decided, the Review-when triggers, why each Alternative was rejected (or under what condition it is revisited), which Consequences genuinely follow. Confirm this packet with the user (especially the Review-when, the rejection reasons and both sides of Consequences) *before* Step 4. The agent that follows only renders what you hand it; it will not fill a gap you leave. If the decision is still fuzzy, resolve it here in the main loop — do not expect the agent to infer it.
### Step 4: Delegate body generation to the adr-writer agent
Invoke the `adr-writer` agent via the Agent tool with:
- ADR number (`$NEXT_NUM`)
- Repo root (`$REPO_ROOT`)
- ADR directory (`$ADR_DIR`)
- Title (kebab-case slug)
- Status / Date / Context / Decision / Review-when / Alternatives / Consequences
The agent will:
- Read the 2 most recent ADRs in `$ADR_DIR` for style calibration
- Fill the 7 sections from your input (no invention)
- Write the file at `$ADR_DIR/$NEXT_NUM-<title>.md`
- Return a summary block
If the agent returns "needs more input", surface the missing-fields message to the user and stop. Do not push partial ADRs.
**Fidelity check (main loop, after the agent writes).** Because the agent only renders, verify it added nothing semantic: read the written file and confirm every Context fact, Decision clause, rejection reason, and Consequence traces back to the packet you approved in Step 3. If the agent introduced an inferred claim (a "logically entailed" consequence, an unstated rationale), strike it or send it back — the render must not exceed the packet.
### Step 4.5: Run the mechanical lint
```bash
python3 ~/.claude/skills/adr-writer/scripts/adr_lint.py --root "$REPO_ROOT"
```
Evidence モード(判定しない・exit 0)。出力 JSON のうち**今書いた ADR に関する逸脱**
(missing_sections / case_mismatch / status / date / index / naming)を修正してから先へ進む。
既存 ADR の逸脱は報告のみ — このステップで直さない(別タスク)。lint の検査範囲は機械的
性質のみで、意味的レビュー(adr-reviewer)の代替ではない。
ad hoc で blocking 判定が欲しいときは `--gate` を足す。免除境界は既定で無制限なので
repo ごとの値を渡す — harness は `--sections-from 44 --require-review-when-from 44`
(ADR-0009 の 2 節欠落と 0043 以前の Review-when 無しを免除、ADR-0051)。
### Step 4.6: Run the semantic review (adr-reviewer)
commit 前に agent: `adr-reviewer` を起動して今書いた ADR を渡す — 省略しない。
**この skill が adr-reviewer の唯一の配線**(ADR-0055 で implementation-chain の Review 表
から外れた)。指摘は Step 3 の packet に照らして主ループが採否を決め、採った分だけ直す。
### Step 5: Update the index
After the agent confirms file written, append a row to `$ADR_DIR/README.md` index table:
```bash
# Read current index
# Find the table block (lines between "| ID |" header and the next "##" heading)
# Append: | $NEXT_NUM | <title human-readable> | <status> | <date> |
```
If the index table is malformed or absent, regenerate it from the directory:
```bash
for f in "$ADR_DIR"/[0-9]*-*.md; do
num=$(basename "$f" | sed -E 's|([0-9]+)-.*|\1|')
title=$(head -1 "$f" | sed -E 's|^# ADR-[0-9]+: ||')
status=$(awk '/^## Status/{getline; getline; print; exit}' "$f")
date=$(awk '/^## Date/{getline; getline; print; exit}' "$f")
echo "| $num | $title | $status | $date |"
done
```
### Step 6: Report
Tell the user:
```
ADR written
---
File: docs/adr/<NNNN>-<title>.md
Number: <NNNN>
Status: <status>
Index: updated (+1 row)
```
## Edge cases
| Case | Handling |
|---|---|
| Called from a sub-directory of the repo | Use `git rev-parse --show-toplevel`; never trust raw cwd |
| Not a git repo | Fall back to cwd, warn the user that they should `git init` |
| ADR number was reserved verbally but not yet written ("I'll write ADR-0010 later") | Skill cannot know; ask the user whether to take the next free number or the reserved one |
| User wants to supersede an existing ADR | Update the old ADR's Status to `superseded by ADR-NNNN`, then create the new one. Two file writes. |
| New ADR **partially weakens** an old one (a premise expired, a Review-when trigger fired) but does not supersede it | Do not flip Status. Append under the affected section of the old ADR: `> **注記(YYYY-MM-DD, ADR-NNNN)**: <what changed and what still stands>`. Never delete the original text — the strength history stays readable in place (precedents: ADR-0018 §Consequences, ADR-0028). This is a main-loop step after the agent has written the new file. |
| Title contains spaces or non-ASCII | Skill normalizes to kebab-case ASCII for the filename; preserves original in the `# ADR-NNNN: ...` heading |
## Boundaries
- **Do not** invent missing sections. Refuse to write an ADR with `Context: [TBD]` or similar placeholders.
- **Do not** modify ADRs other than the new one and (optionally) the index, except the two explicit main-loop steps above (Status flip on full supersede; dated 注記 on partial weakening). The `adr-writer` agent itself never touches an existing ADR (ADR-0016).
- **Do not** infer the user's decision from chat history without confirming. Ask, even if the answer feels obvious.
- **Do not** commit the file. The user owns the commit step.
## Reference Files
- ADR template canonical source: read the target repo's existing ADRs to mirror their voice. For the harness itself, see `~/.claude/docs/adr/README.md`.
- Agent that fills the body: `~/.claude/agents/adr-writer.md`.
- Mechanical lint (evidence mode + `--gate`): `scripts/adr_lint.py`(ADR-0051。repo の
`docs/adr/README.md` Template からテンプレを自動適応、tests は `tests/test_adr_lint.py`)。
- レビュー頻出指摘の事例集: `references/review-findings.md`(Step 3 の予防チェックで読む)。
- Evals: `evals/evals.json` (3 scenarios — new ADR / missing docs-adr / sequence collision).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!