spec-first
No code before a written, human-approved spec.
- Writes a spec to specs/<slug>.md — context, scope, out-of-scope, machine-checkable acceptance criteria, verification command
- Presents it and waits for your explicit approval before touching any code
- Treats the approved spec as the contract and refuses to expand scope silently
View full SKILL.md
---
name: spec-first
description: Write a spec and get explicit human approval before implementing any feature, change, or bug fix. Use whenever the user asks to build, add, change, refactor, or fix something that touches source code. Not for answering questions, read-only exploration, or fixes the user explicitly wants applied immediately.
---
# Spec-First: No Code Before an Approved Spec
When the user asks for a feature, change, or fix, do NOT start writing code.
Write a spec first, present it, and wait for explicit approval. A prompt is a
wish; a spec is a contract.
## Workflow
1. **Investigate before writing.** Read the files the change will touch and
note how the existing code works. If a decision materially shapes the spec
(data model, API surface, new dependency), ask the user before drafting —
not after.
2. **Write the spec** to `specs/<slug>.md`, where `<slug>` is a short
kebab-case name for the task (e.g. `specs/rate-limit-login.md`). Create
the `specs/` directory if it does not exist. Use the template below.
Keep the spec under one page: if it will not fit, the story is too big —
propose splitting it into smaller specs instead.
3. **Present it and stop.** Show the spec (or a faithful summary plus the
file path) and ask: "Approve this spec, or want changes?" Then WAIT.
Do not write, edit, or scaffold any implementation code until the user
replies with explicit approval ("approved", "go ahead", "yes, build it").
Silence, follow-up questions, or partial answers are not approval.
4. **After approval, the spec is the contract.** Implement exactly what it
says. If reality contradicts the spec mid-implementation (an API that does
not exist, a wrong assumption), stop, update the spec file, and re-request
approval for the delta before continuing. Never expand scope silently —
"while I was in there" improvements belong in a future spec, not this diff.
5. **Before declaring done, re-read the spec.** Walk the acceptance criteria
one by one, run the verification command, and report each criterion as met
or not met.
## Spec template
# <Title>
## Context
Why this change is needed, in 2-4 sentences. Link related code or issues.
## Scope
What will be built, and which files/modules it touches.
## Out of scope
Explicit non-goals, so nobody "helpfully" builds them.
## Acceptance criteria
- [ ] Machine-checkable statements ("GET /api/login returns 429 after
5 requests/minute"), never vibes ("works well", "feels fast").
## Verification
One command that proves the criteria, e.g.
npm test -- rate-limit && npx tsc --noEmit
## Edge cases
- **Tiny change** (typo, comment, one-line config): a one-paragraph spec in
chat is enough — but still get a "yes" before editing.
- **User says "skip the spec, just do it"**: comply, and note in one line that
spec-first was skipped at their request.
- **Vague request**: draft the spec anyway with your best-guess scope and mark
every guess with `ASSUMPTION:` so approval doubles as clarification.
- **A spec for this task already exists**: re-read it and confirm it still
stands instead of writing a duplicate.
## Boundaries
- Never write implementation code before explicit approval. The only file you
may create pre-approval is the spec itself.
- Never mark an acceptance criterion as met without having run the
verification command in this session.
- Never widen scope beyond the approved spec without a new approval.
- Approval comes from the human — never from you deciding the spec
"looks fine".
worktree-story
Every task gets its own git worktree and branch.
- Creates a sibling worktree with git worktree add ../<repo>-<slug> -b story/<slug>
- Handles existing-branch and already-checked-out errors without --force
- Keeps the main checkout untouched, reports the worktree path, and includes post-merge cleanup
View full SKILL.md
---
name: worktree-story
description: Create an isolated git worktree and branch for the current task before changing any files. Use at the start of implementation work in a git repository — features, fixes, refactors — especially when the main checkout must stay clean or other work may run in parallel. Not needed for read-only tasks.
---
# Worktree Per Story: One Task, One Isolated Checkout
Before changing anything, move the work into a dedicated git worktree on its
own branch. The main checkout stays untouched, and parallel work stays
possible.
## Workflow
1. **Confirm the repo and check its state.**
git rev-parse --show-toplevel
git status --porcelain
If the main checkout has uncommitted changes, do not drag them into the
story — tell the user and ask how to proceed.
2. **Name the branch after the story**: `story/<slug>`
(e.g. `story/rate-limit-login`). If a spec exists (see the spec-first
skill), reuse its slug so branch, spec, and PR line up.
3. **Create the worktree as a sibling folder**, never nested inside the repo:
git worktree add ../<repo-name>-<slug> -b story/<slug>
Example, repo `shop`, story `rate-limit-login`:
git worktree add ../shop-rate-limit-login -b story/rate-limit-login
4. **Handle errors — never force through them.**
- "branch already exists": attach to it without `-b`:
`git worktree add ../<dir> story/<slug>` — or pick a new slug if that
branch belongs to other work. Never `-B` (force-reset) an existing
branch.
- "already checked out in another worktree": that story is live elsewhere.
Run `git worktree list`, then either continue there or choose a new
branch name.
- Target directory already exists: choose another path. Never delete a
directory you did not create.
5. **Work only inside the worktree.** `cd` into it and stay there: every
edit, build, and test run happens under the worktree path. Commit to the
story branch as you go. The main checkout is read-only for you from now on.
6. **Report the path.** Tell the user the absolute worktree path and branch
name as soon as they exist, and repeat both in your final summary.
## Cleanup (after the branch is merged — not before)
git worktree remove ../<repo-name>-<slug>
git branch -d story/<slug> # -d refuses unmerged work; that is the point
git worktree prune
If `git worktree remove` refuses because of modified files, show the user
what is dirty instead of reaching for `--force`.
## Edge cases
- **Not a git repo**: say so and ask whether to `git init` or proceed
without isolation — never pretend the isolation exists.
- **Dependencies do not follow**: `node_modules`, virtualenvs, and ignored
`.env*` files are not copied into a new worktree. Re-run the installer
(`npm install`, `uv sync`, ...) and copy env files only with the user's
consent.
- **Shared state is still shared**: databases, dev-server ports, and global
caches are not isolated between worktrees. Flag collisions (two servers on
one port) instead of silently debugging them.
## Boundaries
- Never modify files, commit, or switch branches in the main checkout while a
story worktree exists for this task.
- Never use `--force` variants of worktree or branch commands to bypass an
error you have not explained to the user.
- Never delete a worktree or branch containing unmerged work without explicit
confirmation.
pr-per-story
Verify against the spec, open the PR, never merge.
- Runs the spec's verification command and iterates on failures (best effort, honestly reported)
- Generates the PR description from the spec: what, why, acceptance-criteria checklist, test evidence
- Stops at the PR — merging stays a human decision
View full SKILL.md
---
name: pr-per-story
description: Finish a story by running the spec's verification command, iterating on failures, and opening a pull request whose description is generated from the spec. Use when implementation work is complete and ready for review — the user says the story is done or asks for a PR. Never merges.
---
# PR Per Story: Verified Diff, Human Merge
Every story ends in a pull request: a bounded diff, traceable to its spec,
merged by a human. This skill closes the loop.
## Workflow
1. **Re-read the spec** (`specs/<slug>.md`). The PR is judged against the
spec, not against the chat history. If no spec exists, write down the
acceptance criteria you are about to claim and confirm them with the user
first.
2. **Run the spec's verification command** exactly as written, then walk the
acceptance criteria one by one.
3. **Iterate on failures — best effort, honestly reported.** Fix, re-run,
repeat. If it still fails after a handful of focused attempts, or the fix
would change the spec's scope, stop and report exactly what fails and why.
A red check reported honestly beats a green check achieved by weakening
the test.
4. **Review your own diff before pushing**: `git diff <base>...HEAD --stat`,
then the full diff. Remove debug output, stray files, and unrelated
reformatting. Everything left in the diff must trace back to the spec.
5. **Push the story branch and open the PR** (from the story worktree — see
the worktree-story skill):
git push -u origin story/<slug>
gh pr create --title "<story title>" --body-file <body file>
6. **Generate the PR description FROM the spec**, in this shape:
## What
One paragraph — the change, taken from the spec's Scope.
## Why
Taken from the spec's Context.
## Acceptance criteria
- [x] Each criterion from the spec — checked only if verified
in this session
- [ ] Unmet criteria stay unchecked, with a one-line note
## Test evidence
The verification command and a summary of its real output
(pass/fail counts — not just "tests pass").
Spec: specs/<slug>.md
7. **Stop.** Post the PR URL and the verification summary, then hand off.
Merging is the human's decision, always.
## Edge cases
- **No remote or no `gh` CLI**: push the branch and print the compare URL,
or output the PR title and body as text the user can paste.
- **Verification command itself is broken** (fails before testing anything):
fixing the harness is in scope only if the spec says so — otherwise report
it and stop.
- **Out-of-scope changes crept into the diff**: split them out before opening
the PR, even if they are improvements.
- **A PR already exists for this branch**: update it (push, `gh pr edit`)
instead of opening a duplicate.
## Boundaries
- Never merge, enable auto-merge, approve your own PR, or delete the branch.
- Never check an acceptance-criteria box you did not verify in this session.
- Never weaken, skip, or delete a failing test to make verification pass.
- Never force-push over commits you did not create.
Each skill is one folder containing one SKILL.md. Put them in ~/.claude/skills/ to use them everywhere, or in a project's .claude/skills/ to version them with the repo and share them with your team.
mkdir -p ~/.claude/skills/spec-first \
~/.claude/skills/worktree-story \
~/.claude/skills/pr-per-story
# then save each file below as SKILL.md in its folder:
# ~/.claude/skills/spec-first/SKILL.md
# ~/.claude/skills/worktree-story/SKILL.md
# ~/.claude/skills/pr-per-story/SKILL.mdWhat Claude Code skills actually are
A Claude Code skill is nothing exotic: a folder containing a SKILL.md file. The file starts with YAML frontmatter — a name and a description — followed by markdown instructions. Claude reads only the name and description at session start; when your request matches what the description promises, it loads the full instructions on demand. That description is the trigger, which is why each skill in this pack spells out exactly when it applies and when it does not.
User scope
~/.claude/skills/<name>/SKILL.md — available in every project on your machine. Right for personal process habits like these three.Project scope
.claude/skills/<name>/SKILL.md — committed to the repo, so the whole team's agents follow the same process. Right for team conventions.Because skills load lazily, they cost you almost no context until they fire — unlike a long CLAUDE.md, which rides along in every session whether it is relevant or not.
Why encode process as skills at all
Everyone who works with agents develops process rules: plan before coding, do not touch main, end with a reviewable diff. The failure mode is that these rules live in your head, so they get applied on good days and skipped on busy ones — and never survive handing the project to a teammate. Consistency beats memory. Written process is the core argument of the AIDEN manifesto: your workflow should be written down, in the open, portable to whatever agent comes next.
A skill is the cheapest way to write a rule down where the agent will actually re-read it. You stop re-typing "first write a plan, then wait for me" into every session; the instruction fires by itself, with the edge cases and boundaries you refined once instead of improvising each time.
Three skills, one loop
The pack is designed to compose. Each skill hands off to the next, and together they reproduce the story loop that a multi-agent workflow runs at scale — spec, isolated build, pull request.
- 1
spec-first
The request becomes a contract in specs/<slug>.md: scope, non-goals, machine-checkable acceptance criteria, a verification command. Nothing is built until you approve it. - 2
worktree-story
The approved story gets its own branch and sibling worktree, so the agent never works in your main checkout — the same isolation that makes parallel agents safe. - 3
pr-per-story
The agent runs the spec's verification command, iterates on failures, and opens a PR whose description is generated from the spec. The merge button stays yours.
The slugs line up on purpose: specs/rate-limit-login.md becomes branch story/rate-limit-login becomes a PR that links back to the spec. If you want the deeper reasoning on worktree isolation, see running parallel agents with git worktrees; for writing better specs, the agent spec builder generates the template these skills expect.
Honest limits
Skills are conventions. A well-written SKILL.md raises the odds Claude follows the process dramatically — clear triggers, imperative steps, explicit boundaries all help — but nothing in the mechanism can force compliance. Long sessions drift. A vague request may not trigger the description match. And a model under pressure to "just fix it" can skip the spec it promised to write.