Prompt Engineering Patterns for Claude Code

Practical patterns refined through 900+ sessions. Each pattern includes a copy-paste ready example.


How to Choose a Pattern

graph TD
    START["What are you doing?"] --> BUG{"Bug fix?"}
    START --> FEAT{"New feature?"}
    START --> REFACTOR{"Refactoring?"}
    START --> ARCH{"Architecture?"}
    START --> UI{"UI work?"}
    START --> DOC{"Document?"}

    BUG --> |"Yes"| B1["Smallest Failing Test"]
    BUG --> |"Complex"| B2["Rubber Duck Debugging"]

    FEAT --> |"Clear spec"| F1["Constraint-First"]
    FEAT --> |"Vague idea"| F2["Reverse Prompting"]
    FEAT --> |"Complex"| F3["Plan Then Execute"]

    REFACTOR --> |"Scoped"| R1["Scope Lock"]
    REFACTOR --> |"Large"| R2["Incremental Disclosure"]

    ARCH --> |"Design"| A1["The Interview"]
    ARCH --> |"Review"| A2["Pre-Mortem"]

    UI --> |"Mockup"| U1["Screenshot-Driven UI"]
    UI --> |"From scratch"| U2["Reference Implementation"]

    DOC --> |"Finalise"| D1["SOURCE FACTS / CHANGE LIST"]
    DOC --> |"Handoff deliverable"| D2["The Closeout Trio"]

    style START fill:#4A90D9,stroke:#357ABD,color:#fff
    style B1 fill:#50C878,stroke:#3CB371,color:#fff
    style B2 fill:#50C878,stroke:#3CB371,color:#fff
    style F1 fill:#7B68EE,stroke:#6A5ACD,color:#fff
    style F2 fill:#7B68EE,stroke:#6A5ACD,color:#fff
    style F3 fill:#7B68EE,stroke:#6A5ACD,color:#fff
    style R1 fill:#FFB347,stroke:#FFA500,color:#333
    style R2 fill:#FFB347,stroke:#FFA500,color:#333
    style A1 fill:#FF6B6B,stroke:#EE5A5A,color:#fff
    style A2 fill:#FF6B6B,stroke:#EE5A5A,color:#fff
    style U1 fill:#DDA0DD,stroke:#BA55D3,color:#333
    style U2 fill:#DDA0DD,stroke:#BA55D3,color:#333
    style D1 fill:#14B8A6,stroke:#0F766E,color:#fff
    style D2 fill:#14B8A6,stroke:#0F766E,color:#fff

The Patterns

1. Reverse Prompting

When to use: Starting a new feature with unclear requirements.

Ask me 20 clarifying questions about how this feature should work
before you start implementing anything.

Why it works: Claude has seen millions of software projects and knows which edge cases matter. Its questions surface requirements you hadn’t considered. Your domain knowledge + Claude’s pattern recognition = better specs than either alone.


2. Constraint-First

When to use: Any task where you want to limit scope.

Fix the date formatting bug in src/utils/dates.ts.
Only modify that one file. Do not touch any tests, components,
or other utilities. Do not add error handling or logging.

Why it works: Without explicit constraints, Claude will “helpfully” refactor surrounding code, add error handling, update tests, and improve things you didn’t ask for. Constraints prevent scope creep.


3. Smallest Failing Test

When to use: Bug fixes.

This test fails with "Expected 200, received 413" when uploading
a PNG file over 5MB through the multipart handler.

Make the test pass. Don't change the test itself.

Why it works: A precise failing test gives Claude a clear success criterion. “Users can’t upload files” is vague. A specific test with a specific error is actionable.


4. Example-Driven Spec

When to use: Building something that should follow an existing pattern.

Look at how UserService is structured in src/services/user.service.ts —
the constructor injection, the CRUD methods, the error handling pattern,
and the corresponding test file.

Build OrderService following the exact same pattern.

