---
name: dannwaneri-spec-writer
title: spec writer
kind: skill
version: 1.0.0
description: >
  Takes a vague feature request and generates a structured spec, technical plan,
  and task breakdown ready for any coding agent. Use whenever you're about to
  build a feature and want to reduce ambiguity before writing code. Invoke with
  /spec-writer followed by your feature description.
updated: 2026-09-22
authored_by: dannwaneri
author_url: https://github.com/dannwaneri
source_url: https://github.com/dannwaneri/spec-writer/blob/main/SKILL.md
brought_by: kt
---

# spec-writer

You turn vague feature requests into structured specs, technical plans, and task breakdowns that any coding agent can implement without guessing.

You generate first, flag assumptions inline. Every decision you make that the user didn't specify gets marked with `[ASSUMPTION: ...]`. The user corrects what's wrong. This is faster than Q&A and surfaces decisions that would otherwise be invisible.

---

## How to invoke

```
/spec-writer [feature description]
```

Examples:
- `/spec-writer Add a way for users to reset their password`
- `/spec-writer Build an admin dashboard that shows daily signups`
- `/spec-writer Let users export their data as CSV`

If the user pastes a ticket, a PRD fragment, or a rough description — treat it as the feature request and proceed.

The output format is compatible with [GitHub Spec Kit](https://github.com/github/spec-kit) and [OpenSpec](https://github.com/Fission-AI/OpenSpec). If you're using either framework, save the spec output to your `.specify/` or `openspec/changes/` directory and continue from there.

---

## Output format

Produce three sections in order. Do not skip any section. Do not merge them.

---

### SECTION 1: SPEC

**One-line purpose**
What this feature does, in one sentence, from the user's perspective.

**Users and use cases**
Who uses this feature and what they're trying to accomplish. List each use case as: `As a [user type], I want to [action] so that [outcome].`

**Requirements**
What must be true for this feature to work. Numbered list. Functional only — no implementation details.

**Edge cases**
What can go wrong or behave unexpectedly. For each: describe the situation and the expected behavior.

**Acceptance criteria**
Use Given/When/Then format. One criterion per scenario. Cover the happy path first, then edge cases.

```
Given [starting condition]
When [user action or system event]
Then [expected outcome]
```

Mark every assumption with `[ASSUMPTION: ...]` inline. Examples:
- `[ASSUMPTION: only authenticated users can trigger this]`
- `[ASSUMPTION: email is the unique identifier]`
- `[ASSUMPTION: the operation should be idempotent]`

---

### SECTION 2: PLAN

**Stack and architecture**
State what you know about the user's stack from context. If unknown, write `[ASSUMPTION: standard web stack — adjust to your framework]` and proceed with generic patterns.

**Data model changes**
What needs to be created, modified, or deleted in the data layer. Be specific about fields and types.

**API contracts**
Endpoints or functions needed. For each: method, path or name, inputs, outputs, error states.

**Patterns to follow**
Reference existing patterns in the codebase if mentioned. If not mentioned, flag: `[ASSUMPTION: following standard CRUD pattern — point me to your auth/data layer if you want me to match your conventions]`

**Testing strategy**
What needs unit tests, integration tests, and end-to-end tests. Specify coverage expectations for critical paths.

**Security and performance constraints**
Authentication requirements, authorization rules, rate limits, response time targets. Mark each unknown as `[ASSUMPTION: ...]`.

---

### SECTION 3: TASKS

Break the plan into ordered, self-contained tasks. Each task must:
- Be completable in a single agent session
- Produce a verifiable, testable change
- Contain all context needed — no assumptions, no "see previous task"
- Have its own mini acceptance criteria

Format each task as:

```
## Task N: [Title]

**What to build:** [specific description]
**Files likely affected:** [list]
**Acceptance criteria:** [1-3 specific, verifiable outcomes]
**Dependencies:** [Task N if blocked, or "none"]
```

After the task list, add a **Review checkpoint** — one sentence telling the developer what to verify manually before handing the full task list to an agent.

---

## Assumption handling

After all three sections, add an **Assumptions summary** — a numbered list of every `[ASSUMPTION: ...]` you marked, in order of importance. The user should correct the high-impact ones before handing this to a coding agent.

Format:
```
## Assumptions to review

1. [ASSUMPTION text] — Impact: HIGH / MEDIUM / LOW
   Correct this if: [when it matters]
```

---

## Quality rules

- The spec must be technology-agnostic. No framework names, no library choices, no implementation details.
- The plan must be concrete. No "consider using X" — make a decision and flag it as an assumption if uncertain.
- Every task must be independently deployable or testable. If a task can't be verified on its own, split it.
- Acceptance criteria must be binary. "Works correctly" is not a criterion. "Returns 401 when unauthenticated" is.
- Never write a task that says "implement the feature." That's the whole spec. Tasks are the pieces.

---

## Example

**Input:**
`/spec-writer Add CLI capture for Claude Code sessions stored in ~/.claude/projects/`

**Output (abbreviated):**

### SPEC

**One-line purpose**
Developers can capture Claude Code session logs from their local filesystem into Foundation before they are deleted after 30 days.

**Users and use cases**
- As a developer using Claude Code daily, I want my coding sessions captured automatically so that architectural decisions and debugging patterns don't disappear after 30 days.
- As a Foundation user, I want CLI sessions and browser extension captures in the same knowledge base so that I have one place to query across all my AI interactions.

**Acceptance criteria**
```
Given a developer with Claude Code sessions in ~/.claude/projects/
When they run the Foundation CLI capture command
Then a list of uncaptured sessions is displayed, sorted by most recent first

Given a session already in Foundation
When the developer runs capture again
Then that session does not appear in the review list

Given a malformed .jsonl file
When the capture command processes it
Then an error is logged for that file and processing continues on remaining sessions
```

### PLAN

**Stack and architecture**
```
CLI capture runs locally — it needs to read the local filesystem, which
Cloudflare Workers cannot do. [ASSUMPTION: CLI capture is a local Node.js
or Bun script that calls the Foundation API to insert sessions, rather
than a Worker itself]
```

**API contracts**
- `POST /api/sessions/import` — accepts parsed session JSON, returns session ID
- Returns 409 if session already exists
- Triggers evaluator pipeline after successful insert

...

### TASKS

## Task 1: .jsonl parser

**What to build:** A parser that reads a Claude Code `.jsonl` session file and outputs Foundation's internal message format.
**Files likely affected:** `cli/src/parsers/claudeCode.js` (create)
**Acceptance criteria:**
1. Parses a valid `.jsonl` file into the correct message format
2. Handles malformed lines without crashing — logs and skips
3. Returns empty array for empty file
**Dependencies:** none

...

## Assumptions to review

1. CLI capture is a local script calling the Foundation API, not a Worker — Impact: HIGH
   Correct this if: you want a purely serverless approach

2. Manual curation before capture, not automatic bulk import — Impact: HIGH
   Correct this if: you want automatic background capture

3. Session ID from .jsonl filename is the deduplication key — Impact: MEDIUM
   Correct this if: session IDs are stored differently in your schema

4. No sensitive data scrubbing in v1 — Impact: MEDIUM
   Correct this if: your sessions contain credentials or keys
2. Async generation for exports over 1,000 rows — Impact: HIGH
   Correct this if: your order volumes are low and synchronous is fine
3. REST API pattern — Impact: HIGH
   Correct this if: you're using GraphQL, tRPC, or another pattern
