03 - Prompting Claude for Code
📋 Jump to Takeaways🎁 Two engineers ask Claude for the same feature. One gets a clean PR in three minutes, the other burns twenty minutes and gives up. Same model. What did the first one say differently?
Prompting Claude for code isn't about magic words. It's about handing over the same context and constraints you'd give a good contractor. Get that right and the first attempt is usually the one you ship.
Specify the Task Not the Steps
Say what you want to be true when it's done. Don't script the implementation. Claude plans better than a step list you improvised, and a rigid script boxes it out of the obvious solution.
❌ Open cart.ts, add a function called applyDiscount, make it take
a code string, look it up in the discounts map, then multiply...
✅ Add promo-code support to the cart. Users enter a code at checkout,
valid codes reduce the total, invalid codes show an error.
Follow the existing validation pattern in checkout.ts.The second one gives Claude the goal and a pattern to match. It figures out the function names, the error path, and where the code lives, and it usually matches your conventions better than you'd have spelled out.
State the Intent
Tell Claude why the change exists. Intent lets it make the hundred small decisions you didn't mention in a way that serves the actual goal.
We're adding promo codes because marketing wants to run a Black Friday
campaign. Codes are time-limited and single-use per account. Precision
on expiry matters more than raw speed here.Now Claude knows to check expiry carefully and not over-engineer the hot path. Skip the "why" and it optimizes for the wrong thing, then you re-explain in the second round.
Constrain the Change
Left unbounded, Claude tidies. It renames things, adds abstractions, and "improves" files you never asked it to touch. That's noise in your diff and risk in your review. Fence it in.
Only touch cart.ts and checkout.ts. Don't refactor unrelated code,
don't add new dependencies, and don't change the public API of Cart.
If you think a bigger change is needed, tell me first instead of doing it.A tight scope makes the diff reviewable and keeps the blast radius small. The "tell me first" line turns a silent rewrite into a conversation.
Provide a Verification Path
The best prompts hand Claude a way to check its own work. Point at the failing test, the repro command, or the acceptance criteria. Then it can run, see red, fix, and see green before it ever hands back to you.
There's a failing test in cart.test.ts named "rejects expired codes".
Make it pass. Run `npm test cart` to check. Don't edit the test.Give it the command and it closes the loop itself. Without a verification path, Claude writes plausible code and you become the test runner.
Iterate Don't Restart
When the output is 80% right, don't wipe the slate and re-prompt from scratch. Correct in place. Claude keeps the context and fixes the specific thing.
Close. Two problems: the error message should be user-facing text,
not an exception, and you're checking expiry in UTC but our timestamps
are local. Fix those two, leave the rest.Restarting throws away everything it learned about your codebase this session. A targeted follow-up is faster and keeps the parts that already worked.
Common Prompting Mistakes
Three patterns waste the most time. Each has the same fix, be more specific.
Too vague: "make the checkout better" → no target, no done state
Too much: "add promo codes, refactor the → five tasks, none finished well
cart, fix the tests, and update
the docs"
No criteria: "add promo codes" → works? you can't tellShip one task at a time with a clear finish line. "Add promo-code support and make the expired-code test pass" beats a paragraph of loosely related wishes every time.
Key Takeaways
- Specify the goal and constraints, not a step-by-step script. Claude plans the implementation better than an improvised list
- State the intent (the "why") so Claude makes unmentioned decisions in service of the real goal
- Constrain scope explicitly: which files, no new dependencies, no unrelated refactors, "tell me first" for bigger changes
- Give a verification path (a failing test, a repro, a command) so Claude closes the loop instead of leaving you as the test runner
- Iterate with targeted follow-ups when output is close; don't restart and throw away session context
- The top time-wasters are vague asks, too many tasks at once, and no acceptance criteria, all fixed by being specific
🎁 Claude just handed you 200 lines that compile, pass the tests, and look right. How do you know it isn't confidently, plausibly wrong?