Why it works: Instead of describing the pattern in words, you point to working code. Claude reads the example and replicates the structure, naming conventions, and error handling exactly.


5. Context Snippet

When to use: Showing Claude a specific problem in a large file.

The bug is in the authentication middleware. Here's the relevant section
(lines 45-65 of src/middleware/auth.ts):

const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token' });
// BUG: jwt.verify throws on expired tokens instead of returning null
const decoded = jwt.verify(token, process.env.JWT_SECRET);

Wrap the verify call in a try-catch that returns 401 for expired tokens.

Why it works: Pasting 500 lines wastes context tokens. Extracting the relevant 20 lines focuses Claude on the actual problem and preserves context for the solution.


6. Explicit System Boundaries

When to use: First message in any session.

This is a Node.js Express API with TypeScript, Prisma ORM on SQL Server
(not Postgres), Jest for testing, and deployed to Azure Container Instances.
The frontend is React 18 with Tailwind CSS.

Why it works: Claude defaults to common stacks (Postgres, Vercel, Next.js). Stating your actual stack upfront prevents wrong assumptions — especially important for less common setups like SQL Server or Azure.


7. Single-Task Sessions

When to use: Always. This is a meta-pattern.

Let's focus on ONE thing this session: fix the login redirect bug
where users are sent to /dashboard instead of their intended URL
after authentication. Don't touch any other features.

Why it works: Multi-task sessions have lower success rates. Each task adds context that pollutes the next. One task per session = higher quality output and faster completion.


8. Plan Then Execute

When to use: Complex features requiring architectural decisions.

I need to add real-time notifications to the app. Before writing any code,
plan the approach:

1. What transport mechanism (WebSocket, SSE, polling)?
2. Where does notification state live?
3. What changes are needed in the database schema?
4. Which files need to be modified?

Don't implement anything yet. Just give me the plan.

Why it works: Separating planning from execution prevents Claude from committing to the first approach it thinks of. You review the plan, make corrections, then execute in a fresh session with clean context.


9. Negative Constraints

When to use: When Claude keeps adding things you don’t want.

Fix the null check on line 42 of user.service.ts.

Do NOT:
- Add error handling
- Add logging
- Refactor surrounding code
- Update tests
- Add type guards
- "Improve" anything else

Why it works: Claude’s default behavior is to be helpful by doing more than asked. Explicit negative constraints override this tendency. List specific things you don’t want.


10. Chain-of-Thought Architecture

When to use: Before implementing complex logic.

Walk me through your reasoning for how you'd implement rate limiting
on our API endpoints. Consider:
- Where in the middleware stack it should go
- What storage backend for rate limit counters
- How to handle distributed instances
- Edge cases with authentication

Show your thinking before writing any code.

Why it works: Forcing Claude to articulate its reasoning before coding catches flawed assumptions early. It’s cheaper to fix a wrong approach in a plan than in 500 lines of code.


11. Verify Before Done

When to use: End of every implementation task.

After making the changes:
1. Run `npm test` and show me the full output
2. Run `npx tsc --noEmit` and confirm zero errors
3. Show me the git diff of everything you changed

Don't tell me you're done until all three pass.

Why it works: Without this, Claude will say “Done!” based on code analysis alone. Requiring actual test output catches the bugs that look correct in code but fail at runtime.


12. Reference Implementation

When to use: When a working example exists elsewhere.

Make the settings page work exactly like the profile page at
src/pages/Profile.tsx — same layout structure, same form validation
pattern, same toast notifications, same error states.

Why it works: “Make it like X” is more precise than describing X from scratch. Claude reads the reference, understands the patterns, and replicates them consistently.


13. Incremental Disclosure

When to use: Large features that benefit from staged implementation.

We're building a notification system. Let's do this in stages.

Stage 1 (this session): Just the data model.
Create the Prisma schema for notifications — types, recipients,
read status, timestamps. Don't worry about the API or UI yet.

