Spec, Prompt, Constraints: Who Does What
Write a spec for one-offs, constraints for the repeated stuff, prompts for the temporary stuff.
Where a sentence belongs depends on how long it needs to stay in force. Temporary things go in the prompt; things that apply across a module go in the spec; things that apply across the whole project go in the constraints file.
What you'll run into:
- You restate the same rules in every conversation
- The constraints file keeps growing, and eventually the AI stops following it
- By round three, it overthrows the data structure you agreed on in round one
What goes in each layer
Constraints are the backdrop, the spec is the module's setup, the prompt is the current action. All three layers apply at once when code is generated; on conflict, the lower layer wins — but to override cleanly, say so explicitly rather than hoping it judges for itself.
| Layer | Where it lives | What it holds | Typical content |
|---|---|---|---|
| Constraints | CLAUDE.md | Rules that hold for the whole project | Every component implements four states, spacing uses these six values, permissions are always checked backend-side |
| Spec | docs/specs/module.md | A module's data, states, edge cases | Two-level replies, soft delete, folding past 500 chars |
| Prompt | The text you type | The concrete task for this round | Move this button to the top-right, change this spacing to 24 |
The spec layer is the easiest to skip. Skip it and the module's decisions live only in conversation history — which fades as it grows. "By round three it overthrows the data structure we agreed on" almost always traces back to this. The official Claude Code best practices make the same point: bake long-lived conventions into files instead of restating them each conversation. claude-practices
Consider "replies go two levels deep." Mentioned in a single prompt, it may be forgotten next round; written into the comments module's spec, it's honored on every change to that module; and if every list on the site needs pagination, that belongs in the constraints file. The same sentence lands differently depending on the layer you put it in.
When to move something up
- If you've said the same thing three times, move it into the spec. Three is a decent threshold — more reliable than "feels like I'm saying this a lot."
- If it has to be restated across two or more modules, move it into constraints. What holds in only one module stays in that module's spec.
- If the spec changes, the code changes too — and vice versa. Change the code without updating the spec and the spec is dead. Have the AI update the spec file before every change.
- Delete the constraints file on a regular schedule. Once the project has moved on, stale constraints are worse than none — they make the AI produce things you no longer want.
Constraints aren't commands
The constraints file is not a hard switch. It enters the context as ordinary content; the model follows it probabilistically, not as a guarantee. That implies two things. Like an employee handbook: however well it's written, the new hire won't memorize every line — only the ones used daily stick.
- Keep it lean. Ask of every line: would removing it cause an error? If not, delete it. Most people's constraints files are half project description, half actual constraints. Keep it under two hundred lines — the longer it gets, the lower the probability each line is followed.
- Re-check the critical ones. Key constraints shouldn't live only in the file; restate them in the current instruction. And after the work is done, have the AI check itself against the constraints — it costs little.
Below constraints sits the spec itself — see Spec Before Code, where the most valuable of the four parts, "open questions," forces out the things you haven't thought through.
