Claude Code Mastery3 / 12
Writing Prompts That Work
"Make it better" is not a prompt. "Refactor this for performance" is not a prompt. Here is the four-part structure that makes Claude Code actually finish what you asked.
Most people prompt Claude Code the same way they prompt ChatGPT. That is the bug.
ChatGPT is a Q&A engine. Claude Code is an agent. The shape of a good question is not the shape of a good goal.
After a year of running Claude Code on production codebases, I have boiled it down to four parts that always need to be in the prompt:
- Goal — what success looks like.
- Constraints — what must not change.
- Definition of Done — how the agent knows it's finished.
- Context — pointers to the relevant files / tickets / errors.
Skip any of these and you get drift. Include all four and the agent will quietly run for 5 minutes and come back with a clean diff.
The bad prompt
> Refactor the user service for performance.
Why it fails:
- "Performance" is undefined. Latency? Memory? Throughput?
- No constraints — it might rewrite your DB schema.
- No definition of done — it stops when it gets bored.
- No context — it has to guess which file is "the user service."
You will get back something that looks like work but isn't.
The good prompt
> Goal: Reduce p95 latency on GET /api/users/:id from 240ms to under 80ms.
>
> Constraints:
> - Do NOT change the public API shape.
> - Do NOT add new dependencies.
> - Keep code in app/api/users — no new layers.
>
> Definition of Done:
> - Existing tests pass.
> - Add a load test (50 concurrent calls × 100 iterations).
> - p95 < 80ms locally on Node 20.
> - Add a one-paragraph PR description.
>
> Context:
> - app/api/users/route.ts is the entry point.
> - lib/db/users.ts has the slow N+1 query.
> - We use Postgres 15, drizzle ORM.
Same task. Different result. The agent will:
- Read the two files.
- Identify the N+1.
- Write the fix with a single batched query.
- Add the load test.
- Run the test, confirm the number.
- Hand back a diff with the PR description.
That is delegation, not autocomplete.
Why each part matters
Goal
Write it as an outcome, not an action. "Reduce p95 latency to 80ms" is an outcome. "Refactor the database calls" is an action — and a bad agent will do the action without hitting the outcome.
Constraints
Constraints are what would surprise you. If a junior engineer rewriting that file would surprise you by changing the API shape, write that down. If they would surprise you by adding Redis, write that down.
Most "Claude Code did something weird" stories are missing constraints, not missing intelligence.
Definition of Done
The single most underused part of any prompt. Without it, the agent stops when it thinks the task is done — usually after writing the code, before running the tests.
Good DoDs are testable:
- "Existing tests pass."
- "New endpoint returns 201 and a valid Location header."
- "lighthouse-ci shows no regression on the homepage."
If you cannot write a DoD, the task is not ready to be delegated.
Context
You do not need to paste files. Pointers are enough:
app/api/users/route.ts— entry point.tests/api/users.test.ts— existing tests.- "We saw the regression in PR #842."
Claude Code can read and search. It just needs you to point at the right neighborhood.
The 80/20 template I keep in .claude/commands/
# /goal — paste this template, fill the blanks
Goal: <outcome with a number when possible>
Constraints:
- <thing that must not change>
- <dependency rule>
- <style or architecture rule>
Definition of Done:
- <test command passes>
- <perf or correctness check>
- <PR description in 1 paragraph>
Context:
- <file or folder>
- <related ticket / error / log>
Aliasing this as a slash command means a new feature prompt takes 90 seconds to write. We will cover slash commands properly in Article 4.
Anti-patterns to drop today
- "Make it cleaner." Cleaner by what metric? Pick one: lines of code, cyclomatic complexity, or a specific lint rule.
- "Fix the bug." Which bug? What is the expected behavior? What is the actual?
- "Refactor for readability." Readability is taste. Pick a concrete pattern: "extract to pure functions," "replace nested ifs with early returns."
Vague prompts produce vague code. The agent is a mirror.
One last trick: the "negative example"
Sometimes the cleanest way to constrain an agent is to show it what not to do.
> Do NOT add a new abstraction layer.
> The previous attempt added a UserRepository class — we removed it.
> The fix should be ~20 lines in lib/db/users.ts, not 200 lines.
This is brutally effective. You are pre-empting the most common failure mode of an over-eager agent: building a kingdom when a single function would do.
Next article: Slash Commands — how to turn the prompt template above into a one-keystroke /feature command, and how to chain /init, /agents, /compact to build a full project skeleton in one session.
Series — Claude Code Mastery
- Part 01Claude Code vs ChatGPT vs Copilot vs AgentsMost developers are using the wrong AI tool for the wrong job. Here is why — and what to do instead.
- Part 02Installation + The Antigravity WorkflowInstalling Claude Code is a 30-second job. Setting up the workflow that makes the agent feel like it's doing the heavy lifting — that's the part nobody writes about.
- Part 03Writing Prompts That Work — you are here"Make it better" is not a prompt. "Refactor this for performance" is not a prompt. Here is the four-part structure that makes Claude Code actually finish what you asked.
- Part 04Slash Commands — Building a Project from A to Z/init, /agents, /compact and your own custom commands. The toolkit that lets you go from empty folder to running app without leaving the Claude prompt.
- Part 05Sub-Agents — The 11 Specialized Experts Inside Claude CodeSlash commands reuse prompts. Sub-agents reuse whole personas — code-reviewer, test-writer, migration-runner. Here is the team you should have on day one.
- Part 06Production Codebase SafetyPermissions, guardrails, and what not to automate. The unsexy article that decides whether Claude Code becomes infrastructure or becomes the reason you got paged at 2 AM.
- Part 07Multi-Agent PipelinesChaining sub-agents, running them in parallel, and the patterns for 'review-while-coding' without losing your mind. Where Claude Code starts to feel like a small engineering org.
- Part 08Building Complete FeaturesFrom Linear ticket to merged PR with Claude Code. A real, honest walk-through — what the prompt looked like, what the agent got right, what I caught in review.
- Part 09Testing and DebuggingLetting Claude Code own the entire test loop. Including the parts that make engineers nervous: regressions, flakies, integration tests, and the stack-trace whisperer.
- Part 10Team WorkflowsHow engineering teams are actually integrating Claude Code today. The shared .claude/ folder, the review rituals, and the anti-patterns I keep seeing in the wild.
- Part 11Advanced Patterns — Hooks, MCP Servers, Custom Tools, System PromptsOnce you've outgrown the defaults: hooks for deterministic side effects, MCP servers for org-specific data, custom tools, and system-prompt surgery.
- Part 12The Future of Agentic DevelopmentWhere this is going in 2026 and beyond. What I'd bet on, what I would not, and the line where I get sceptical of the hype.