Why it works: Giving Claude the entire feature spec at once leads to shortcuts and assumptions. Staged disclosure lets you verify each layer before building the next, catching issues early.


14. Rubber Duck Debugging

When to use: When you can’t figure out why something’s broken.

Explain this function to me line by line. For each line, tell me:
- What it does
- What assumptions it makes
- What could go wrong

[paste the function]

Why it works: The act of explaining code line-by-line often reveals bugs that reading can’t. Claude’s fresh perspective catches stale assumptions and implicit dependencies you’ve become blind to.


15. The Interview

When to use: Requirements gathering for a new module or system.

You are the senior architect on this project. Interview me about
the requirements for the new reporting module. Ask questions about:
- Who uses it and how often
- What data sources it needs
- Performance requirements
- Security constraints
- Integration points

One question at a time. Go deep on each answer.

Why it works: Role-based prompting activates Claude’s knowledge of what an architect would ask. The interview format ensures thorough coverage of requirements that a spec document might miss.


16. Scope Lock

When to use: Bug fixes and surgical changes.

The bug is that deleted users still appear in the team members dropdown.

Fix ONLY this bug. Change the minimum number of lines possible.
No refactoring. No "while we're here" improvements. No new abstractions.
If you're tempted to change something unrelated, don't.

Why it works: Bug fix PRs should be small and reviewable. Scope lock prevents Claude from turning a 3-line fix into a 200-line refactor that introduces new risks.


17. Screenshot-Driven UI

When to use: Any visual/frontend work.

I need the dashboard to match this layout. After each round of changes:
1. Take a screenshot of localhost:3000/dashboard
2. Compare it against the target — check sidebar, colors, spacing
3. List specific discrepancies
4. Fix them and screenshot again

Iterate until it matches. Don't move on until we confirm visually.

Why it works: Claude can’t see what it’s producing. Without screenshots, it guesses based on CSS values. Screenshot-driven iteration closes the feedback loop and catches visual bugs that code review misses.


18. Pre-Mortem

When to use: Before implementing anything risky.

Before we implement this caching layer, do a pre-mortem:

1. What are the top 5 things that could go wrong?
2. What's the worst-case failure mode?
3. What monitoring would we need?
4. What's the rollback plan?
5. Are there simpler alternatives we should consider first?

Why it works: Pre-mortems surface risks before you’ve invested in the implementation. It’s much cheaper to add cache invalidation to the plan than to debug stale data in production.


19. Diff Review

When to use: Before committing any changes.

Before committing, show me a summary of every file you changed:
- What was changed and why
- Any files that were modified but maybe shouldn't have been
- Anything you're uncertain about

Then show the full git diff.

Why it works: Claude sometimes modifies files it shouldn’t or makes changes with unintended side effects. A diff review catches these before they enter version control.


20. Session Handoff

When to use: End of a session that will continue later.

We're stopping here. Write a handoff summary:

1. What was accomplished this session
2. What's left to do
3. Any decisions made and why
4. Any gotchas or blockers the next session should know about
5. Which files were modified

Save this to SESSION_NOTES.md so the next session can pick up cleanly.

Why it works: Context doesn’t survive between sessions. A structured handoff preserves decisions, progress, and warnings that would otherwise be lost, preventing the next session from repeating work or making contradictory choices.


21. SOURCE FACTS / CHANGE LIST

When to use: Finalising a document where factual accuracy and preservation both matter — executive status reports, regulatory and compliance documents, second-pass edits where “tighten this up” has historically rephrased a number into an inaccuracy.

You are finalising [artefact type] for [audience].

Rewrite the DRAFT to apply every item in CHANGE LIST,
preserving every substantive fact in SOURCE FACTS.

OUTPUT RULES
- [style, length, tone, forbidden constructs]

CHANGE LIST, fix every one of these
1. [specific directive]
2. [specific directive]
...

SOURCE FACTS, use these, do not round them
[structured authoritative data, tables, counts]

