Decide what to build, before anything gets built.
Keywords
spec, requirement IDs, hooks, UserPromptSubmit, PreToolUse, stages, intent
Why
Coding agents rarely write bad code. They write code that quietly decides what the feature is: they guess the gaps, test their guesses, and everything comes back green. And when the agent writes most of the code, I lose my picture of the system.
So every change goes through three stages, and I start each one.
Stages
1- ๐ Spec, do we understand each other?
2- ๐งช Tests, do I understand the architecture?
3- ๐ ๏ธ Code, ship it
Spec: Claude only touches docs/spec, the numbered requirements (ACT-149, SCHED-022, โฆ) that describe how the app behaves. No code, no tests. It tells me which IDs it added, changed or retired, and I review the diff.
This stage is a communication check. What I asked, how Claude wrote it down and what it actually understood are three different things. The spec diff shows the gap between them in plain language, at the cheapest possible point, before a single line of code or test depends on it.
Tests: when I say “build the tests”, Claude updates and adds tests to match the new spec. Only test files can change.
This stage is about understanding the project and its architecture better. In a project developed mostly by Claude, this is where the right and wrong architectural decisions, the patterns and the relationships between the code come to the surface, and the gaps in my mental picture of the project get filled.
Code: when I say “build it”, Claude changes the code until those tests pass. If a test looks wrong, it reports it instead of bending the test to fit the code.
By now the hard thinking is done. What is left is ordinary productization: implement against the usual coding principles, then ship.
Each stage is its own commit, so the PR reads spec โ tests โ code.
Enforcement
Writing the rule in CLAUDE.md is not enough. Two small hooks keep it in place.
Stage hook (UserPromptSubmit + PreToolUse): reads how my prompt starts, sets the stage, repeats it at the top of every turn and blocks edits outside it. During Spec, a write to src/ fails, and so does sed -i in the shell.
Spec-context hook: matches the words in my prompt against the spec and adds the related requirements to Claude’s context. So it starts from the rules, not from searching the code.
There is also a small script that checks requirement IDs are never reused. A removed rule is struck through (~~ACT-135~~), never deleted.
Prompts
You don’t need to write the hooks by hand. These prompts get Claude to build them.
Move all the app’s behaviour rules out of CLAUDE.md and the code comments into
docs/spec, one file per area, as numbered requirements likeACT-001. Each requirement links to its code with aCode:line. Add a script that fails when an ID is duplicated, reused or points nowhere.
Add a UserPromptSubmit hook that matches the prompt’s words against
docs/specand puts the most relevant requirements (ID, file:line, first sentence) into context.
Set up a staged workflow. A change request starts in Spec: only
docs/specmay change. “build the tests” moves to Tests: only test files may change. “build it” moves to Code: no test file may change. “create a pr” pushes and opens the PR. Write a hook that sets the stage from how the prompt opens, tells Claude the stage every turn, and blocks Edit/Write and shell writes the stage doesn’t allow. Document it in CLAUDE.md.
Pros
1- โ
Misunderstandings surface first, in a small spec diff before any code exists
2- โ
Tests come from the spec, not the code, so they test what I asked for
3- โ
My mental picture stays complete, the tests surface the architectural decisions, patterns and relationships in the code
4- โ
Cheap to change my mind, a revert is just another spec change with the reason recorded
5- โ
Clean history, one commit per stage
6- โ
The spec stays true, every code change starts in it
Cons
1- โ Slower for small fixes, a one-line tweak still needs three stages and three commits
2- โ More round trips, I have to step in between stages, not fire and forget
3- โ The stage is guessed from wording, a question starting with "build it" can misfire
4- โ Upkeep, the spec is a second codebase in prose and needs pruning
5- โ Harder for UI, layout and wiring are better checked by eye
6- โ Only works if I read, skimming the tests throws away the stage that keeps me in the loop
Closing
It is not a framework, just a few hooks and a habit. But it changed my role. The spec is where I decide what gets built, the tests are where I keep understanding what was built, and the code is the easy part.
Staying the person who understands the system, while most of it is written by an agent.
That’s the part I want to keep.