From writing
Guide for writing and updating domain specifications. Use when creating a new spec, updating an existing spec, converting planned spec to implemented, or reviewing spec quality. Triggers on: "write spec", "update spec", "spec this", "review spec".
How this skill is triggered — by the user, by Claude, or both
Slash command
/writing:spec-authoringThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Specs are persistent domain documents that describe a system boundary: why it exists, what it contains, what it excludes, and how it should evolve as code changes. They are written from the code outward, with code as reality and the spec as the durable statement of intent, rationale, and boundaries.
Specs are persistent domain documents that describe a system boundary: why it exists, what it contains, what it excludes, and how it should evolve as code changes. They are written from the code outward, with code as reality and the spec as the durable statement of intent, rationale, and boundaries.
| Variable | Value | Notes |
|---|---|---|
| SPECS_DIR | specs/ | Root directory for all spec files |
| SPECS_README | specs/README.md | Index table linking specs to code |
Specs describe intent informed by reality. Code is the source of truth for what exists; specs capture why it exists, what boundary it belongs to, and what should not change accidentally. Never write a spec from memory or assumption — read the code first.
A spec names a stable system boundary, not a feature request or delivery task.
Good names:
auth-systemtask-enginedata-pipelineBad names:
add-priority-filterspec-003phase-2-redesignIf the user gives a feature name, identify which domain it belongs to before naming the spec.
Choose the lightest spec shape that still captures the boundary clearly. Default to minimal. A spec competes with the code and tests for a reader's attention; detail that duplicates them is a liability, not a feature.
Size by module LOC (source lines, excluding tests):
| Module LOC | Default shape | Contents |
|---|---|---|
| < 2000 | Minimal | Overview (Purpose + Non-Goals) and Design Decisions only. No architecture/data-model/interface prose — the source is short enough to read. |
| 2000–5000 | Medium | Add Architecture summary + Code Locations. Still no type transcriptions or interface prose that tests already encode. |
| > 5000 | Heavyweight | All sections as needed. Even then, prefer pointers over restatement. |
Tests count as documentation. If a well-named test file covers a behavior, the spec should not restate it in prose — reference the test file instead.
The threshold is a guide, not a hard rule. A 500-LOC module with a subtle cross-system contract may still need a medium spec; a 3000-LOC module that's mostly boilerplate may still only need a minimal one. Err minimal and grow when readers actually struggle.
Planned → In Progress → Implemented
Specs capture things code cannot:
| Spec captures | Code captures |
|---|---|
| Why this design was chosen | What the design is |
| What was explicitly rejected | What was built |
| Non-goals and scope boundaries | Current behavior |
| Cross-system tradeoffs | Local implementation details |
| External API contracts upfront | Internal types and functions |
| Implementation sequencing | Final structure |
describe/it blocks communicate this better than spec bullet points.| Section | Planned (high detail) | Implemented (summary + pointers) |
|---|---|---|
| Overview | Full | Full |
| Design Decisions | Full | Full (most valuable section long-term) |
| Architecture | Component diagrams, file maps | Summary pointing to code |
| Data Model | Full schemas, key types | Summary pointing to code |
| Interfaces | Full API contracts | Summary pointing to code |
| Implementation Phases | Sequenced checklist | Replace with Testing section |
| Code Locations | Files to create/modify | Files that exist |
| Open Questions | Active | Resolved or remaining |
Every non-obvious choice gets its own entry with explicit rationale. This is what agents need most when modifying existing code — understanding why something is the way it is prevents accidental design regression.
Format:
- **Decision:** Discovery uses `DefaultPackageManager.resolve(...)` instead of manual parsing.
- **Rationale:** It exactly matches the real extension/package discovery rules, including package manifests, precedence, and path filters.
Good decisions to document:
Include copy-pasteable artifacts when they carry design intent an agent couldn't derive from context:
| Artifact | Include in spec? |
|---|---|
| SQL schema DDL | Yes — defines the data contract |
| API endpoint tables | Yes — defines the interface contract |
| CLI flag definitions | Yes — defines the user contract |
| K8s RBAC/manifests | Yes — infrastructure intent an agent wouldn't guess |
| Rust/TS type signatures | Only key types; link to code for full definitions |
| Full function bodies | No — code is the truth |
| Config env vars table | Yes — operational contract |
| External API details | Yes — domain knowledge agents lack |
Entry state: DETERMINE_MODE
This is the foundation for any spec based on existing code. Read the actual implementation thoroughly:
Never write a spec from memory or assumptions. The code is the source of truth for what exists. The spec adds why it exists and what its boundaries are.
Write all sections at full detail. This is the blueprint an agent will implement from.
**Status:** Planned, **Last Updated:** <date>## 1. Overview
### Purpose
One paragraph: what this system does and why it exists.
### Goals
Bulleted list of concrete, verifiable outcomes.
### Non-Goals
Bulleted list of things explicitly out of scope. Be specific — "not X" is more useful than "simple".
## 2. Design Decisions
- **Decision:** <what was chosen>
- **Rationale:** <why, including what alternatives were rejected>
Place this early so the agent internalizes constraints before reading architecture details.
## 3. Architecture
### Component structure
File tree or module map showing what will be created.
### Data flow
ASCII diagram or numbered flow showing how data moves through the system.
Include concrete file paths, crate names, or module structure. The agent needs to know where things belong.
## 4. Data Model
### Database schema (if applicable)
Full SQL DDL — this is a design contract, not documentation.
### Core types
Key type signatures. Only types that define the domain contract; skip internal helpers.
## 5. Interfaces
### API endpoints (if applicable)
Method | Path | Description table.
### CLI flags / Commands (if applicable)
Flag | Description | Default table.
### Events / Hooks (if applicable)
Event name, payload shape, behavioral contract.
Include request/response examples for non-obvious APIs.
## 6. Implementation Phases
### Phase 1: <name> (<time estimate>)
- [ ] Task 1
- [ ] Task 2
### Phase 2: <name> (<time estimate>)
- [ ] Task 3
Sequence phases so each can be built and tested independently. Earlier phases should not depend on later ones.
## 7. Code Locations
| File | Change |
| --------------------- | -------------------- |
| `path/to/new/file.ts` | New: description |
| `path/to/existing.ts` | Modify: what changes |
## 8. Open Questions
- Should X support Y? (tradeoff: complexity vs flexibility)
- Is Z the right default? (alternative: W)
Transition a spec from Planned/In Progress to Implemented. The goal is to keep what code can't express and remove what it already expresses.
Change status to **Status:** Implemented
Update **Last Updated:** date
Keep at full detail: Overview, Design Decisions, Open Questions
Slim Architecture to summary: Replace detailed file trees with a one-line description + pointer to the code directory. Keep ASCII diagrams only if they show cross-component flow.
Slim Data Model: Remove type transcriptions. Keep SQL schemas (they're the contract). For code types, write "See path/to/types.ts".
Slim Interfaces: Keep API endpoint tables and CLI flag tables (they're contracts). Remove behavioral prose that restates test assertions.
Replace Implementation Phases with Testing:
## Testing
Automated tests in:
- `path/to/foo.test.ts` — integration tests for X
- `path/to/bar.test.ts` — unit tests for Y
Manual verification: description of any manual testing needed.
Update Code Locations to reflect actual file paths (remove the "Change" column, just list paths)
For existing code that has no spec. Read the code first, then work backwards.
The index groups specs by system area with ## headings. Each area has a 3-column table:
# Specifications
Persistent domain specifications. Organized by system area, not feature chronology.
## [Category Name]
| Spec | Purpose | Code |
| ------------------------ | ---------------- | ----------------------------------- |
| [domain.md](./domain.md) | One-line purpose | `src/domain/` |
| [other.md](./other.md) | One-line purpose | `src/other/`, `src/shared/utils.ts` |
## [Another Category]
| Spec | Purpose | Code |
| ---- | ------- | ---- |
| ... | ... | ... |
Index rules:
Before considering a spec complete, verify:
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub codethread/agents --plugin writing