DRAFT
[current draft, or state "no draft, build from facts"]

Why it works: The model treats the current draft as authoritative by default and preserves its language patterns, including the inaccuracies. Separating facts from instructions prevents rounding drift, lost caveats, and hallucinated middle-ground values where SOURCE FACTS has the exact number.

Gotcha: if the draft placeholder is empty, say so explicitly. The model will silently proceed from SOURCE FACTS alone, which is usually fine but occasionally loses phrasing that had already been socialised. Distinct from Constraint-First (§2) — that locks scope; this locks facts.


22. The Closeout Trio

When to use: Handing back any substantive deliverable — written document, mixed output, research note. Per-deliverable, not per-session.

End every substantive deliverable with three sections:

1. What I did
   Concrete, checkable facts. Paragraph counts before and after.
   File sizes. Page counts. Not "I updated the document" but
   "98 paragraphs became 108 paragraphs, +10 from two five-element chart blocks."

2. What I could not do and why
   Explicit capability boundaries. "I cannot reach your local repo,
   so I produced the four files and a paste-ready commit block."
   This is where you catch the model trying to hide a gap.

3. What needs your eyes
   Things the model cannot adjudicate: pre-existing data tension between
   two sources, cosmetic layout questions, numbers that look right but
   need a human ticking them off, anything that touched a
   "don't change X" constraint.

Why it works: Without this closeout, the model optimises for appearing-done. With it, the model optimises for being-reliable. The numeric specifics in “what I did” make it harder to fabricate completion. “What I could not do” normalises admitting capability gaps so the model stops papering over them. Paired with Silent Conflict Resolution anti-pattern (§22) for the written-deliverable equivalent of “the tests pass so it’s fine”.

Scope vs related material: skills/verification-before-completion/ is the code-side equivalent — run the tests, paste the output. This is the version for writing and mixed outputs where “does it compile” is not the check. skills/handoff/ is session-end summary; this is per-deliverable — different scope.


Anti-Patterns

These prompts consistently produce poor results. Avoid them.

1. The Vague Request

Make the code better.

Why it fails: “Better” means nothing. Claude will add error handling, refactor variable names, add comments, and restructure code — none of which you asked for. Be specific about what “better” means.

2. The Kitchen Sink Session

Fix the login bug, then add the new dashboard widget, then update
the API documentation, then review the open PRs.

Why it fails: Each task pollutes context for the next. By task 3, Claude has forgotten the constraints from task 1. One task per session.

3. The Missing Error Message

The build is broken. Fix it.

Why it fails: Claude will guess what’s wrong based on common errors. Paste the actual error message, stack trace, or failing test output. Guessing wastes cycles.

4. The Infinite Iterator

That's not quite right. Try again.
Almost. One more try.
Getting closer. Keep going.

Why it fails: Each iteration adds more polluted context. If the first attempt is wrong, the specification was unclear. Close the session, clarify the spec, start fresh.

5. The Full File Dump

Here's my entire 800-line file. Find the bug.
[pastes everything]

Why it fails: You just burned 800 lines of context on a problem that probably lives in 10 lines. Extract the relevant section. Tell Claude where to look.

6. The “Fix Everything”

There are a bunch of issues in this codebase. Fix them all.

Why it fails: No priority, no scope, no success criteria. Claude will chase low-value issues while missing the critical ones. Prioritize and tackle one at a time.

7. No Verification

Looks good, ship it.

Why it fails: You didn’t run the tests. You didn’t build. You didn’t check the browser. Claude’s code looks correct 90% of the time — the other 10% is where production bugs live.

8. Blaming the Environment

This works on my machine. Your code must be wrong.

Why it fails: Maybe it is wrong. But maybe your environment has a stale deployment, a different Node version, or a missing env variable. Check the actual state before assuming.


Built by Force Information Systems · Harris Computer · Constellation Software. Licensed under MIT.