The quality of what AI builds is limited by the quality of what you ask for. A vague spec produces vague code. A specific spec produces specific code.
Here's the format that works.
What a bad spec looks like
Add user authentication to the app.
What will Claude do with this? Guess. It'll guess which auth library to use, where to store tokens, how sessions work, what the login flow looks like, what happens on failed auth, and whether you want OAuth or username/password.
Some guesses will be right. The ones that are wrong will need rework.
What a good spec looks like
## Task: Add email/password authentication
### What to build
- Login form: email + password fields, submit button
- Session stored in httpOnly cookie, 7-day expiry
- On success: redirect to /dashboard
- On failure: show error message inline, do not redirect
### What NOT to build
- No OAuth/SSO (out of scope)
- No password reset flow (separate task)
- No email verification (separate task)
### Constraints
- Use the existing User model in /src/models/user.ts
- Use bcrypt for password hashing (already installed)
- Session handling: use express-session (already installed, configured in /src/app.ts)
### Files to touch
- /src/routes/auth.ts — add POST /login route
- /src/views/login.html — create login form
- /src/middleware/requireAuth.ts — create auth guard middleware
### Files to leave alone
- /src/models/user.ts — read only
- /src/app.ts — read only unless you need to register the new route
### Done when
- Login with valid credentials redirects to /dashboard
- Login with invalid credentials shows an error without redirecting
- Protected routes return 401 without a valid session
- Tests cover all three scenarios
The key sections
What to build — specific deliverables, not goals.
What NOT to build — explicitly scoping out adjacent features prevents scope creep.
Constraints — what to use and what already exists. Prevents Claude from picking a different library or duplicating existing code.
Files to touch / leave alone — the strongest scope control. If Claude knows exactly which files are in scope, it stays there.
Done when — verifiable acceptance criteria. "The login works" is not verifiable. "Login with valid credentials redirects to /dashboard" is.
Time investment vs. rework avoided
A spec like this takes 10-15 minutes to write. It avoids a round of "wait that's not what I meant" that typically costs more. For anything more complex than a small bug fix, the spec pays for itself.
For complex tasks, have Claude read the spec and ask clarifying questions before starting. It catches the ambiguities you didn't notice.
CLAUDE.md templates for spec-driven development: builtbyzac.com/claudemd-templates.html.
Top comments (0)