Skip to content

A01: Prompt Engineering for Claude Code ​

Related chapters: Ch1 Installation & First Session, Ch2 CLAUDE.md & Memory, Ch6 Custom Skills

Prompt engineering for Claude Code is fundamentally different from prompting a chatbot. When you're talking to Claude in a browser, you're crafting text for text generation. When you're working with Claude Code, you're giving instructions to an agent that has tools, makes multi-step decisions, and operates on your real filesystem. This appendix covers the specific patterns that make Claude Code effective.

Why Claude Code Prompting Is Different ​

In a chat interface, your prompt is the only input Claude receives. In Claude Code, your prompt is one of many inputs:

Claude Code's full context:
┌──────────────────────────────────────┐
│ System prompt (Claude Code's core)   │  ← You don't control this
│ CLAUDE.md (your project rules)       │  ← You control this (Ch2)
│ Memory files (saved preferences)     │  ← Claude manages this
│ Tool definitions (Read, Write, etc.) │  ← You don't control this
│ Conversation history                 │  ← Both of you build this
│ Your current prompt                  │  ← You control this
│ Tool results (file contents, etc.)   │  ← Generated by tools
└──────────────────────────────────────┘

This means your prompt doesn't need to carry all the context. CLAUDE.md handles project standards. Memory handles your preferences. Tool results handle the actual code. Your prompt just needs to say what to do and why.

The Specificity Spectrum ​

Every prompt falls on a spectrum from vague to over-constrained. The optimal zone depends on your task:

Too Vague (Ineffective) ​

Fix the bug.

Problem: Claude doesn't know which bug, where to look, or what "fixed" looks like. It will waste tool calls exploring the codebase randomly.

Too Constrained (Inefficient) ​

Open src/auth/middleware.ts at line 42. Change the if statement from 
`if (token.expired)` to `if (token.expired || !token.valid)`. Then open 
src/auth/types.ts and add a `valid: boolean` field to the Token interface 
on line 15. Then run npm test.

Problem: You've done all the thinking. If you already know exactly what to change, just change it yourself. You're using Claude as a typing assistant, not a reasoning partner.

Just Right (Effective) ​

Users are reporting 401 errors when their JWT token has been rotated but the 
old token hasn't expired yet. The issue is likely in the auth middleware 
(src/auth/). Find where we validate tokens and add a check for token 
validity beyond just expiration. Run the auth tests to verify.

Why this works:

  • What: Fix 401 errors during token rotation
  • Where: src/auth/ directory (narrows the search)
  • Why: Token validity check is missing (explains the root cause)
  • How to verify: Run the auth tests (defines success)
  • What's NOT specified: Exact files, line numbers, implementation details — Claude figures these out

The Five Prompt Patterns for Claude Code ​

Pattern 1: The Investigation Prompt ​

Use when you need Claude to understand something before acting.

I'm seeing intermittent 500 errors in production. The error logs mention 
a "connection pool exhausted" message from the database layer. 

Investigate:
1. Find where we configure the database connection pool
2. Check if there's connection leak potential (connections opened but not closed)
3. Look at the middleware chain for anything that might hold connections open
4. Report your findings before making any changes

Key elements:

  • Describe symptoms, not solutions
  • Ask Claude to report before changing
  • Give starting points but don't prescribe the investigation path

Pattern 2: The Implementation Prompt ​

Use when you want Claude to build something specific.

Add rate limiting to the /api/upload endpoint:
- Max 10 uploads per user per minute
- Return 429 with retry-after header when exceeded
- Use the existing Redis instance for tracking (REDIS_URL is in .env)
- Follow the pattern in src/middleware/auth.ts for middleware structure
- Add tests

Don't modify any existing endpoints.

Key elements:

  • Clear requirements with numbers
  • Point to existing patterns ("follow the pattern in...")
  • Explicit boundaries ("don't modify any existing endpoints")
  • Include tests

Pattern 3: The Review Prompt ​

Use when you want Claude to analyze without changing.

Review the changes on this branch (feature/payments) for:
1. Security issues (especially around payment data handling)
2. Error handling gaps (what happens when Stripe API is down?)
3. Missing tests for edge cases

Don't fix anything — just list the findings with severity ratings.

Key elements:

  • Specific review dimensions (not just "review this")
  • Explicit "don't fix" instruction (Claude will try to fix otherwise)
  • Ask for severity to help prioritize

Pattern 4: The Refactoring Prompt ​

Use when you want Claude to restructure existing code.

The user authentication logic is split across 4 files with duplicated 
validation. Consolidate into a single auth service:
- Keep the public API unchanged (same function signatures)
- Extract shared validation into private methods
- Don't change the database schema
- Run existing tests to verify nothing breaks

Key elements:

  • Describe the current problem (duplication)
  • Describe the target (single service)
  • Constraints ("keep the public API unchanged")
  • Verification step ("run existing tests")

Pattern 5: The Exploration Prompt ​

Use when you're learning a codebase or technology.

I just joined this project. Walk me through the architecture:
1. What's the tech stack? (read package.json, go.mod, or equivalent)
2. How is the code organized? (describe the directory structure)
3. Where's the main entry point?
4. How does a request flow from the API layer to the database?
5. What testing patterns are used?

Key elements:

  • Open-ended but structured
  • Numbered questions (Claude answers each one)
  • Starts broad, goes specific

Anti-Patterns: What NOT to Do ​

Anti-Pattern 1: "Be Careful" ​

Be very careful when making changes. Double-check everything. Make sure 
you don't break anything. Be extra cautious.

Why this fails: These are emotional instructions, not actionable ones. Claude doesn't have a "careful mode." Instead, tell Claude specifically what to watch for:

Before committing: run the test suite, check for TypeScript errors with 
tsc --noEmit, and verify the API responses haven't changed shape.

Anti-Pattern 2: Premature Abstraction Requests ​

Create a flexible, extensible framework for handling all possible 
authentication scenarios. It should support OAuth, SAML, JWT, API keys, 
and any future auth methods.

Why this fails: Claude will over-engineer a massive abstraction that nobody needs. Instead, build for your current needs:

Add JWT authentication to the /api/users endpoint. Use the jsonwebtoken 
package. Store the secret in process.env.JWT_SECRET.

Anti-Pattern 3: Chaining Unrelated Tasks ​

Fix the login bug, then add a dark mode toggle, then update the README, 
then review the PR from last week.

Why this fails: Context rot. By the time Claude reaches task 4, it has forgotten the details of task 1. See A02 Context Engineering. Instead, do one task per session or use /clear between unrelated tasks.

Anti-Pattern 4: Referencing External Knowledge Claude Doesn't Have ​

Implement the solution from that Stack Overflow answer we discussed yesterday.

Why this fails: Claude doesn't have memory of conversations in other tools (browser, Slack, etc.). Give it the actual content:

Implement this approach for handling race conditions:
[paste the specific approach, not just a link]

Prompt Templates for Common Tasks ​

Bug Fix Template ​

Bug: [describe the symptom]
Expected: [what should happen]
Actual: [what happens instead]
Reproduce: [steps or test case]
Suspected area: [file or module, if known]

Find the root cause, fix it, and add a regression test.

Feature Implementation Template ​

Feature: [one-sentence description]
Requirements:
- [requirement 1]
- [requirement 2]
- [requirement 3]
Constraints:
- [what NOT to change]
- [performance/security requirements]
Pattern to follow: [reference existing code]
Verify: [how to test]

Code Review Template (Pipe Mode) ​

bash
git diff main..HEAD | claude -p "Review these changes:
1. Correctness: any logic bugs?
2. Security: any vulnerabilities (OWASP top 10)?
3. Performance: any N+1 queries, unnecessary re-renders, or memory leaks?
4. Style: anything inconsistent with the existing codebase?

Rate each category: PASS / CONCERN / FAIL. Explain any non-PASS ratings."

Chain-of-Thought in Tool-Calling Contexts ​

In a chatbot, chain-of-thought means "think step by step before answering." In Claude Code, chain-of-thought happens naturally through the tool-calling loop:

  1. Claude reads the prompt and decides what information it needs
  2. It calls Read/Glob/Grep to gather context
  3. With each tool result, it refines its understanding
  4. It eventually acts (Write/Edit/Bash)

You can enhance this natural chain-of-thought by structuring your prompt to encourage investigation before action:

Before implementing anything:
1. Read the existing tests to understand what's expected
2. Check if there's a similar feature elsewhere in the codebase
3. Plan the approach and tell me before you start coding

Then implement.

This "investigate, plan, implement" structure is formalized as the R-P-E-R-S workflow in Ch15 Production Workflows.

Token Efficiency in Prompts ​

Your prompt is a small fraction of Claude Code's context, but it sets the direction for everything that follows. A well-structured prompt leads to fewer tool calls, less context consumption, and better results.

Efficient: Point Claude to the right place

The rate limiter config is in src/config/rate-limits.ts. Increase the 
/api/upload limit from 10 to 25 per minute.

Claude reads one file, makes one edit. ~500 tokens total.

Inefficient: Make Claude search

Somewhere in the config files there's a rate limit setting. Find it and change it.

Claude searches multiple files, reads several configs. ~3,000 tokens total.

Both produce the same result, but the efficient prompt uses 6x fewer tokens. When you know where something is, say so. When you don't, that's fine, but acknowledge it:

I'm not sure where the rate limit config lives. Check src/config/ first, 
then the middleware directory.

Key Takeaways ​

  1. Your prompt is one input among many — CLAUDE.md, memory, and tool results carry most of the context. Keep prompts focused on WHAT and WHY.
  2. Describe symptoms, not solutions for investigation tasks. Let Claude use its tools to find the answer.
  3. Point to existing patterns when asking for implementations. "Follow the pattern in src/auth/middleware.ts" is more effective than specifying every detail.
  4. One task per session (or use /clear between unrelated tasks) to avoid context rot.
  5. Ask Claude to investigate before acting for complex tasks. The natural chain-of-thought through tool calls produces better results than jumping straight to implementation.
  6. "Be careful" is not actionable. Replace emotional instructions with specific verification steps.

See also: A02 Context Engineering for how to manage the full context budget, and A05 Tool Calling Internals for how Claude decides which tool to use.

Released under MIT License