Command-by-command reference for specwright. For the why and how it fits together, see architecture.md. For a fully-worked example, see walkthrough.md.
cd <your-project>
claude
> /init # Standard Claude Code init (writes a basic CLAUDE.md)
> /sd:setup # specwright scaffold
/init is optional but recommended. It creates a baseline CLAUDE.md that /sd:setup can parse for stack hints.
/sd:setup is interactive and asks at most 3 questions:
- Ticket system (JIRA / GitHub / Linear / none).
- Ticket pattern (regex like
^[A-Z]+-[0-9]+$). - Shell (PowerShell / bash / both).
It generates:
<repo>/
├── CLAUDE.md (overwrites with backup if present)
├── .specs/
│ ├── constitution.md (with <<placeholder>> tokens to fill)
│ ├── index.md (empty registry)
│ ├── _explorations/ (scratchpad for /sd:explore saves)
│ ├── _reviews/ (scratchpad for /sd:review saves)
│ └── _adr/ (architecture decision records)
└── .claude/
├── project-config.json
└── settings.json
After running, open CLAUDE.md and .specs/constitution.md in your editor and fill the placeholders. /sd:setup does not infer your conventions; you declare them.
Spec-driven feature workflow.
| Phase | Subagent / Actor | Gate |
|---|---|---|
| 0 - Bootstrap | main thread | - |
| 1 - Spec | sd-spec-architect |
⛔ Gate 1 (spec approval) |
| 2 - Impact | sd-code-explorer |
- |
| 3 - Plan + tasks | sd-spec-architect |
⛔ Gate 2 (plan approval; complexity triage) |
| 4 - Execute | sd-implementer per task + main thread self-check |
- |
| 5 - Integration + batch review | main thread + sd-reviewer (holistic, once) |
⛔ Gate 3 (integration + review) |
| 6 - Close-out | main thread | - |
Spec ID: FEAT-<arg>. State machine on re-invocation: detected state -> resume at next phase.
Phase 2 records the codebase's precedents and conventions (nearest similar implementations, naming patterns, existing utilities) alongside the impact map. Phase 3 tasks then carry Pattern refs - file:line citations of precedent code the implementer must read before writing, so new code mirrors the existing structure.
The architect writes a spec-level complexity estimate (S | M | L) at Phase 1. Gate 2 then measures the actual plan: under the decompose thresholds (> 8 tasks, > 2 production layers excluding Tests/Config, > 8 impacted files, or an unresolved Open question) it is the normal plan approval with zero added friction; over them it becomes a HARD Gate Complexity that refuses one oversized plan and forces a split into medium child specs (FEAT-<arg>-<slug>, linked to the parent umbrella). A create-time L estimate also escalates the impact and planning models a tier (aliases only). Still 3 hard gates - complexity triage is a second face of Gate 2, not a fourth gate.
Example:
/sd:feature INV-2501
With JIRA enabled and ticket pattern matching INV-2501, the architect fetches the ticket and includes it in the spec context. It also snapshots the ticket content, its related tickets (1 hop), and linked Confluence pages to .specs/FEAT-INV-2501/04-artifacts/ticket/ as durable evidence - caps configurable via ticket.snapshot in project-config.
Root-cause-first bug fix. Refuses to fix without reproduction confirmed AND root cause documented.
| Phase | Subagent / Actor | Gate |
|---|---|---|
| 0 - Bootstrap | main thread | - |
| 1 - Capture symptoms | sd-spec-architect |
⛔ Gate 1 |
| 2 - Reproduce | main thread (interactive) | ⛔ Gate 2 (HARD - no override) |
| 3 - Investigate | sd-debugger (enumerate + verify) |
⛔ Gate 3 (root cause confirmed) |
| 4 - Write failing test FIRST | main thread | ⛔ Gate 4 (test fails as expected) |
| 5 - Minimal fix | sd-implementer |
- |
| 6 - Regression + review | sd-reviewer (bug-fix-final) |
⛔ Gate 5 |
| 7 - Close-out | main thread | - |
Spec ID: BUG-<arg>.
Example:
/sd:bug 1247
Incident analysis. No code is changed in this workflow. Output IS the spec.
| Phase | Subagent / Actor | Gate |
|---|---|---|
| 0 - Bootstrap | main thread | - |
| 1 - Gather signals | main thread (interactive) | ⛔ Gate 1 (evidence gathered) |
| 2 - Hypothesis enumeration | sd-debugger (enumerate, incident mode) |
⛔ Gate 2 |
| 3 - Verify loop | sd-debugger (verify) |
⛔ Gate 3 (root cause confirmed) |
| 4 - Isolate + document | main thread | - |
| 5 - Follow-up actions | main thread | - |
Spec ID: RCA-<slug>-<YYYYMMDD>.
Fixes spawn separate BUG-*, REF-*, or PERF-* specs (reserved IDs listed under "Spawned specs" in the RCA).
Example:
/sd:rca payment-outage-jan8
Coverage-gated refactor. Refuses to touch code if coverage on affected files is below threshold (default 80%).
| Phase | Subagent / Actor | Gate |
|---|---|---|
| 0 - Bootstrap | main thread | - |
| 1 - Spec | sd-spec-architect |
⛔ Gate 1 |
| 2 - Impact | sd-code-explorer |
- |
| 3 - Coverage | main thread (runs commands.coverage) |
⛔ Gate 2 (threshold) + ⛔ Gate 3 (post-tests) |
| 4 - Plan parallel-safe tasks | sd-spec-architect |
⛔ Gate 4 |
| 5 - Execute batched (max 3 parallel) | sd-implementer per task |
⛔ Gate 5 (per-batch tests green) |
| 6 - Holistic review | sd-reviewer (holistic) |
⛔ Gate 6 |
| 7 - Close-out | main thread | - |
Spec ID: REF-<slug>-<YYYYMMDD>.
Example:
/sd:refactor extract-pricing-service extract-class
Baseline-first optimization. Refuses to optimize without a measured baseline.
| Phase | Subagent / Actor | Gate |
|---|---|---|
| 0 - Bootstrap | main thread | - |
| 1 - Define target | sd-spec-architect |
⛔ Gate 1 |
| 2 - Baseline measurement | main thread | ⛔ Gate 2 (HARD) |
| 3 - Identify hotspot | sd-debugger (hotspot-analysis A) |
⛔ Gate 3 |
| 4 - Per-hotspot loop | sd-debugger (sub B) + sd-implementer + re-measure |
⛔ Gates 4-6 (hypothesis / correctness / keep-or-revert) |
| 5 - Regression check | main thread | ⛔ Gate 7 |
| 6 - Final review + close | sd-reviewer (perf-final) |
⛔ Gate 8 |
Spec ID: PERF-<slug>-<YYYYMMDD>.
Example:
/sd:perf search-endpoint-latency
Fidelity-first port. The donor is the specification - every departure is a row in the deviation table, or it is a defect. Reproduces a donor implementation inside this host repo, with a justified-diff parity review as the close-out gate.
| Phase | Subagent / Actor | Gate |
|---|---|---|
| 0 - Bootstrap (args, port policy) | main thread | - |
| 1 - Consume bridged contract / in-repo extract | main thread + sd-code-explorer (port-extract, in-repo only) + sd-spec-architect (create) |
- |
| 2 - Freeze snapshot | main thread | Gate 1 (HARD) |
| 3 - Host survey | sd-code-explorer (impact-map) + main thread constitution scan |
- |
| 4 - Fidelity tables | sd-spec-architect (refine) |
Gate 2 (HARD) |
| 5 - Pin behavior | main thread + sd-implementer |
Gate 3 (HARD) |
| 6 - Plan atomic tasks | sd-spec-architect (plan) |
Gate 4 |
| 7 - Execute batched | sd-implementer per task |
Gate 5 |
| 8 - Parity review | main thread + sd-reviewer (port-parity) |
Gate 6 (HARD) |
| 9 - Close-out | main thread | - |
Spec ID: PORT-<slug>-<YYYYMMDD>. --scope (endpoint / module / feature / pattern) is
explicit - Phase 0 asks when it is omitted and never infers it, because a wrong guess changes the
behavior-pinning mechanism used at Gate 3. --from selects topology: a bridged (cross-repo)
contract artifact produced by /sd:explore --port in the donor repo, or an in-repo path/symbol for
intra-repo duplication - the rest of the pipeline is identical either way.
Phase 5's pinning mechanism follows scope: endpoint gets a contract test suite runnable against
donor and host; module gets characterization tests through an interface-typed construction seam
so re-pointing changes exactly one factory method; feature uses whichever the surface allows;
pattern skips pinning (there is no donor instance) but still proves the host tree is unmodified.
Phase 6's complexity triage uses a port-specific metric - the count of deviation-table rows requiring adaptation, not the impacted-file count the other workflows use, because a port's file count equals the donor's by construction and would trip on nearly every port regardless of how much judgment the work needs.
Phase 0 reads the port policy from a Port policy heading in .specs/constitution.md and always
states the effective policy in its output, including the fallback (structural mirror, per
sd-port-fidelity) when the host constitution declares nothing.
Example:
/sd:port order-intake --from .specs/_explorations/order-intake-20260809-1200/ --scope endpoint
/sd:port order-intake --from src/orders/order-intake --scope module
Spec registry. No code is changed. No subagent is invoked.
| Subcommand | Args | Use |
|---|---|---|
list |
[type] [status] |
Filtered list of specs |
show |
<ID> |
Frontmatter + section summary + task completion |
status |
<ID> <new-state> |
Validated lifecycle transition (logs to retro) |
link |
<ID-A> <relation> <ID-B> |
Cross-reference (depends-on, related-to, spawned-by, ...) |
archive |
<ID> |
Move from done to archived |
revive |
<ID> [reason] |
Move from archived to in-progress |
search |
<term> |
Full-text grep across spec bodies |
validate |
[ID or --all] |
Verify frontmatter + structure + index consistency |
stats |
- | Counts + aging report |
help |
- | Print subcommand list |
Examples:
/sd:spec list bug in-progress
/sd:spec show FEAT-INV-2501
/sd:spec status BUG-1247 done
/sd:spec link FEAT-INV-2501 depends-on REF-extract-pricing-20260112
/sd:spec search "low-stock"
/sd:spec stats
Read-only code navigation. Single sd-code-explorer invocation. No spec created.
The command parses your query for intent:
- "where is X" / "define X" -> definition mode.
- "who calls X" / "callers of X" -> callers mode.
- "trace X" -> call-graph trace.
- "what depends on X" / "impact of changing X" -> impact map.
- "show all X" / pattern -> grep pattern search.
- "structure of X" -> directory + symbols overview.
Output includes file:line citations for every finding. Offers to save to .specs/_explorations/<slug>-<timestamp>.md.
Examples:
/sd:explore where is PaymentHandler defined
/sd:explore who calls UserService.GetById
/sd:explore impact of changing StockReservation
/sd:explore show all places that use Redis
Standalone compliance review. Constitution required - aborts if missing.
Four modes:
<path>- review a file or directory.recentorrecent <N>h- files modified in the last N hours (default 4).spec <ID>- changed files associated with a spec.- (no args) - interactive prompt to pick a mode.
Output: severity-tagged findings 🔴 BLOCK / 🟠 WARN / 🟡 SUGGEST / 🟢 PASS, each citing file:line and a constitution §N.M.
Examples:
/sd:review src/Application/Payment
/sd:review recent 4h
/sd:review spec BUG-1247
Already covered above. Re-runnable. Detects state (fresh / post-init / partial / complete) and only fills gaps. Backs up any file before overwriting.
Cut a release from completed specs. No code is changed. No subagent is invoked. Pure file ops, like /sd:spec.
Collects every spec currently in done (types feature / bug / refactor / perf / port - RCA is never released), groups them into Keep-a-Changelog sections, writes a versioned section to the project CHANGELOG.md, then transitions each released spec done -> archived.
| Phase | Actor | Gate |
|---|---|---|
| 0 - Bootstrap | main thread | - |
1 - Collect done specs |
main thread | - |
| 2 - Group into sections | main thread | - |
| 3 - Determine version | main thread | - |
| 4 - Preview + confirm | main thread | ⛔ Gate 1 (HARD - preview before any write) |
| 5 - Write CHANGELOG + archive | main thread | - |
| 6 - Report | main thread | - |
Type-to-section mapping: feature + port -> Added, bug -> Fixed, refactor + perf -> Changed.
Version is inferred when omitted (any feature -> minor bump, else patch; major is never auto-inferred - pass it explicitly). --dry-run renders the notes and the archive plan, then stops without writing.
The lifecycle distinction this relies on: done = merged but not yet shipped; archived = shipped in a release.
Examples:
/sd:release # infer version, preview, confirm, write
/sd:release 2.0.0 # explicit version (e.g. a major)
/sd:release --dry-run # preview only, write nothing
Promotes a durable decision into a numbered, MADR-style ADR under .specs/_adr/. Drives the sd-docs-writer agent.
Argument: a spec ID (e.g. FEAT-012) whose 03-decisions.md holds the decision, or a free-text decision title for an ad-hoc ADR with no spec.
| Phase | Actor | Gate |
|---|---|---|
| 0 - Bootstrap | main thread | - |
| 1 - Resolve decision source | main thread | - |
| 2 - Assign number and slug | main thread | - |
| 3 - Draft ADR | sd-docs-writer |
- |
| Gate - approve before keeping | main thread | ⛔ Gate 1 (HARD - nothing is kept without approval) |
| 4 - Report | main thread | - |
Numbers are 4-digit, sequential (0001-, 0002-, ...), derived by scanning .specs/_adr/. The
agent never invents decisions - an empty or absent 03-decisions.md aborts the command. ADRs are
not specs: they have no .specs/index.md lifecycle entry.
Examples:
/sd:adr FEAT-012 # ADR from an existing spec's decisions
/sd:adr "Adopt CQRS for the order service" # ad-hoc ADR, no spec
Proves criterion -> task -> test traceability for one spec and writes
.specs/<ID>/06-verify.md with result: pass|fail. The spec-gate hook blocks a FEAT
(feature-spec) index.md row from transitioning to done without a passing artifact
(hooks.specGate.verifyGate, default on). Other spec types (bug, refactor, perf, rca, port) close
out through the unconditional protected-path rule, same as before this gate existed.
/sd:verify FEAT-1042
Run it at close-out (Phase 6 of /sd:feature runs it for you) or any time earlier as a progress check. A FAIL lists VF0xx findings with file:line citations.
A PORT spec captures reproducing a donor repo's behavior in this host repo: which donor, at
which commit, which members must land, where each path maps to, and which departures are
sanctioned. /sd:port (documented above) drives the full pipeline - bridge, freeze, survey,
fidelity tables, behavior pinning, plan, batched execute, justified-diff parity, close-out.
Cross-repo (bridged) topology - when the donor lives in a different repository, capture its
side first: run /sd:explore --port <entry point> --scope <scope> [--snapshot contract+source] in the donor repo (a separate session - never load a host project's
CLAUDE.md or constitution alongside it). It writes a fixed-section contract, plus - under
contract+source - a source/ bundle with MANIFEST.md, to the donor's own
.specs/_explorations/. Pass that bundle's path as --from to /sd:port in the host repo - moving
the bundle between the two repos is a manual or scripted step, not automated by either command.
Intra-repo topology - when the donor and host are the same repository (duplicating a pattern
elsewhere in the codebase), pass the donor path or symbol directly as --from; /sd:port invokes
sd-code-explorer's port-extract mode itself in Phase 1.
Known limitations:
spec-gate,prompt-router, andsubagent-retrodo not recognize thePORT-prefix (it is hardcoded in the hook scripts) - aPORT-spec is invisible to in-progress-spec detection, context injection, and lesson scoping. Workaround: sethooks.specGate.mode: "warn"for the duration of the port, or track the work under an accompanying FEAT spec.hooks.specGate.verifyGateis FEAT-scoped, so a port'sdoneclose-out is not verify-gated by the hook -/sd:portPhase 9 still runs/sd:verifyitself and requiresresult: passbefore closing out.
| You have | Use |
|---|---|
| "Add a new endpoint / behavior / capability" | /sd:feature |
| "Something is broken; need to investigate then fix" | /sd:bug |
| "Production incident; need a post-mortem with no code change" | /sd:rca |
| "This file / module is too tangled; need to restructure" | /sd:refactor |
| "X is too slow; need to optimize with measurements" | /sd:perf |
| "Reproduce a donor repo's behavior in this repo, faithfully" | /sd:port |
| "I just want to navigate the code" | /sd:explore |
| "Review this change for compliance" | /sd:review |
| "Manage / browse the spec registry" | /sd:spec |
| "Cut a release / generate release notes from completed work" | /sd:release |
| "Prove a spec is really done (criteria covered, tests pass)" | /sd:verify |
Workflow commands are resumable. Re-running /sd:feature INV-2501 after closing your terminal mid-execution detects the current state of .specs/FEAT-INV-2501/ and jumps to the next phase. The state machine is documented at the top of each command file.
The main heuristic: workflow checks for the presence and contents of 00-spec.md, 05-retro.md, and (feature/refactor/port only) 01-plan.md and 02-tasks.md (with task completion ratio) to determine where you are.
When an RCA spawns fixes, link them so the registry knows:
/sd:rca payment-outage-jan8 # produces RCA-payment-outage-jan8-20260108
# ...RCA filled in, spawned specs listed...
/sd:bug 1310 # produces BUG-1310
/sd:spec link BUG-1310 spawned-by RCA-payment-outage-jan8-20260108
Now /sd:spec show BUG-1310 reveals the parent RCA.
Every spec type now carries a ## Spawned specs table - Reserved ID | Type | Title | Owner -
the same one the RCA has always had. Close-out in /sd:feature, /sd:bug, /sd:refactor and
/sd:perf prompts for it whenever the retro names something deferred. It is a prompt, not a gate:
an empty table is a legitimate answer.
A reserved ID is a placeholder, not a registry entry. It does not go in .specs/index.md and
it does not go in linked_specs until the child spec actually exists:
# FEAT-INV-2501 closes with | BUG-1310 | bug | Guard the empty-prefix match | alice |
/sd:bug 1310 # now the directory exists
/sd:spec link BUG-1310 spawned-by FEAT-INV-2501 # now the link exists
/sd:spec validate raises SL090 (🟡 SUGGEST, never a failure) on a done spec that talks about
follow-up work and leaves the table empty.
If you hit a hard gate that the system refuses to override (e.g. bug reproduction unavailable, perf baseline cannot be measured), the workflow surfaces options:
- Gather more evidence - logs, telemetry, observability changes.
- Accept the gate with explicit constitution exception - logged to retro.
- Abort - the spec stays at its current state for later resumption.
The system surfaces; the human decides. The gates exist precisely so the decision is conscious.
Hooks emit output inline during a session. Examples:
prompt-router on "fix bug INV-2501 in stock service":
<context-router>
Routing hints from specwright (UserPromptSubmit hook):
Workflow keyword matches:
- /sd:bug (matched: bug, fix)
Ticket IDs detected: INV-2501
Matching spec folders under .specs/:
- FEAT-INV-2501
Specs currently in-progress (from .specs/index.md):
- FEAT-INV-2501
</context-router>
spec-gate when editing src/Stock.cs with no in-progress spec, mode: warn:
[WARN] spec-gate: editing code file 'src/Stock.cs' but no in-progress spec is recorded in .specs/index.md. Run /sd:feature, /sd:bug, /sd:refactor, or /sd:perf first to create a spec, or set hooks.specGate.mode='off' in .claude/project-config.json to disable.
spec-gate in mode: block:
{"decision":"block","reason":"spec-gate: editing code file 'src/Stock.cs' but no in-progress spec..."}subagent-retro after a subagent run, retro file is 90 minutes stale:
<retro-reminder>
Retro files appear stale or missing for the following in-progress specs:
- FEAT-INV-2501: 05-retro.md last touched 90 min ago (threshold 30 min)
Consider appending: decisions made, surprises encountered, follow-ups identified.
</retro-reminder>
.claude/project-config.json contains the hooks section:
{
"hooks": {
"userPromptRouter": {
"enabled": true
},
"specGate": {
"enabled": true,
"mode": "warn"
},
"subagentRetro": {
"enabled": true,
"retroStaleMinutes": 30,
"debounceMinutes": 10
}
}
}Common adjustments:
- Tightening: change
specGate.modefrom"warn"to"block"once your team is used to the workflow. - Loosening: set
enabled: falseon any hook during noisy debug sessions. Don't forget to flip back. - Pace tuning:
retroStaleMinutesanddebounceMinutescontrol how often the retro reminder fires. Set both higher for long-form work; lower for tight iteration cycles.
paths.protected controls which files trigger an unconditional decision=block:
{
"paths": {
"protected": [
".specs/constitution.md",
".specs/index.md",
"LICENSE"
]
}
}Add anything you never want edited via Claude Code's tool. Migration scripts, sealed configs, generated files, etc.