Official References: Claude Code Overview · Claude Code Best Practices · Prompt Engineering Guide
Curriculum path
- CLAUDE.md Mastery — repo memory and rules
- Effective Prompting — task framing and constraints ← You are here
- MCP Power Tools — connect live tools and docs
- Multi-Agent Workflows — delegate and parallelize
- Hooks Automation — automate guardrails locally
- GitHub Actions Workflows — move repeatable work into team automation
Official docs used in this guide
- Prompting patterns and best practices — Best practices
- General prompt engineering concepts — Prompt engineering
- Claude Code usage model — Overview
The Key Insight
Claude Code isn't a chatbot — it's a junior engineer with perfect memory and infinite patience. The best prompts are the same instructions you'd give a competent teammate.
Prompting Levels
Level 1: Direct Commands
Good for simple, well-defined tasks:
Fix the TypeScript error in src/auth/login.ts
Add input validation to the signup form — email format and password min 8 chars
Level 2: Context + Intent
Better for tasks that need judgment:
The /api/users endpoint is slow (~2s). Profile it and suggest optimizations.
Don't change the database schema — we're mid-migration.
The constraint ("don't change schema") prevents Claude from going down the wrong path.
Level 3: Architectural Delegation
For complex, multi-step work:
Refactor the payment module from callbacks to async/await.
1. Start with the stripe integration (src/payments/stripe.ts)
2. Update the order processor that depends on it
3. Make sure existing tests still pass
4. Don't touch the PayPal integration — that's next sprint
Numbered steps give Claude a roadmap. Exclusions prevent scope creep.
Anti-Patterns
The Vague Request
❌ "Make the code better"
✅ "Reduce the cyclomatic complexity of processOrder() — it has 12 branches"
The Kitchen Sink
❌ "Rewrite the entire auth system, add OAuth, implement RBAC, and add 2FA"
✅ "Add Google OAuth to the existing auth system. Keep the current session management."
(Then follow up with RBAC and 2FA as separate tasks)
Assuming Context
❌ "Fix the bug"
✅ "Fix the race condition in useCart — adding items rapidly creates duplicate entries"
The "Plan First" Pattern
For non-trivial tasks, ask Claude to plan before executing:
I want to add real-time notifications using WebSockets.
Before writing any code, outline your approach:
- Which library?
- Where does the WebSocket server live?
- How does it integrate with our existing auth?
This catches architectural mismatches before Claude writes 500 lines in the wrong direction.
Extended Thinking Mode
Claude Code lets you dial up reasoning depth based on the complexity of your task:
| Situation | Phrasing |
|---|---|
| Routine work | Default mode is fine |
| Complex problems | "think hard", "think carefully" |
| Architecture decisions | "ultrathink", "think as deeply as possible" |
❌ "How should I restructure the auth layer?"
✅ "Use ultrathink to analyze migrating our session-based auth to JWT.
Include security trade-offs, rollback strategy, and a phased migration plan."
For significant design decisions or complex refactors, this pattern gets Claude to surface edge cases and risks it might otherwise skip.
Conversation Management
When to Start a New Conversation
A fresh conversation is often more efficient than a long thread:
- When you're switching to a different feature after finishing the current one
- When Claude's responses seem overly anchored to earlier context
- When response quality noticeably drops after a long session
Using /compact
Compress context mid-conversation to save tokens and restore focus:
/compact
Claude summarizes the conversation so far, keeping only the essential context. Most useful when you're approaching token limits or working across a long session.
Paste Screenshots Directly
For UI bugs and layout issues, a screenshot communicates more precisely than text descriptions:
[paste screenshot]
"The button overlaps the nav bar on mobile. Fix it."
A single screenshot eliminates ambiguity that paragraphs of description can't resolve.
Iterative Refinement Pattern
Claude Code's key advantage over autonomous tools is the conversation loop. Don't try to write the perfect prompt upfront — refine progressively:
Round 1: "Add login functionality"
→ Review output
Round 2: "Good. Now make the error messages user-friendly —
'Invalid credentials' should say 'Incorrect email or password'"
→ Review output
Round 3: "Last thing: add rate limiting — lock for 5 minutes after 5 failed attempts"
Each round is a verifiable, contained unit of work. The quality compounds.
Slash Commands
Claude Code has built-in commands that streamline your workflow:
| Command | What it does |
|---|---|
/help |
List available commands and capabilities |
/compact |
Compress conversation context to save tokens |
/clear |
Reset the conversation — useful when starting a new task |
/cost |
Check API costs for the current session |
You can also define custom slash commands in CLAUDE.md to automate project-specific workflows.
"Tell Me" vs "Do It" Pattern
Asking for an explanation and asking for action produce very different results:
❌ "How does the auth system work?"
→ You get an explanation
✅ "Analyze the auth system and fix any security vulnerabilities you find"
→ Claude reads the code and makes changes
❌ "Why is this API slow?"
→ You get a list of possible causes
✅ "Profile this API, find the bottleneck, and fix whatever you can right now"
→ Diagnosis + implementation
Claude Code is an engineer, not an analyst. Ask for action.
File References for Precise Context
You can mention files directly in your prompt and Claude will read them. Instead of expecting Claude to search the entire codebase, point it to the relevant files:
Read src/types/user.ts first, then add a new field for avatar_url
Look at src/auth/login.ts — the token refresh logic seems off
Full paths or relative paths both work. You can also drag and drop files into the prompt for quick context.
Best practice: Point Claude to relevant files rather than expecting it to search the entire codebase. Faster input, more accurate output.
Non-Interactive Mode
claude --print (or claude -p) runs a single prompt with no conversation — perfect for scripts and pipelines:
# Summarize error logs
cat error.log | claude -p "summarize these errors"
# Save output to a file
claude -p "generate test for src/utils.ts" > tests/utils.test.ts
# Get structured JSON output
claude -p --output-format json "list all exported functions in src/api/"Practical Examples
Git commit message generation:
git diff --staged | claude -p "write a conventional commit message"Code review in CI:
claude -p "review this diff for security issues" < pr.diffDocumentation generation:
claude -p "generate JSDoc for all exported functions in src/api/"Works anywhere: Makefiles, shell scripts, git hooks.
Model Selection Strategy
Use /model to switch models mid-conversation. Match the model to your task's complexity for optimal cost and performance:
| Task | Recommended Model |
|---|---|
| Architecture review, complex debugging | opus |
| Feature implementation, code review | sonnet (default) |
| Quick questions, file search, formatting | haiku |
For non-interactive mode, use the --model flag:
claude -p --model haiku "explain this error"Cost awareness: haiku is roughly 10x cheaper than opus per token. Start with sonnet, escalate to opus for complex reasoning, and use haiku for bulk or batch tasks.
Permission Modes
Use --allowedTools to pre-approve specific tools and reduce permission prompts:
claude --allowedTools "Edit,Write,Bash(git *)"For persistent configuration, set allowed tools in .claude/settings.json:
{
"permissions": {
"allow": ["Edit", "Write", "Bash(npm test)", "Bash(npm run lint)"]
}
}For fully automated scripts (CI only, never interactive), --dangerouslySkipPermissions bypasses all permission checks.
Best practice: Start restrictive, gradually allow tools you trust.
Codex Comparison
GPT Codex works differently — you write a task description upfront and it executes autonomously. There's no back-and-forth conversation. This means:
- Codex prompts need to be more complete upfront
- Claude Code allows iterative refinement
- Both benefit from explicit constraints and examples