Skip to content

2. Core Workflow

Last updated:

What you’ll learn: The mental model and critical workflows for Claude Code mastery.

  • Interaction Loop: Describe → Analyze → Review → Accept/Reject cycle
  • Context Management 🔴 CRITICAL: Watch Ctx(u):, /compact at 70%, /clear at 90%
  • Plan Mode: Read-only exploration before making changes
  • Rewind: Undo with Esc×2 or /rewind
  • Mental Model: Claude = expert pair programmer, not autocomplete

Always check context % before starting complex tasks. High context = degraded quality.

Read this section if: You want to avoid the #1 mistake (context overflow) Skip if: You just need quick command reference (go to Section 10)


Reading time: 20 minutes

Skill level: Day 1-3

Goal: Understand how Claude Code thinks

Every Claude Code interaction follows this pattern:

┌─────────────────────────────────────────────────────────┐
│ INTERACTION LOOP │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. DESCRIBE ──→ You explain what you need │
│ │ │
│ ▼ │
│ 2. ANALYZE ──→ Claude explores the codebas │
│ │ │
│ ▼ │
│ 3. PROPOSE ──→ Claude suggests changes (diff) │
│ │ │
│ ▼ │
│ 4. REVIEW ──→ You read and evaluate │
│ │ │
│ ▼ │
│ 5. DECIDE ──→ Accept / Reject / Modify │
│ │ │
│ ▼ │
│ 6. VERIFY ──→ Run tests, check behavior │
│ │ │
│ ▼ │
│ 7. COMMIT ──→ Save changes (optional) │
│ │
└─────────────────────────────────────────────────────────┘

The loop is designed so that you remain in control. Claude proposes, you decide.

🔴 This is the most important concept in Claude Code.

The zones (author heuristics, not native compaction thresholds):

  • 🟢 0-50%: Work freely
  • 🟡 50-75%: Be selective
  • 🔴 75-90%: Review relevance and consider /compact
  • ⚫ 90%+: Preserve state and assess compaction or a new session

When context is high:

  1. /compact (summarizes active context and frees space; details can be omitted)
  2. /clear (resets the active conversation; saved sessions can still be resumed)

Prevention: Load only needed files, compact regularly, commit frequently


Context is Claude’s “working memory” for your conversation. It includes:

  • All messages in the conversation
  • Files Claude has read
  • Command outputs
  • Tool results

The context window depends on the selected model and provider. Opus 5.5, Sonnet 5.5 and Fable 5.1 have native 1M-token windows on the direct API; Haiku 4.5 has 200K. Inspect /context for the active session. Capacity does not guarantee that every detail will be retrieved reliably.

The statusline shows your context usage:

Claude Code │ Ctx(u): 45% │ Cost: $0.23 │ Session: 1h 23m
MetricMeaning
Ctx(u): 45%You’ve used 45% of context
Cost: $0.23API cost so far
Session: 1h 23mTime elapsed

The default statusline can be enhanced with more detailed information like git branch, model name, and file changes.

Option 1: ccstatusline (recommended)

Add to ~/.claude/settings.json:

{
"statusLine": {
"type": "command",
"command": "npx -y ccstatusline@latest",
"padding": 0
}
}

This displays: Model: Sonnet 4.6 | Ctx: 0 | ⎇ main | (+0,-0) | Cost: $0.27 | Session: 0m | Ctx(u): 0.0%

Option 2: Custom script

Create your own script that:

  1. Reads JSON data from stdin (model, context, cost, git info)
  2. Outputs a single formatted line to stdout
  3. Supports ANSI colors for styling
{
"statusLine": {
"type": "command",
"command": "/path/to/your/statusline-script.sh",
"padding": 0
}
}

Use /statusline command in Claude Code to auto-generate a starter script.

Available JSON fields (stdin):

FieldTypeDescription
modelstringCurrent model name
contextobjectused, total, percentage
cost_usdnumberSession cost
gitobjectBranch, staged/unstaged counts
rate_limitsobjectClaude.ai usage (v2.1.80+)

rate_limits object (v2.1.80+): displays Claude.ai token usage directly in the statusline without opening the dashboard:

{
"rate_limits": {
"5h": { "used_percentage": 42, "resets_at": "2026-03-20T15:30:00Z" },
"7d": { "used_percentage": 18, "resets_at": "2026-03-23T00:00:00Z" }
}
}

Example usage in a statusline script:

#!/usr/bin/env bash
input=$(cat)
pct_5h=$(echo "$input" | jq -r '.rate_limits["5h"].used_percentage // "?"')
echo "RL: ${pct_5h}%"

These are workflow heuristics, not product states or automatic-compaction triggers. Inspect /context; recovery depends on the model, settings and retained content.

ZoneUsageAction
🟢 Green0-50%Work freely
🟡 Yellow50-75%Start being selective
🔴 Red75-90%Review relevance and consider /compact
⚫ Critical90%+Preserve state and assess compaction or a new session

When context gets high:

Option 1: Compact (/compact)

  • Summarizes the conversation
  • Aims to preserve relevant context, but can omit details
  • Reduction varies with the conversation; no fixed percentage is guaranteed

When /compact goes wrong: Compaction fires when the model has the most accumulated context, meaning it is also at its most distracted point. If the model cannot predict where the work is heading (e.g., auto-compact fires mid-debugging and your next message is “now fix that warning in bar.ts”), it may drop future-relevant info from the summary. Mitigate by compacting proactively and with context: /compact focus on the auth refactor, drop the test debugging guides the summary toward what matters next. (Source: Anthropic internal guidance)

Option 2: Clear (/clear)

  • Resets the active conversation
  • Does not delete saved session history or project instruction files
  • Use when changing topics; see session resumption

“One Task, One Chat”: mixing unrelated topics across turns degrades model accuracy by ~39%. Context accumulates noise (“context rot”) that distorts judgment even when total token usage stays low. Use /clear aggressively between distinct tasks, not just when the context bar turns red.

Option 3: Summarize from here (v2.1.32+)

  • Use /rewind (or Esc + Esc) to open the checkpoint list
  • Select a checkpoint and choose “Summarize from here”
  • Claude summarizes everything from that point forward, keeping earlier context intact
  • Frees space while keeping critical context
  • More precise than full /compact

Option 4: Targeted Approach

  • Be specific in queries
  • Avoid “read the entire file”
  • Use symbol references: “read the calculateTotal function”

When approaching the red zone (75%+), /compact alone may not be enough. You need to actively decide what information to preserve before compacting.

Priority: Keep

KeepWhy
CLAUDE.md contentCore instructions must persist
Files being actively editedCurrent work context
Tests for the current componentValidation context
Critical decisions madeArchitectural choices
Error messages being debuggedProblem context

Priority: Evacuate

EvacuateWhy
Files read but no longer relevantOne-time lookups
Debug output from resolved issuesHistorical clutter
Long conversation historySummarized by /compact
Files from completed tasksNo longer needed
Large config filesCan be re-read if needed

Pre-Compact Checklist:

  1. Document critical decisions in CLAUDE.md or a session note
  2. Commit pending changes to git (creates restore point)
  3. Note the current task explicitly (“We’re implementing X”)
  4. Run /compact to summarize and free space

Pro tip: If you know you’ll need specific information post-compact, tell Claude explicitly: “Before we compact, remember that we decided to use Strategy A for authentication because of X.” Claude will include this in the summary.

Claude Code has three distinct memory systems. Knowing which one to use avoids losing context you meant to keep across sessions:

AspectSession MemoryAuto-Memory (native)Persistent Memory (Serena)
ScopeCurrent conversation onlyAcross sessions, per-projectAcross all sessions
Managed by/compact, /clear/memory command (automatic)write_memory() via Serena MCP
Lost whenSession ends or /clearExplicitly deleted via /memoryExplicitly deleted from Serena
RequiresNothingNothing (v2.1.59+)Serena MCP server
Use caseImmediate working contextKey decisions, context snippetsArchitectural decisions, patterns

Session Memory (short-term):

  • Everything in your current conversation
  • Files Claude has read, commands run, decisions made
  • Managed with /compact (compress) and /clear (reset)
  • Disappears when you close Claude Code

Auto-Memory (native, v2.1.59+):

  • Built into Claude Code, no MCP server or configuration required
  • Claude automatically saves useful context (decisions, patterns, preferences) to MEMORY.md files
  • Organized per-project: .claude/memory/MEMORY.md or ~/.claude/projects/<path>/memory/MEMORY.md
  • Managed with /memory: view, edit, or delete what’s been saved
  • Survives across sessions automatically

Persistent Memory (long-term, Serena MCP):

  • Requires Serena MCP server installed
  • Explicitly saved with write_memory("key", "value")
  • Survives across sessions
  • Ideal for: architectural decisions, API patterns, coding conventions

Pattern: End-of-Session Save

# Before ending a productive session:
"Save our authentication decision to memory:
- Chose JWT over sessions for scalability
- Token expiry: 15min access, 7d refresh
- Store refresh tokens in httpOnly cookies"
# Claude calls: write_memory("auth_decisions", "...")
# Next session:
"What did we decide about authentication?"
# Claude calls: read_memory("auth_decisions")

When to use which:

  • Session memory: Active problem-solving, debugging, exploration
  • Auto-memory: Decisions and context you want Claude to rediscover next session without manual effort (v2.1.59+)
  • Persistent memory (Serena): Structured key-value store for architectural decisions across many projects
  • CLAUDE.md: Team conventions, project structure (versioned with git)

Auto-compact and PostToolUse memory capture: a conflict to know about:

Claude Code auto-compacts the conversation when the remaining context drops below a fixed buffer threshold (roughly the last 6-7% of the context window, or about 13K tokens from the effective limit). In practice, this triggers somewhere in the 90-95% usage range depending on the model’s context window and reserved output tokens. Before full compaction runs, Claude Code also applies micro-compaction: a lighter pass that selectively compresses older tool results (file reads, bash outputs, search results) to free space incrementally without summarizing the whole conversation. If auto-compact fails (e.g., due to a rate limit), it retries up to 3 consecutive times before giving up for that session.

If you use a hook-based memory capture tool (like claude-mem) that saves session history via PostToolUse, auto-compact can fire and discard conversation history before the save pipeline has a chance to capture it.

Two ways to handle this:

// Option 1: disable auto-compact in your project settings.json
// (you manage compaction manually via /compact)
{
"autoCompactEnabled": false
}
Terminal window
# Option 2: keep auto-compact on, but set your tool's save threshold
# to trigger well below 80% (e.g., at 60% context usage)
# — check your memory plugin's cooldowns/threshold config

Option 1 gives full control but requires discipline. Option 2 is safer if you forget to compact manually. The general guide advice (use /compact proactively at 75%) still applies. Auto-compact disabled just means you own the timing.

See also: Memory Systems: Session vs Persistent Memory for the full comparison table and cross-session tool options.

Research shows LLM performance degrades significantly with accumulated context:

  • 20-30% performance gap between focused and polluted prompts (Chroma, 2025)
  • Degradation starts at ~16K tokens for older Claude models (Chroma, 2025); Anthropic reports noticeable degradation around 300-400K tokens on the 1M context window (task-dependent, not a fixed threshold)
  • Failed attempts, error traces, and iteration history dilute attention

Instead of managing context within a session, you can restart with a fresh session per task while persisting state externally.

Terminal window
# Canonical "Ralph Loop" (Geoffrey Huntley)
while :; do cat TASK.md PROGRESS.md | claude -p ; done

Naming note: “Ralph Loop” is used in two distinct ways in the community. Geoffrey Huntley’s original pattern (above) is about context rotation: spawning fresh sessions to avoid context rot. A separate usage, popularized by Addy Osmani and others in 2026, applies the same term to atomic task iteration in multi-agent teams: pick task → implement → validate → commit → reset context → repeat. Both share the same core mechanic (stateless loop with external state), but the scope differs. When the term appears without attribution, clarify which variant is meant.

State persists via:

  • TASK.md: Current task definition with acceptance criteria
  • PROGRESS.md: Learnings, completed tasks, blockers
  • Git commits: Each iteration commits atomically

Variant: tasks/lessons.md

A lightweight alternative for interactive sessions (no loop required): after each user correction, Claude updates tasks/lessons.md with the rule to avoid the same mistake. Reviewed at the start of each new session.

tasks/
├── todo.md # Current plan (checkable items)
└── lessons.md # Rules accumulated from corrections

The difference from PROGRESS.md: lessons.md captures behavioral rules (“always diff before marking done”, “never mock without asking”) rather than task state. It compounds over time. The mistake rate drops as the ruleset grows.

TraditionalFresh Context
Accumulate in chat historyReset per task
/compact to compressState in files + git
Context bleeds across tasksEach task gets full attention
SituationUse
Context 70-90%, staying interactive/compact
Context 90%+, need fresh start/clear then continue
Long autonomous run, task-basedFresh Context Pattern
Overnight/AFK executionFresh Context Pattern

Good fit:

  • Autonomous sessions >1 hour
  • Migrations, large refactorings
  • Tasks with clear success criteria (tests pass, build succeeds)

Poor fit:

  • Interactive exploration
  • Design without clear spec
  • Tasks with slow/ambiguous feedback loops

Variant: Session-per-Concern Pipeline

Instead of looping the same task, dedicate a fresh session to each quality dimension:

  1. Plan session: Architecture, scope, acceptance criteria
  2. Test session: Write unit, integration, and E2E tests first (TDD)
  3. Implement session: Code until all linters and tests pass
  4. Review sessions: Separate sessions for security audit, performance, code review
  5. Repeat: Iterate with scope adjustments as needed

This combines Fresh Context (clean 200K per phase) with OpusPlan (Opus for review/strategy sessions, Sonnet for implementation). Each session generates progress artifacts that feed the next.

Option 1: Manual loop

Terminal window
# Simple fresh-context loop
for i in {1..10}; do
echo "=== Iteration $i ==="
claude -p "$(cat TASK.md PROGRESS.md)"
git diff --stat # Check progress
read -p "Continue? (y/n) " -n 1 -r
[[ ! $REPLY =~ ^[Yy]$ ]] && break
done

Option 2: Script (see examples/scripts/fresh-context-loop.sh)

Terminal window
./fresh-context-loop.sh 10 TASK.md PROGRESS.md

Option 3: External orchestrators

  • AFK CLI: Zero-config orchestration across task sources
TASK.md
## Current Focus
[Single atomic task with clear deliverable]
## Acceptance Criteria
- [ ] Tests pass
- [ ] Build succeeds
- [ ] [Specific verification]
## Context
- Related files: [paths]
- Constraints: [rules]
## Do NOT
- Start other tasks
- Refactor unrelated code

/compact preserves conversation flow. Fresh context maximizes per-task attention at the cost of continuity.

Sources: Chroma Research - Context Rot | Ralph Loop Origin | METR - Long Task Capability | Anthropic - Context Engineering

ActionContext Cost
Reading a small fileLow (~500 tokens)
Reading a large fileHigh (~5K+ tokens)
Running commandsMedium (~1K tokens)
Multi-file searchHigh (~3K+ tokens)
Long conversationsAccumulates

Learn to recognize when context is running out:

SymptomSeverityAction
Shorter responses than usual🟡 WarningContinue with caution
Forgetting CLAUDE.md instructions🟠 SeriousDocument state, prepare checkpoint
Inconsistencies with earlier conversation🔴 CriticalNew session needed
Errors on code already discussed🔴 CriticalNew session needed
”I can’t access that file” (when it was read)🔴 CriticalNew session immediately

Check your context usage in detail:

/context

Example output:

┌─────────────────────────────────────────────────────────────┐
│ CONTEXT USAGE 67% used │
├─────────────────────────────────────────────────────────────┤
│ System Prompt ████████░░░░░░░░░░░░░░░░ 12,450 tk │
│ System Tools ██░░░░░░░░░░░░░░░░░░░░░░ 3,200 tk │
│ MCP Tools (5 servers) ████████████░░░░░░░░░░░░ 18,600 tk │
│ Conversation ████████████████████░░░░ 89,200 tk │
├─────────────────────────────────────────────────────────────┤
│ TOTAL 123,450 tk │
│ REMAINING 76,550 tk │
└─────────────────────────────────────────────────────────────┘

💡 The Last 20% Rule: Reserve ~20% of context for:

  • Multi-file operations at end of session
  • Last-minute corrections
  • Generating summary/checkpoint

Note: Anthropic announced a separate monthly credit for programmatic usage (claude -p, the Agent SDK, third-party apps) due on June 15, 2026, then paused it. As verified on 2026-09-30, that usage still draws from your subscription’s usage limits. See §9.13: The Interactive/Programmatic Billing Split for the announced plan and audit steps, and AI FinOps for the cost section as a whole.

Claude Code usage can draw from a subscription allowance, usage credits or API billing. Check the active account and billing path before interpreting a token-cost estimate.

Pricing Model (rates checked October 6, 2026)

Section titled “Pricing Model (rates checked October 6, 2026)”

Claude Code v2.1.280 and later defaults to Opus 5.5 on Pro, Max, Team, Enterprise, the Anthropic API, Claude Platform on AWS, Bedrock, and Google Cloud’s Agent Platform. Microsoft Foundry retains Sonnet 4.5 as its account default. Organization policy, model settings, and environment overrides can change the result. Check /model and /status for your session.

ModelInput / MTokOutput / MTokCache read / MTokContextDefault effort in Claude Code
Opus 5.5$4$20$0.201Mmedium
Sonnet 5.5$2$10$0.201Mhigh
Haiku 4.5$1$5$0.10200KNo effort parameter
Fable 5.1$10$50$0.251Mhigh

These are standard Anthropic API rates in USD, checked October 6, 2026. Subscription allowances, usage credits, cache writes, batch discounts, data residency, and partner-operated cloud pricing are separate. Sonnet 5.5 (claude-sonnet-5-5) replaced Sonnet 5 as the default Sonnet on the Anthropic API in Claude Code v2.1.284 (September 28, 2026) at the same $2/$10; Sonnet 5 is now a legacy model, and the September increase once announced for it did not occur. Official model pricing.

Fast mode supports Opus 5.5 ($8/$40 per MTok), Opus 5 and Opus 4.8 ($10/$50). It is unavailable on Sonnet and Haiku. Anthropic describes up to 2.5 times faster output; this is not a guarantee for every request. Subscription fast mode uses usage credits. Fast mode reference.

Fable 5.1 is available by explicit selection, subject to account and organization access. It is not an account-type default. Previous-generation model prices belong to the official legacy pricing table, not to the current default rows above.

200K vs 1M context: Performance, cost & use cases

Section titled “200K vs 1M context: Performance, cost & use cases”

Opus 5.5, Sonnet 5.5, and Fable 5.1 have native 1M context on the Anthropic API. The older Opus 4.6 and Sonnet 4.6 use a [1m] variant with plan-specific access. Gateway and cloud-provider settings can expose a different window; inspect /context and the provider rules.

The current native 1M models use their standard rates beyond 200K input tokens. Old beta-header and long-context premium advice for Sonnet 4/4.5 must not be applied to them. Maximum output is 128K for Opus 5.5, Sonnet 5.5, and Fable 5.1, and 64K for Haiku 4.5. Model specifications.

Illustrative token bills, not measured session costs, without caching or retries:

ExampleInputOutputSonnet 5.5Opus 5.5
Bounded review50K5K$0.15$0.30
Module refactoring150K20K$0.50$1.00
Large-context analysis500K50K$1.50$3.00

A larger window is capacity, not a guarantee of retrieval or reasoning quality. Load relevant context and evaluate the complete task. Earlier Opus 4.6 and Sonnet 4.5 retrieval measurements describe those models and their benchmark conditions; they do not establish performance for the current lineup.

Native 1M sessions normally auto-compact around 967K tokens. Use /autocompact auto to restore the model default, or /autocompact 500k to choose a smaller window. Compact or start a new session when accumulated context hurts the task, rather than treating a fixed percentage as a universal accuracy threshold.

ActionTokens ConsumedEstimated Cost
Read a 100-line file~500$0.0015
Read 10 files (1000 lines)~5,000$0.015
Long conversation (20 messages)~30,000$0.090
MCP tool call (Serena, Context7)~2,000$0.006
Running tests (with output)~3,000-10,000$0.009-$0.030
Code generation (100 lines)~2,000 output$0.030

The expensive operations:

  1. Reading entire large files - 2000+ line files add up fast
  2. Multiple MCP server calls - Each server adds ~2K tokens overhead
  3. Long conversations without /compact - Context accumulates
  4. Repeated trial and error - Each iteration costs

Strategy 1: Be specific in queries

Terminal window
# ❌ Expensive - reads entire file
"Check auth.ts for issues"
# ~5K tokens if file is large
# ✅ Cheaper - targets specific location
"Check the login function in auth.ts:45-60"
# ~500 tokens

Strategy 2: Use /compact proactively

Terminal window
# Without /compact - conversation grows
Context: 10% → 30% → 50% → 70% → 90%
Cost per message increases as context grows
# With /compact at 70%
Context: 10% → 30% → 50% → 70% → [/compact] → 30% → 50%
Frees significant context space for subsequent messages

Strategy 3: Choose the right model

Terminal window
# Evaluate Haiku for bounded tasks (standard token rates below Opus 5.5)
claude --model haiku "Fix this typo in README.md"
# Select Sonnet explicitly for standard work
claude --model sonnet "Refactor this module"
# Use Opus only for critical/complex tasks
claude --model opus "Design the entire authentication system"

Strategy 4: Limit MCP servers

// ❌ Expensive - 5 MCP servers loaded
{
"mcpServers": {
"serena": {...},
"context7": {...},
"sequential": {...},
"playwright": {...},
"postgres": {...}
}
}
// ~10K tokens overhead per session
// ✅ Cheaper - load only what you need
{
"mcpServers": {
"serena": {...} // Only for this project
}
}
// ~2K tokens overhead

Strategy 5: Batch operations

Terminal window
# ❌ Expensive - 5 separate prompts
"Read file1.ts"
"Read file2.ts"
"Read file3.ts"
"Read file4.ts"
"Read file5.ts"
# ✅ Cheaper - single batched request
"Read file1.ts, file2.ts, file3.ts, file4.ts, file5.ts and analyze them together"
# Shared context, single response

Strategy 6: Use prompt caching for repeated context (API)

If you call the Anthropic API directly (e.g., for custom agents or pipelines), prompt caching cuts costs by up to 90% on repeated prefixes.

# Mark stable sections with cache_control
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "<your large system prompt / codebase context>",
"cache_control": {"type": "ephemeral"} # Cache this prefix
}
],
messages=[{"role": "user", "content": "Fix the bug in auth.ts"}]
)

Prompt caching economics:

OperationCost multiplierTTL
Cache write1.25x base price5 minutes (default)
Cache write (extended)2x base price1 hour
Cache read (hit)0.1x base price—
Latency reductionUp to 85% for long prompts—

Break-even: 2 cache hits with 5-minute TTL. After that, pure savings.

Rules:

  • Max 4 cache breakpoints per request
  • Cache key = exact prefix match (single character change = cache miss)
  • Place breakpoints after large stable sections: system prompt, tool definitions, codebase context
  • For Claude Code itself: caching is handled automatically by the CLI. This applies to API-based workflows you build on top of Claude

Docs: prompt caching

How Claude Code handles caching automatically

Section titled “How Claude Code handles caching automatically”

Claude Code manages prompt caching without any configuration on your part. Understanding the mechanics helps you make decisions that keep cache hit rates high and costs low.

Cache prefix hierarchy

Every API call Claude Code makes structures content in this fixed order: tools → system → messages. Cache matching always starts from the beginning of this prefix. A stable tool list + stable CLAUDE.md + growing conversation history means the first two layers are almost always cache hits, while only new message turns require fresh computation.

The 20-block lookback: the long-session trap

Cache matching uses a bounded lookback of approximately 20 blocks. In a long session with many tool calls and exchanges, blocks from early in the conversation fall outside this window and become cache misses. Practical consequence: very long sessions gradually lose cache efficiency at the message layer. The fix is /compact: it compresses the conversation history into a single summary block, resetting the lookback window and restoring high hit rates.

Minimum token thresholds by model

A block must meet a minimum size to be eligible for caching. Blocks smaller than the threshold are never cached, regardless of how stable they are:

Model familyMinimum tokens
Claude Opus 5, Fable 5512
Claude Sonnet 5, Opus 4.81,024
Claude Opus 4.7, Opus 4.6, Opus 4.5, Haiku 4.54,096
Claude Sonnet 4.62,048
Claude Sonnet 4.5, Sonnet 4, Sonnet 3.7, Opus 4.1, Opus 41,024
Claude Haiku 3.5, Haiku 32,048

Short CLAUDE.md files (under ~1,000 tokens) may not be cached at all on Sonnet models. If cost optimization matters, make sure your system prompt crosses the threshold for your target model.

Tool result size and cache economics

Tool results land in the message history and stay there for the rest of the session. Every subsequent API call re-reads that history, at cache read price (0.1x), but still proportional to size. A git status output of 500 tokens costs 500 × 0.1x to read on every turn that follows. The same output at 50 tokens (filtered by a tool like RTK) costs 50 × 0.1x: 90% less, compounding across every turn in the session. Compact tool outputs are not just faster to process; they make the entire cached prefix cheaper to maintain.

The same logic applies to cache writes: a smaller history prefix means cheaper initial writes (1.25x × fewer tokens).

Monitoring cache performance in your own pipelines

When building agents or pipelines on top of the Anthropic API, the response usage object exposes cache metrics directly:

response = client.messages.create(...)
print(response.usage.cache_creation_input_tokens) # Tokens written to cache this request
print(response.usage.cache_read_input_tokens) # Tokens read from cache (hits)
print(response.usage.input_tokens) # Non-cached input tokens

Calculate your hit rate as cache_read / (cache_read + cache_creation) across requests. A ratio above 0.8 means your prompt structure is working well. Low ratios usually mean content in the stable prefix is changing between requests: check for timestamps, random IDs, or dynamic content embedded in your system prompt.

/usage includes prompt-cache statistics for the main conversation on supported current versions. For custom API pipelines, inspect the response fields above. See the cost and cache documentation.

Practical rules

  • Keep CLAUDE.md stable between sessions: edits invalidate the system cache one-shot, then it re-warms on the next request
  • Run /compact before the conversation gets very long, not after performance degrades
  • Avoid dynamic content in stable sections (dates, random values, per-request context)
  • Larger CLAUDE.md = more expensive cache write, but also more tokens saved per read, profitable after ~2 hits

Known cache bugs (v2.1.69+)

Two active bugs silently break caching on v2.1.69+. Apply these workarounds immediately:

  • —resume/—continue causes a full cache rebuild (0% hit ratio) on every resume because session JSONL strips deferred tool records before write. Workaround: avoid --resume until fixed.
  • Per-session billing header injects a unique hash as the first system prompt block, causing a cold miss on every session start and subagent call. Workaround: "CLAUDE_CODE_ATTRIBUTION_HEADER": "false" in ~/.claude/settings.json.

See Known Issues → Prompt Cache Bugs and run /check-cache-bugs for a full audit.

Docs: prompt caching

Real-time tracking:

The status line shows current session cost:

Claude Code │ Ctx(u): 45% │ Cost: $0.23 │ Session: 1h 23m
↑ Current session cost

Advanced tracking with ccusage:

The ccusage CLI tool provides detailed cost analytics beyond the /cost command (use /usage since v2.1.118):

Terminal window
ccusage daily # Daily usage from detected local sources
ccusage daily --last 1 # Today's usage
ccusage monthly # Monthly breakdown
ccusage session # Session breakdown
ccusage daily --breakdown # Costs by model

Illustrative historical output, not a current model recommendation:

┌──────────────────────────────────────────────────────┐
│ USAGE SUMMARY - January 2026 │
├──────────────────────────────────────────────────────┤
│ Today $2.34 (12 sessions) │
│ This week $8.91 (47 sessions) │
│ This month $23.45 (156 sessions) │
├──────────────────────────────────────────────────────┤
│ MODEL BREAKDOWN │
│ Sonnet 3.5 85% $19.93 │
│ Opus 4.6 12% $2.81 │
│ Haiku 3.5 3% $0.71 │
└──────────────────────────────────────────────────────┘

Why use ccusage over /cost (alias for /usage since v2.1.118)?

  • Historical trends: Track usage patterns over days/weeks/months
  • Model breakdown: See which model tier drives costs
  • Budget planning: Set monthly spending targets
  • Team analytics: Aggregate costs across developers

For a full inventory of community cost trackers, session viewers, config managers, and alternative UIs, see Third-Party Tools.

Monthly tracking:

Check your Anthropic Console for detailed usage:

Cost budgeting:

Estimate from measured input, output, cache usage and retries for representative accepted tasks. Use the provider’s billing records for charged amounts; local tools provide estimates. See the ccusage command guide for available reports.

Perspective on costs: If Claude Code saves you meaningful time on a task, the API cost is usually negligible compared to your hourly rate. Don’t over-optimize for token costs at the expense of productivity.

When to optimize:

  • ✅ You’re on a tight budget (student, hobbyist)
  • ✅ High-volume usage (>4 hours/day)
  • ✅ Team usage (5+ developers)

When NOT to optimize:

  • ❌ Your time is more expensive than API costs
  • ❌ You’re spending more time optimizing than the savings
  • ❌ Optimization hurts productivity (being too restrictive)

Choose a model and effort level that meet the task’s acceptance criteria, then compare total cost including retries and review. Route repetitive work to a cheaper model only when the measured result justifies it. A team pilot should record accepted tasks, model usage, failures and human review effort before setting a budget.

ObservationInvestigation
Cost rises during long sessionsInspect context growth and cache misses with /usage
Repeated tool calls return the same materialNarrow the request and reuse an explicit result
A cheaper model needs many retriesCompare cost per accepted task with a stronger model
Many agents repeat repository discoveryGive each a bounded scope and shared written context

Check current plans and the usage information for the signed-in account. Subscription allowances are not fixed published token budgets; API price ratios do not determine quota consumption. Model access and organization policy can change independently of the plan label. Pro is not limited to Sonnet: current defaults and available selections are described in the model table above.

Monitoring Your Usage

/usage # Session estimates, subscription limits and usage breakdown
/model # Available models for this account and provider
/status # Active account and session configuration

The session dollar estimate does not by itself represent a subscriber’s bill. /usage includes plan bars for subscription accounts and, when enabled, usage-credit information. Use the relevant Claude or provider billing page for authoritative charged amounts. Cost tracking documentation.

If you choose opusplan, Opus handles planning and Sonnet handles execution. Haiku requires separate explicit selection. Evaluate this routing policy against your work; it does not promise a fixed saving or a guaranteed number of usable hours.

When a limit interrupts work, inspect its reset information and current account policy. Preserve the task state before switching model, account or execution mode. Historical reports of quotas and peak-hour behavior are not reliable current limits.

Definition: When information from one task contaminates another.

Pattern 1: Style Bleeding

Task 1: "Create a blue button"
Claude: [Creates blue button]
Task 2: "Create a form"
Claude: [Creates form... with all buttons blue!]
↑ The "blue" bled into the new task
Solution: Use explicit boundaries
"---NEW TASK---
Create a form. Use default design system colors."

Pattern 2: Instruction Contamination

Instruction 1: "Always use arrow functions"
Instruction 2: "Follow project conventions" (which uses function)
Claude: [Paralyzed, alternating between styles]
Solution: Clarify priority
"In case of conflict, project conventions take precedence over my preferences."

Pattern 3: Temporal Confusion

Early session: "auth.ts contains login logic"
... 2h of work ...
You renamed auth.ts to authentication.ts
Claude: "I'll modify auth.ts..."
↑ Using outdated info
Solution: Explicit updates
"Note: auth.ts was renamed to authentication.ts"

Context Hygiene Checklist:

  • New tasks = explicit markdown boundaries
  • Structural changes = inform Claude explicitly
  • Contradictory instructions = clarify priority
  • Long session (>2h) = consider /clear or new session
  • Erratic behavior = check with /context

Verify that Claude has loaded your configuration correctly.

Simple Method:

  1. Add at the top of CLAUDE.md:
# My name is [Your Name]
# Project: [Project Name]
# Stack: [Your tech stack]
  1. Ask Claude: “What is my name? What project am I working on?”

  2. If correct → Configuration loaded properly

Advanced: Multiple Checkpoints

# === CHECKPOINT 1 === Project: MyApp ===
[... 500 lines of instructions ...]
# === CHECKPOINT 2 === Stack: Next.js ===
[... 500 lines of instructions ...]
# === CHECKPOINT 3 === Owner: [Name] ===

Ask “What is checkpoint 2?” to verify Claude read that far.

Failure SymptomProbable CauseSolution
Doesn’t know your nameCLAUDE.md not loadedCheck file location
Inconsistent answersTypo in filenameMust be CLAUDE.md (not clause.md)
Partial knowledgeContext exhausted/clear or new session

When ending a session or switching contexts, create a handoff document to maintain continuity.

Purpose: Bridge the gap between sessions by documenting state, decisions, and next steps.

Template:

# Session Handoff - [Date] [Time]
## What Was Accomplished
- [Key task 1 completed]
- [Key task 2 completed]
- [Files modified: list]
## Current State
- [What's working]
- [What's partially done]
- [Known issues or blockers]
## Decisions Made
- [Architectural choice 1: why]
- [Technology selection: rationale]
- [Trade-offs accepted]
## Next Steps
1. [Immediate next task]
2. [Dependent task]
3. [Follow-up validation]
## Context for Next Session
- Branch: [branch-name]
- Key files: [list 3-5 most relevant]
- Dependencies: [external factors]

When to create handoff documents:

ScenarioWhy
End of work dayResume tomorrow without re-explaining context
Before context limitPreserve state before /clear
Switching focus areasDifferent task requires fresh context
Interruption expectedEmergency or meeting disrupts work
Complex debuggingDocument hypotheses and tests tried

Storage location: claudedocs/handoffs/handoff-YYYY-MM-DD.md

Pro tip: Ask Claude to generate the handoff:

You: "Create a session handoff document for what we accomplished today"

Claude will analyze git status, conversation history, and generate a structured handoff.

Handoff Triad Pattern: For teams or multi-session workflows, a three-command protocol adds explicit merge semantics on top of the basic handoff. Three commands work together:

CommandJob
/handoff:createGenerates the structured document from current session context
/handoff:resumeLoads a handoff document, confirms understanding, and waits for approval before starting
/handoff:updateUpdates an existing handoff with section-specific merge rules (see below)

The critical addition is per-section merge rules in update:

SectionMerge Rule
Task, ScopeKeep or refine
FilesMerge: combine original with new files touched
DiscoveriesAppend: add new findings, never remove prior ones
Work DoneAppend only: add new entries, never delete history, include commit hashes
StatusReplace: write current state
Next StepsReplace: write updated checklist

The append-only Work Done section creates an audit trail across sessions. Even if earlier work was revised, the revision appears as a new entry rather than an overwrite.

Fork-ready templates at examples/commands/handoff/ in this repo.

Pattern inspired by Packmind’s handoff command triad (Apache 2.0). See Credits.

Plan Mode is Claude Code’s “look but don’t touch” mode.

/plan

Or ask Claude directly:

You: Let's plan this feature before implementing
  • ✅ Reading files
  • ✅ Searching the codebase
  • ✅ Analyzing architecture
  • ✅ Proposing approaches
  • ✅ Writing to a plan file
  • ❌ Editing files
  • ❌ Running commands that modify state
  • ❌ Creating new files
  • ❌ Making commits
SituationUse Plan Mode?
Exploring unfamiliar codebase✅ Yes
Investigating a bug✅ Yes
Planning a new feature✅ Yes
Fixing a typo❌ No
Quick edit to known file❌ No

Recommended frequency: Boris Cherny (Head of Claude Code at Anthropic) starts approximately 80% of tasks in Plan Mode, letting Claude plan before writing a single line of code. Once the plan is approved, execution is almost always correct on the first try. Lenny’s Newsletter, February 19, 2026

Press Shift+Tab to toggle back to Normal Mode (Act Mode). You can also type a message and Claude will ask: “Ready to implement this plan?”

Note: Shift+Tab toggles between Plan Mode and Normal Mode during a session. Use Shift+Tab twice from Normal Mode to enter Plan Mode, once from Plan Mode to return.

Concept: Automatically trigger planning mode before any risky operation.

Configuration File (~/.claude/auto-plan-mode.txt):

Before executing ANY tool (Read, Write, Edit, Bash, Grep, Glob, WebSearch), you MUST:
1. FIRST: Use exit_plan_mode tool to present your plan
2. WAIT: For explicit user approval before proceeding
3. ONLY THEN: Execute the planned actions
Each new user request requires a fresh plan - previous approvals don't carry over.

Launch with Auto Plan Mode:

macOS/Linux:

Terminal window
# Direct
claude --append-system-prompt "Before executing ANY tool..."
# Via file (recommended)
claude --append-system-prompt "$(cat ~/.claude/auto-plan-mode.txt)"
# Alias in .zshrc/.bashrc
alias claude-safe='claude --append-system-prompt "$(cat ~/.claude/auto-plan-mode.txt)"'

Windows (PowerShell):

Terminal window
# Create the config file at %USERPROFILE%\.claude\auto-plan-mode.txt with the same content
# Direct
claude --append-system-prompt "Before executing ANY tool..."
# Via file (add to $PROFILE)
function claude-safe {
$planPrompt = Get-Content "$env:USERPROFILE\.claude\auto-plan-mode.txt" -Raw
claude --append-system-prompt $planPrompt $args
}

Resulting Workflow:

User: "Add an email field to the User model"
Claude (Auto Plan Mode active):
┌─────────────────────────────────────────────────────────────┐
│ 📋 PROPOSED PLAN │
│ │
│ 1. Read schema.prisma to understand current model │
│ 2. Add field email: String? @unique │
│ 3. Generate Prisma migration │
│ 4. Update TypeScript types │
│ 5. Add Zod validation in routers │
│ │
│ ⚠️ Impact: 3 files modified, 1 migration created │
│ │
│ Approve this plan? (y/n) │
└─────────────────────────────────────────────────────────────┘
User: "y"
Claude: [Executes the plan]

Expected benefit: reviewing a plan can catch misunderstandings before implementation. Token savings and defect reduction depend on the task and must be measured; no general percentage is established here.

Aliases resolve by provider and can be remapped by configuration. Verified against the official model configuration on September 24, 2026:

Provideropussonnet
Anthropic APIOpus 5.5Sonnet 5.5 (since v2.1.284)
Claude Platform on AWSOpus 5.5Sonnet 4.6
Amazon Bedrock / Google Cloud’s Agent PlatformOpus 5.5Sonnet 4.5
Microsoft FoundryOpus 4.6Sonnet 4.5
SelectionMeaning
defaultClear the override and use the account or organization default
haikuHaiku family alias; current direct-service model is Haiku 4.5
fableFable 5.1, except Fable 5 through the Claude apps gateway
bestSame as fable where available, otherwise opus
opus[1m], sonnet[1m]Request a 1M variant where the provider/model needs one
opusplanopus for planning, sonnet for execution
opusplan[1m]Request 1M in both phases where not native; /model accepts it from v2.1.265

Pin a version with its exact provider ID, such as claude-opus-5-5, or the appropriate ANTHROPIC_DEFAULT_*_MODEL variable. A provider alias resolving to an older model does not mean newer explicit IDs are unavailable.

/model <name> saves a default for new sessions. In the picker, press s for this session only. claude --model <name> and ANTHROPIC_MODEL apply to the launched session. Project and managed settings can reapply on the next launch; resumed sessions usually restore their recorded model. ANTHROPIC_DEFAULT_MODEL is a lower-priority default, not a replacement for these overrides.

Use the status line, /model, or the API response metadata to identify the active model. Model self-reports are not reliable identification. The current reliable knowledge cutoffs are June 2026 for Opus 5.5, Sonnet 5.5 and Fable 5.1, and February 2025 for Haiku 4.5. Model specifications.

Concept: Use Opus for planning (superior reasoning) and Sonnet for implementation (cost-efficient).

Why OpusPlan?

  • Cost optimization: Opus tokens cost more than Sonnet
  • Best of both worlds: Opus-quality planning + Sonnet-speed execution
  • Token savings: Planning is typically shorter than implementation

Activation:

/model opusplan

Or in ~/.claude/settings.json:

{
"model": "opusplan"
}

How It Works:

  1. In Plan Mode (/plan or Shift+Tab twice) → Uses Opus
  2. In Act Mode (normal execution) → Uses Sonnet
  3. Automatic switching based on mode

Recommended Workflow:

1. /model opusplan → Enable OpusPlan
2. Shift+Tab × 2 → Enter Plan Mode (Opus)
3. Describe your task → Get Opus-quality planning
4. Shift+Tab → Exit to Act Mode (Sonnet)
5. Execute the plan → Sonnet implements efficiently

Alternative Approach with Subagents:

You can also control model usage per agent:

.claude/agents/planner.md
---
name: planner
model: opus
tools: Read, Grep, Glob
---
# Strategic Planning Agent
.claude/agents/implementer.md
---
name: implementer
model: haiku
tools: Write, Edit, Bash
---
# Fast Implementation Agent

Pro Users Note: OpusPlan is particularly valuable for Pro subscribers with limited Opus tokens. It lets you use Opus reasoning for critical planning while preserving tokens for more sessions.

Budget Variant: SonnetPlan (Community Hack)

opusplan is hardcoded to Opus+Sonnet. There’s no native sonnetplan alias. But you can remap what the opus and sonnet aliases resolve to via environment variables, effectively creating a Sonnet→Haiku hybrid:

Terminal window
# Add to ~/.zshrc
sonnetplan() {
ANTHROPIC_DEFAULT_OPUS_MODEL=claude-sonnet-5 \
ANTHROPIC_DEFAULT_SONNET_MODEL=claude-haiku-4-5-20251001 \
claude "$@"
}

With sonnetplan, /model opusplan routes:

  • Plan Mode → Sonnet 5 (via remapped opus alias)
  • Act Mode → Haiku 4.5 (via remapped sonnet alias)

Caveat: The model’s self-report (what model are you?) is unreliable: models don’t always know their own identity. Trust the status bar (Model: Sonnet 5 in plan mode) or verify via billing dashboard. GitHub issue #9749 tracks native support.

Pinning Opus 4.6 (Community Hack)

Opus 4.7 ships with a new tokenizer that maps the same input to roughly 1.0-1.35x more tokens depending on content type, and at higher effort levels it produces more output tokens (more reasoning steps). For workflows where that extra spend doesn’t translate into better results, pinning to Opus 4.6 keeps an older model and tokenizer; measure the cost and quality tradeoff on your task.

Option A: Opus 4.6 everywhere (simplest)

~/.claude/settings.json
{
"model": "claude-opus-4-6"
}

All sessions use Opus 4.6. No hybrid. Add [1M] if you need the 1M context window: "claude-opus-4-6[1M]".

Option B: Keep OpusPlan, intentionally pin the older Opus side

~/.claude/settings.json
{
"model": "opusplan",
"env": {
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-6"
}
}

opusplan still switches between Plan and Act modes, but Plan Mode now routes to Opus 4.6 instead of the provider’s current Opus alias. Sonnet stays unchanged in Act Mode.

Shell variant (non-persistent, useful for testing):

Terminal window
ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-6 claude

Option C: Per-session switch (no config change)

/model claude-opus-4-6

Resets on the next session. Useful before committing to a config change.

Verification: check the status bar in Plan Mode. Verify the resolved Opus 4.6 model ID. The billing dashboard confirms which model was charged.

Trade-offs: Opus 4.6 does not support xhigh, but does support max. Pinning keeps an older model, tokenizer, and knowledge cutoff. Compare accepted outcomes and total tokens with the current default before treating the older model as a cost optimization.

Concept: Run multiple rounds of planning and deep thinking before executing. Like warming up an engine before driving.

Standard workflow: think → plan → execute. Rev the Engine: think → plan → think harder → refine plan → think hardest → finalize → execute.

When to use:

  • Critical architectural decisions (irreversible, high-impact)
  • Complex migrations affecting 10+ files
  • Unfamiliar domain where first instincts are often wrong

Pattern:

## Round 1: Initial analysis
User: /plan
User: Analyze the current auth system. What are the key components,
dependencies, and potential risks of migrating to OAuth2?
Claude: [Initial analysis]
## Round 2: Deep challenge
User: Now use extended thinking. Challenge your own analysis:
- What assumptions did you make?
- What failure modes did you miss?
- What would a senior security engineer flag?
Claude: [Deeper analysis with self-correction]
## Round 3: Final plan
User: Based on both rounds, write the definitive migration plan.
Include rollback strategy and risk mitigation for each step.
Claude: [Refined plan incorporating both rounds]
## Execute
[approve the plan, or Shift+Tab to leave plan mode]
User: Implement the plan from round 3.

Purpose: a second round challenges assumptions and a third consolidates the plan. Repetition does not guarantee new findings or correctness; keep independent tests and explicit acceptance criteria.

📊 Empirical backing: Anthropic AI Fluency Index (Feb 2026)

In 9,830 Claude.ai conversations sampled during one week in January 2026, conversations with iteration/refinement were 5.6 times more likely to show users questioning reasoning and four times more likely to show users identifying missing context. These are associations between observed behaviors, not measured bug-detection rates.

The report explicitly does not establish causality. It does not test the three-round pattern above or prove that another review round improves a plan.

Source: Swanson et al., “The AI Fluency Index”, Anthropic (2026-02-23), anthropic.com/research/AI-fluency-index

Cloud-based parallel multi-agent code review. Multiple review agents read through your changes simultaneously and surface bugs and design issues that careful reviewers would catch.

Activation:

Terminal window
/ultrareview # Review current branch (diff from base)
/ultrareview <PR#> # Review a specific GitHub PR

Ultrareview operates on diffs, not the full codebase: it reviews what changed on the current branch, or the changes in a given PR. The cloud session dispatches parallel agents to analyse the diff; results arrive in the browser and can optionally be teleported back to the terminal.

Launch offer: Pro and Max subscribers receive three free ultrareviews to try the feature.

Requirements:

RequirementDetail
Claude Code versionv2.1.114+
AccountPro or Max
ProvidersAnthropic API only

Concept: Layer multiple Claude Code mechanisms for maximum intelligence on critical decisions.

Layer 1: Plan Mode → Exploration without source-file edits
Layer 2: Extended Thinking → Deep reasoning with thinking tokens
Layer 3: Rev the Engine → Multi-round refinement
Layer 4: Split-Role Agents → Multi-perspective analysis
Layer 5: Permutation → Systematic variation testing

You don’t need all layers for every task. Match the stack depth to the decision’s impact:

Decision ImpactStack DepthExample
Low (fix typo)0 layersJust do it
Medium (add feature)1-2 layersPlan Mode + Extended Thinking
High (architecture)3-4 layersRev the Engine + Split-Role
Critical (migration)4-5 layersFull stack

Anti-pattern: Stacking on trivial decisions. If the change is reversible and low-risk, just execute. Over-planning is as wasteful as under-planning.

Cross-references:

Rewind is Claude Code’s undo mechanism.

Access via Esc + Esc (double-tap Escape) or the /rewind command. This opens a scrollable checkpoint list.

Rewind provides four distinct actions from the checkpoint list:

ActionEffect
Restore code and conversationRevert both file changes and conversation to selected point
Restore conversationKeep current code, rewind conversation only
Restore codeRevert file changes, keep conversation
Summarize from hereCompress conversation from selected point forward (frees space without reverting)

Key distinction: Restore = undo (reverts state). Summarize = compress (frees space without reverting). Checkpoints persist across sessions (30-day cleanup).

  • Only works on Claude’s changes (not manual edits)
  • Works within the current session
  • Git commits are NOT automatically reverted

Before a risky operation:

You: Let's commit what we have before trying this experimental approach

This creates a git checkpoint you can always return to.

When things go wrong, you have multiple recovery options. Use the lightest-weight approach that solves your problem:

┌─────────────────────────────────────────────────────────┐
│ RECOVERY LADDER │
├─────────────────────────────────────────────────────────┤
│ │
│ Level 3: Git Restore (nuclear option) │
│ ───────────────────────────────────── │
│ • git checkout -- <file> (discard uncommitted) │
│ • git stash (save for later) │
│ • git reset --hard HEAD~1 (undo last commit) │
│ • Works for: Manual edits, multiple sessions │
│ │
│ Level 2: /rewind (session undo) │
│ ───────────────────────────── │
│ • Reverts Claude's recent file changes │
│ • Works within current session only │
│ • Doesn't touch git commits │
│ • Works for: Bad code generation, wrong direction │
│ │
│ Level 1: Reject Change (inline) │
│ ──────────────────────────── │
│ • Press 'n' when reviewing diff │
│ • Change never applied │
│ • Works for: Catching issues before they happen │
│ │
└─────────────────────────────────────────────────────────┘

When to use each level:

ScenarioRecovery LevelCommand
Claude proposed bad codeLevel 1Press n
Claude made changes, want to undoLevel 2/rewind
Changes committed, need full rollbackLevel 3git reset
Experimental branch went wrongLevel 3git checkout main
Context corrupted, strange behaviorFresh start/clear + restate goal

Pro tip: The /rewind command shows a list of changes to undo. You can selectively revert specific files rather than all changes.

For systematic experimentation, use the checkpoint pattern to create safe restore points:

┌─────────────────────────────────────────────────────────┐
│ CHECKPOINT WORKFLOW │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. Create checkpoint │
│ ────────────────── │
│ git stash push -u -m "checkpoint-before-refactor" │
│ (saves all changes including untracked files) │
│ │
│ 2. Experiment freely │
│ ────────────────── │
│ Try risky refactoring, architectural changes, etc. │
│ If it works → commit normally │
│ If it fails → restore checkpoint │
│ │
│ 3. Restore checkpoint │
│ ────────────────── │
│ git stash list # find your checkpoint │
│ git stash apply stash@{0} # restore without delete │
│ # or │
│ git stash pop stash@{0} # restore and delete │
│ │
└─────────────────────────────────────────────────────────┘

Automated checkpoint: Create a Stop hook to auto-checkpoint on session end:

.claude/hooks/auto-checkpoint.sh
# See: examples/hooks/bash/auto-checkpoint.sh
# Automatically creates git stash on session end
# Naming: claude-checkpoint-{branch}-{timestamp}
# Logs to: ~/.claude/logs/checkpoints.log

Common workflows:

ScenarioWorkflow
Risky refactorCheckpoint → Try → Commit or restore
A/B testing approachesCheckpoint → Try A → Restore → Try B → Compare
Incremental migrationCheckpoint → Migrate piece → Test → Repeat
Prototype explorationCheckpoint → Experiment → Discard cleanly

Benefits over branching:

  • Faster than creating feature branches
  • Preserves uncommitted changes
  • Lightweight for quick experiments
  • Works across multiple files

Choosing the right model for each task is the fastest ROI improvement most Claude Code users can make. One decision per task, no overthinking.

Quick jump: Decision Table · Effort Levels · Model per Agent · When Thinking Helps

Cross-references: OpusPlan Mode · Rev the Engine · Cost Awareness


TaskCandidate modelEffort starting point
Rename, format, bounded extractionHaiku 4.5Not supported
Feature work, tests, routine debuggingSonnet 5.5 or Opus 5.5Model default
Architecture or difficult debuggingOpus 5.5Increase from medium if evaluation warrants it
Long or ambiguous work that misses the quality barEvaluate Fable 5.1Start at high
Multi-agent workflowAssign by role and measured task resultsPer supported model

No fixed cost per task follows from a model name. Measure input, output, cache tokens, retries, and review effort against the same acceptance criteria. See the pricing table.

Fable 5.1 (claude-fable-5-1, Claude Code v2.1.257+) is an explicit option when evaluations on Opus 5.5 still fall short. /model fable normally selects it; Claude apps gateway sessions map that alias to Fable 5, so use a full supported ID to pin the newer model. Availability and usage-credit billing depend on the account. A stronger model does not remove the need to verify security or production decisions. Fable access and billing.

Effort controls adaptive reasoning and can change tool use, response length, latency, and cost. It is not an accuracy guarantee.

ModelsSupported Claude Code effort levelsDefault
Opus 5.5low, medium, high, xhigh, maxmedium
Sonnet 5, Opus 5 / 4.8, Fable 5 / 5.1low, medium, high, xhigh, maxhigh
Opus 4.7low, medium, high, xhigh, maxxhigh
Opus 4.6, Sonnet 4.6low, medium, high, maxhigh
Haiku 4.5No effort parameterNot applicable

/effort or the /model picker saves supported low through xhigh choices per model when confirmed with Enter; s makes the choice session-only. /effort max is session-only. Persistent modelSettings and effortLevel do not accept max. CLAUDE_CODE_EFFORT_LEVEL can override the session, and organization policy can cap available levels.

/effort ultracode enables dynamic workflow orchestration with xhigh reasoning. It is a Claude Code setting, not a sixth model effort level. The prompt keyword ultrathink adds an instruction to reason more deeply without changing the effort value sent to the API.

Opus 5.5 starts at medium and does not inherit the old top-level effortLevel from user settings. A per-model choice, an explicit runtime override, or project/local/managed effort settings can still change it. Official effort rules.

Skills can declare their own effort level in frontmatter. The skill’s value overrides the session setting for the duration of that skill’s execution, then reverts. This eliminates the need to manually toggle effort between mechanical and analytical tasks.

# Mechanical skill — always fast, never wastes reasoning budget
---
name: release
description: Bump version, update CHANGELOG, commit, push
effort: low
---
# Analytical skill — always deep, regardless of session setting
---
name: architecture-review
description: Full architectural analysis with trade-off evaluation
effort: high
---

Decision table for common skill types:

Skill typeRecommended effortReasoning
Commit, push, synclowSequential steps, no design decisions
Changelog, release noteslowReads git + formats, mécanique
Scaffolding, boilerplatelowTemplate instantiation
Code review (single PR)mediumPattern recognition, bounded scope
Issue triage, backlogmediumCategorization + some analysis
Security audithighThreat modeling, adversarial thinking
Architecture reviewhighDesign decisions, cross-component reasoning
Multi-agent orchestrationhighCoordination + planning

Cost model: low effort means fewer tool calls, no preamble, direct output. high effort means more tool calls with explanations, detailed summaries, deeper exploration. Match effort to where analysis adds value, not to “effort = quality” uniformly.


Assign models to agents based on role, not importance:

Planner (examples/agents/planner.md): Strategy, read-only exploration

---
name: planner
description: Strategic planning agent — read-only. Use before implementation.
model: opus
tools: Read, Grep, Glob
---

Implementer (examples/agents/implementer.md): Mechanical execution, bounded scope

---
name: implementer
description: Mechanical execution agent. Scope must be defined explicitly in the task.
model: haiku
tools: Write, Edit, Bash, Read, Grep, Glob
---

Note: Haiku is for mechanical tasks only. If the implementation requires design decisions or complex business logic, use Sonnet, and state this in the task prompt.

Architecture Reviewer (examples/agents/architecture-reviewer.md): Critical design review

---
name: architecture-reviewer
description: Architecture and design review — read-only. Never modifies code.
model: opus
tools: Read, Grep, Glob
---

Pro tip: Add a model reminder to your CLAUDE.md:

# Model reminder
Project preference: Sonnet for routine work, Haiku for bounded tasks, Opus for harder reasoning. This is a chosen policy, not the account default.

ScenarioThinkingReason
Rename 50 filesOFFZero reasoning, pure mechanics
Bug spanning 3+ servicesON (high)Multi-layer hypothesis testing
Boilerplate / test generationOFFRepetitive pattern, no decisions
Architecture migrationON (max)Irreversible decisions
Direct factual questionsOFF (low)Immediate answer sufficient
Security code reviewON (high)Adversarial reasoning needed

Thinking toggle: Option+T on macOS or Alt+T elsewhere, where supported. Opus 5.5 and Fable always use thinking; lower their effort for bounded work instead.


Understanding how Claude Code “thinks” makes you more effective.

┌─────────────────────────────────────────────────────────┐
│ YOUR PROJECT │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│ │ Files │ │ Git │ │ Config │ │
│ │ (.ts,.py) │ │ History │ │ Files │ │
│ └─────────────┘ └─────────────┘ └───────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Claude's Understanding │ │
│ │ - File structure & relationships │ │
│ │ - Code patterns & conventions │ │
│ │ - Recent changes (from git) │ │
│ │ - Project rules (from CLAUDE.md) │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
  1. File Structure: Claude can navigate and search your files
  2. Code Content: Claude can read and understand code
  3. Git State: Claude sees branches, commits, changes
  4. Project Rules: Claude reads CLAUDE.md for conventions
  1. Runtime State: Claude can’t see running processes
  2. External Services: Claude can’t access your databases directly
  3. Your Intent: Claude needs clear instructions
  4. Hidden Files: Claude respects .gitignore by default

⚠️ Pattern Amplification: Claude mirrors the patterns it finds. In well-structured codebases, it produces consistent, idiomatic code. In messy codebases without clear abstractions, it perpetuates the mess. If your code lacks good patterns, provide them explicitly in CLAUDE.md or use semantic anchors (Section 2.9).

Think of yourself as a CPU scheduler. Claude Code instances are worker threads. You don’t write the code, you orchestrate the work.

┌─────────────────────────────────────────┐
│ YOU (Main Thread) │
│ ┌────────────────────────────────────┐ │
│ │ Responsibilities: │ │
│ │ • Define tasks and priorities │ │
│ │ • Allocate context budgets │ │
│ │ • Review outputs │ │
│ │ • Make architectural decisions │ │
│ │ • Handle exceptions/escalations │ │
│ └────────────────────────────────────┘ │
│ │ │ │ │
│ ┌────▼───┐ ┌────▼───┐ ┌────▼───┐ │
│ │Worker 1│ │Worker 2│ │Worker 3│ │
│ │(Claude)│ │(Claude)│ │(Claude)│ │
│ │Feature │ │Tests │ │Review │ │
│ └────────┘ └────────┘ └────────┘ │
└─────────────────────────────────────────┘

Implications:

  • Don’t write code when Claude can. Your time is for decisions, not keystrokes.
  • Don’t micromanage. Give clear instructions, then review results.
  • Context-switch deliberately. Like a scheduler, batch similar tasks.
  • Escalate to yourself. When Claude is stuck, step in, then hand back.

This mental model scales: one developer can orchestrate 2-5 Claude instances on independent tasks (see §9.17 Scaling Patterns).

The most common mistake is treating Claude Code like a chatbot: typing ad-hoc requests and hoping for good output. What separates casual usage from production workflows is a shift in thinking:

Chatbot mode: You write good prompts. Context system: You build structured context that makes every prompt better.

“Stop treating it like a chatbot. Give it structured context. CLAUDE.md, hooks, skills, project memory. Changes everything.” Robin Lorenz, AI Engineer (comment)

This guide groups four mechanisms into a conceptual learning model, not an exhaustive runtime architecture:

LayerWhat It DoesSectionWhen to Set Up
CLAUDE.mdPersistent rules, conventions, project knowledge§3.1Week 1
SkillsReusable knowledge modules for consistent workflows§5Week 2
HooksAutomated guardrails (lint, security, formatting)§7Week 2-3
Project memoryCross-session decisions and architectural context§3.1Ongoing

These are not independent features. They are layers of the same system:

  • CLAUDE.md teaches Claude what your project needs (conventions, stack, patterns)
  • Skills teach Claude how to perform specific workflows (review, deploy, test)
  • Hooks enforce guardrails automatically (block secrets, auto-format, run linting)
  • Memory preserves decisions across sessions (architectural choices, resolved tradeoffs)

Before (chatbot mode):

“Use pnpm, not npm. And remember our naming convention is…” (Every session. Every time. Copy-pasting context.)

After (context system):

Applicable CLAUDE.md files supply conventions. Skills provide reusable workflows. Configured hooks run checks for supported events. Memory records decisions for later use.

These mechanisms improve available context; they do not guarantee instruction adherence, complete recall or a successful quality check.

See also: §9.10 Continuous Improvement Mindset for evolving this system over time. Ready to choose the right mechanism? Memory Loading Comparison maps all seven mechanisms with a decision tree.

Good prompt:

The login function in src/auth/login.ts isn't validating email addresses properly.
Plus signs should be allowed but they're being rejected.

Weak prompt:

Login is broken

The more context you provide, the better Claude can help.

XML-structured prompts provide semantic organization for complex requests, helping Claude distinguish between different aspects of your task for clearer understanding and better results.

XML tags act as labeled containers that explicitly separate instruction types, context, examples, constraints, and expected output format.

Basic syntax:

<instruction>
Your main task description here
</instruction>
<context>
Background information, project details, or relevant state
</context>
<code_example>
Reference code or examples to follow
</code_example>
<constraints>
- Limitation 1
- Limitation 2
- Requirement 3
</constraints>
<output>
Expected format or structure of the response
</output>
BenefitDescription
Separation of concernsDifferent aspects of the task are clearly delineated
Reduced ambiguityClaude knows which information serves what purpose
Better context handlingHelps Claude prioritize main instructions over background info
Consistent formattingEasier to template complex requests
Multi-faceted requestsComplex tasks with multiple requirements stay organized

Core Instruction Tags:

<instruction>Main task</instruction> <!-- Primary directive -->
<task>Specific subtask</task> <!-- Individual action item -->
<question>What should I do about X?</question> <!-- Explicit inquiry -->
<goal>Achieve state Y</goal> <!-- Desired outcome -->

Context and Information Tags:

<context>Project uses Next.js 14</context> <!-- Background info -->
<problem>Users report slow page loads</problem> <!-- Issue description -->
<background>Migration from Pages Router</background> <!-- Historical context -->
<state>Currently on feature-branch</state> <!-- Current situation -->

Code and Example Tags:

<code_example>
// Existing pattern to follow
const user = await getUser(id);
</code_example>
<current_code>
// Code that needs modification
</current_code>
<expected_output>
// What the result should look like
</expected_output>

Constraint and Rule Tags:

<constraints>
- Must maintain backward compatibility
- No breaking changes to public API
- Maximum 100ms response time
</constraints>
<requirements>
- TypeScript strict mode
- 100% test coverage
- Accessible (WCAG 2.1 AA)
</requirements>
<avoid>
- Don't use any for types
- Don't modify the database schema
</avoid>

Example 1: Code Review with Context

<instruction>
Review this authentication middleware for security vulnerabilities
</instruction>
<context>
This middleware is used in a financial application handling sensitive user data.
We follow OWASP Top 10 guidelines and need PCI DSS compliance.
</context>
<code_example>
async function authenticate(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token' });
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
}
</code_example>
<constraints>
- Point out any security risks
- Suggest PCI DSS compliant alternatives
- Consider timing attacks and token leakage
</constraints>
<output>
Provide:
1. List of security issues found
2. Severity rating for each (Critical/High/Medium/Low)
3. Specific code fixes with examples
4. Additional security hardening recommendations
</output>

Example 2: Feature Implementation with Examples

<instruction>
Add a rate limiting system to our API endpoints
</instruction>
<context>
Current stack: Express.js + Redis
No rate limiting currently exists
Experiencing API abuse from specific IPs
</context>
<requirements>
- 100 requests per minute per IP for authenticated users
- 20 requests per minute per IP for unauthenticated
- Custom limits for premium users (stored in database)
- Return 429 status with Retry-After header
</requirements>
<code_example>
// Existing middleware pattern we use
app.use(authenticate);
app.use(authorize(['admin', 'user']));
</code_example>
<constraints>
- Must not impact existing API performance
- Redis connection should be reused
- Handle Redis connection failures gracefully
</constraints>
<output>
Provide:
1. Rate limiter middleware implementation
2. Redis configuration
3. Unit tests
4. Documentation for the team
</output>

Example 3: Bug Investigation with State

<task>
Investigate why user sessions are expiring prematurely
</task>
<problem>
Users report being logged out after 5-10 minutes of activity,
but session timeout is configured for 24 hours.
</problem>
<context>
- Next.js 14 App Router with next-auth
- PostgreSQL session store
- Load balanced across 3 servers
- Issue started after deploying v2.3.0 last week
</context>
<state>
Git diff between v2.2.0 (working) and v2.3.0 (broken) shows changes to:
- middleware.ts (session refresh logic)
- auth.config.ts (session strategy)
- database.ts (connection pooling)
</state>
<constraints>
- Don't suggest reverting the deploy
- Production issue, needs quick resolution
- Must maintain session security
</constraints>
<output>
Provide:
1. Root cause hypothesis
2. Files to investigate (in priority order)
3. Debugging commands to run
4. Potential fixes with trade-offs
</output>

Nested Tags for Complex Hierarchy:

<task>
Refactor authentication system
<subtask priority="high">
Update user model
<constraints>
- Preserve existing user IDs
- Add migration for email verification
</constraints>
</subtask>
<subtask priority="medium">
Implement OAuth providers
<requirements>
- Google and GitHub OAuth
- Reuse existing session logic
</requirements>
</subtask>
</task>

Multiple Examples with Labels:

<code_example label="current_implementation">
// Old approach with callback hell
getUser(id, (user) => {
getOrders(user.id, (orders) => {
res.json({ user, orders });
});
});
</code_example>
<code_example label="desired_pattern">
// New async/await pattern
const user = await getUser(id);
const orders = await getOrders(user.id);
res.json({ user, orders });
</code_example>

Conditional Instructions:

<instruction>
Optimize database query performance
</instruction>
<context>
Query currently takes 2.5 seconds for 10,000 records
</context>
<constraints>
<if condition="PostgreSQL">
- Use EXPLAIN ANALYZE
- Consider materialized views
</if>
<if condition="MySQL">
- Use EXPLAIN with query plan analysis
- Consider query cache
</if>
</constraints>
ScenarioRecommended?Why
Simple one-liner requests❌ NoOverhead outweighs benefit
Multi-step feature implementation✅ YesSeparates goals, constraints, examples
Bug investigation with context✅ YesDistinguishes symptoms from environment
Code review with specific criteria✅ YesClear separation of code, context, requirements
Architecture planning✅ YesOrganizes goals, constraints, trade-offs
Quick typo fix❌ NoUnnecessary complexity

Do’s:

  • ✅ Use descriptive tag names that clarify purpose
  • ✅ Keep tags consistent across similar requests
  • ✅ Combine with CLAUDE.md for project-specific tag conventions
  • ✅ Nest tags logically when representing hierarchy
  • ✅ Use tags to separate “what” from “why” from “how”

Don’ts:

  • ❌ Over-structure simple requests (adds noise)
  • ❌ Mix tag purposes (e.g., constraints inside code examples)
  • ❌ Use generic tags (<tag>, <content>) without clear meaning
  • ❌ Nest too deeply (>3 levels becomes hard to read)

You can standardize XML tag usage in your project’s CLAUDE.md:

# XML Prompt Conventions
When making complex requests, use this structure:
<instruction>Main task</instruction>
<context>
Project context and state
</context>
<code_example>
Reference implementations
</code_example>
<constraints>
Technical and business requirements
</constraints>
<output>
Expected deliverables
</output>
## Project-Specific Tags
- `<api_design>` - API endpoint design specifications
- `<accessibility>` - WCAG requirements and ARIA considerations
- `<performance>` - Performance budgets and optimization goals

XML + Plan Mode:

<instruction>Plan the migration from REST to GraphQL</instruction>
<context>
Currently 47 REST endpoints serving mobile and web clients
</context>
<constraints>
- Must maintain REST endpoints during transition (6-month overlap)
- Mobile app can't be force-updated immediately
</constraints>
<output>
Multi-phase migration plan with rollback strategy
</output>

Then use /plan to explore read-only before implementation.

XML + Cost Awareness:

For large requests, structure with XML to help Claude understand scope and estimate token usage:

<instruction>Analyze all TypeScript files for unused imports</instruction>
<scope>
src/ directory (~200 files)
</scope>
<output_format>
Summary report only (don't list every file)
</output_format>

This helps Claude optimize the analysis approach and reduce token consumption.

Create reusable templates in claudedocs/templates/:

claudedocs/templates/code-review.xml:

<instruction>
Review the following code for quality and best practices
</instruction>
<context>
[Describe the component's purpose and architecture context]
</context>
<code_example>
[Paste code here]
</code_example>
<focus_areas>
- Security vulnerabilities
- Performance bottlenecks
- Maintainability issues
- Test coverage gaps
</focus_areas>
<output>
1. Issues found (categorized by severity)
2. Specific recommendations with code examples
3. Priority order for fixes
</output>

Usage:

Terminal window
cat claudedocs/templates/code-review.xml | \
sed 's/\[Paste code here\]/'"$(cat src/auth.ts)"'/' | \
claude -p "Process this review request"

Token overhead: XML tags consume tokens. For simple requests, natural language is more efficient.

Not required: Claude understands natural language perfectly well. Use XML when structure genuinely helps.

Consistency matters: If you use XML tags, be consistent. Mixing styles within a session can confuse context.

Learning curve: Team members need to understand the tag system. Document your conventions in CLAUDE.md.

💡 Pro tip: Start with natural language prompts. Introduce XML structure when:

  • Requests have 3+ distinct aspects (instruction + context + constraints)
  • Ambiguity causes Claude to misunderstand your intent
  • Creating reusable prompt templates
  • Working with junior developers who need structured communication patterns

Source: DeepTo Claude Code Guide - XML-Structured Prompts

The Claude Code team internally treats prompts as challenges to a peer, not instructions to an assistant. This subtle shift produces higher-quality outputs because it forces Claude to prove its reasoning rather than simply comply.

Three challenge patterns from the team:

1. The Gatekeeper: Force Claude to defend its work before shipping:

"Grill me on these changes and don't make a PR until I pass your test"

Claude reviews your diff, asks pointed questions about edge cases, and only proceeds when satisfied. This catches issues that passive review misses.

2. The Proof Demand: Require evidence, not assertions:

"Prove to me this works — show me the diff in behavior between main and this branch"

Claude runs both branches, compares outputs, and presents concrete evidence. Eliminates the “trust me, it works” failure mode.

3. The Reset: After a mediocre first attempt, invoke full-context rewrite:

"Knowing everything you know now, scrap this and implement the elegant solution"

This forces a substantive second attempt with accumulated context rather than incremental patches on a weak foundation. The key insight: Claude’s second attempt with full context consistently outperforms iterative fixes.

Why this works: Provocation triggers deeper reasoning paths than polite requests. When Claude must convince rather than comply, it activates more thorough analysis and catches its own shortcuts.

Source: 10 Tips from Inside the Claude Code Team (Boris Cherny thread, Feb 2026)

A semantic anchor is the name of an established method, pattern, or framework used as shorthand in a prompt. It gives Claude a more specific reference than a request such as “write good tests.” Recognition and correct application still depend on the model, the task, and the surrounding instructions.

“Write good tests” leaves the testing approach open. “Use TDD, London School; start with an outside-in behavior test” names a particular approach and states the part you need. The added instruction matters: a model may recognize the term without applying it well to your code.

Vague requestAnchor with task-specific directionWhat to check
”Handle errors""Use Railway Oriented Programming with Result for expected failures”Expected failures remain explicit; unexpected failures stay observable
”Improve the design""Apply Deep Modules: hide implementation detail behind a small interface”Callers depend on fewer details without losing needed behavior
”Modernize this feature""Use Strangler Fig: replace one behavior behind a boundary”Old and new paths coexist safely during migration
”Design the API""Target Richardson Maturity Model Level 2”Resources, HTTP methods, and status codes match the API contract

An anchor should fit the problem. State the relevant behavior, boundaries, and acceptance checks alongside it. For example, CQRS and Event Sourcing are separate choices; naming either one does not justify adopting both.

The Semantic Anchors project’s evaluation plan separates recognition from application and compares anchor prompts with ordinary descriptions. It describes an evaluation method, not a measured quality gain for the examples in this guide. If a model applies a term incorrectly, expand it into explicit instructions and verify the result.

# Payment integration
- Architecture: Hexagonal Architecture (Ports & Adapters). Keep provider code outside the domain.
- Error handling: Use a Result type for expected payment failures; keep unexpected failures observable.
- Testing: Use TDD, London School at the service boundary; add an integration test for the provider adapter.
- Documentation: Record the provider-boundary decision in an ADR.

These are project choices, not defaults to copy into every repository. An XML-structured prompt (Section 2.8) can group the same instructions, but the tags alone do not make the anchor more reliable.

For more terms, sources, and usage limits, see the curated semantic anchors catalog. The LLM-Coding community catalog describes its quality criteria and additional candidates.

Two prompt-level techniques that close the gap between well-structured prompts and reliably accurate outputs: few-shot examples for calibrating format and style, and validation retry loops for catching and correcting extraction failures.


Few-shot examples show the model what correct output looks like before it processes the actual input. They are most effective for establishing output format, tone calibration, and input-specific processing style. They cannot enforce business rules or guarantee compliance; use schema validation for that.

Optimal count: 2-4 examples. Below 2, the pattern is too weak to anchor behavior. Above 4, the examples consume context budget without proportional improvement, and the model may pattern-match too literally on superficial features.

Message-pair format for tool use:

When the task involves tool calls, examples must include the full exchange, not just user inputs and final text outputs:

messages = [
# Example 1
{"role": "user", "content": "Invoice: Acme Corp, 15 Jan 2025, $4,200.00"},
{"role": "assistant", "content": [
{
"type": "tool_use",
"id": "toolu_01",
"name": "extract_invoice",
"input": {
"vendor": "Acme Corp",
"date": "2025-01-15",
"amount": 4200.00
}
}
]},
{"role": "user", "content": [{"type": "tool_result", "tool_use_id": "toolu_01", "content": "OK"}]},
# Example 2 (null handling)
{"role": "user", "content": "Invoice: no vendor listed, 22 Feb 2025, €892"},
{"role": "assistant", "content": [
{
"type": "tool_use",
"id": "toolu_02",
"name": "extract_invoice",
"input": {
"vendor": null,
"date": "2025-02-22",
"amount": 892.00
}
}
]},
{"role": "user", "content": [{"type": "tool_result", "tool_use_id": "toolu_02", "content": "OK"}]},
# Actual task
{"role": "user", "content": f"Invoice: {actual_invoice_text}"}
]

The second example above demonstrates null handling explicitly. Without it, the model may invent a vendor name rather than returning null for an ambiguous field.

Calibrating false positive rates:

In CI-style review tasks (security scanning, code quality checks, compliance checks), false positives destroy trust faster than false negatives. A few-shot example set that includes a near-miss that should NOT trigger an alert teaches the boundary explicitly:

# In the system prompt or early in the conversation:
CALIBRATION_EXAMPLES = """
Examples of what triggers a HIGH severity flag vs what does not:
Example 1 (HIGH, triggers):
Input: SELECT * FROM users WHERE id = ' + user_input + '
Reason: Direct string concatenation in SQL, classic injection vector.
Example 2 (NOT flagged, near-miss):
Input: query = f"SELECT * FROM users WHERE id = {user_id}"
Reason: f-string with a typed integer variable. No injection risk if user_id is
validated upstream. Untyped string concatenation = flag; typed variable
interpolation = safe.
Example 3 (HIGH, triggers):
Input: os.system(request.GET['cmd'])
Reason: Direct shell execution from unsanitized request parameter.
"""

Near-miss examples reduce false positive rates by teaching the model where the actual boundary sits, not just what a clear violation looks like.

Limits of few-shot:

Few-shot examples teach style and format. They cannot enforce schema constraints (use strict: true for that), guarantee business rule compliance (use a programmatic validator), or replace explicit instructions. If the rule needs to hold without exception, state it as a rule, not just as an example.


The validation retry loop catches structured extraction failures programmatically and feeds specific error feedback back to the model for regeneration, rather than silently discarding bad output or failing the whole task.

Three-attempt budget:

from dataclasses import dataclass
@dataclass
class ExtractionResult:
success: bool
data: dict | None
error: str | None
attempts: int
def extract_with_retry(
client,
document: str,
schema_validator,
max_attempts: int = 3
) -> ExtractionResult:
messages = [{"role": "user", "content": f"Extract fields from:\n\n{document}"}]
for attempt in range(1, max_attempts + 1):
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
tools=[EXTRACTION_TOOL],
tool_choice={"type": "tool", "name": "extract_fields"},
messages=messages
)
raw_output = response.content[0].input
errors = schema_validator.validate(raw_output)
if not errors:
return ExtractionResult(
success=True, data=raw_output, error=None, attempts=attempt
)
if attempt == max_attempts:
break
# Feed specific errors back, not a generic "try again"
error_feedback = format_errors(errors, raw_output)
messages.extend([
{"role": "assistant", "content": response.content},
{
"role": "user",
"content": (
f"The extraction has {len(errors)} validation error(s):\n\n"
f"{error_feedback}\n\n"
f"Please correct these specific issues and re-extract."
)
}
])
return ExtractionResult(
success=False, data=None,
error=f"Failed after {max_attempts} attempts: {errors}",
attempts=max_attempts
)
def format_errors(errors, raw_output):
lines = []
for err in errors:
lines.append(f"- Field `{err.field}`: {err.message}")
if err.field in raw_output:
lines.append(f" Got: {raw_output[err.field]!r}")
return "\n".join(lines)

The feedback triple matters. Effective retry feedback includes (1) the original document excerpt where the issue occurred, (2) the failed JSON the model produced, and (3) a specific error list per field. Vague feedback (“please try again, there were errors”) degrades into random variation. Specific feedback (“field date expected ISO 8601, got ‘15th January’”) almost always resolves on the second attempt.

When source data is absent:

If the document genuinely does not contain the required field, a retry loop will not help. The model will keep hallucinating or oscillating between null and invented values. Exit condition: if the same field fails twice with different invented values, mark it as absent_from_source and move on. Do not burn the full 3-attempt budget on a field that isn’t there.

def is_hallucination_cycle(error_history: list[dict], field: str) -> bool:
values = [h.get(field) for h in error_history if h.get(field) is not None]
# Two different non-null values for the same field across attempts = hallucination
return len(set(str(v) for v in values)) > 1

Graceful degradation with human review routing:

When the retry budget is exhausted, route to human review rather than silently dropping the document:

result = extract_with_retry(client, document, validator)
if not result.success:
human_review_queue.append({
"document_id": doc_id,
"document": document,
"last_attempt": result.error,
"attempts": result.attempts,
"requires_human": True
})
metrics.increment("extraction.failed", tags={"reason": "max_retries"})

Asking the same model instance that generated an output to review its own output produces results with a 15-30% self-preference bias: the model tends to agree with itself, finding the generated content “correct” at rates above what independent reviewers would. The context window shared between generation and review is the contamination vector.

Mitigation: independent review instance

# Generation pass
generation_response = client.messages.create(
model="claude-opus-4-5",
max_tokens=2048,
messages=[
{"role": "user", "content": f"Analyze this contract:\n\n{contract_text}"}
]
)
analysis = generation_response.content[0].text
# Review pass: fresh conversation, no generation context
review_response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
system="You are a critical reviewer. Identify gaps, errors, and unsupported claims.",
messages=[
{
"role": "user",
"content": (
f"Review this contract analysis for accuracy:\n\n"
f"CONTRACT:\n{contract_text}\n\n"
f"ANALYSIS TO REVIEW:\n{analysis}\n\n"
f"Identify any errors, gaps, or claims not supported by the contract text."
)
}
]
)

The review instance receives the source document and the generated analysis but has no memory of generating it. This eliminates the self-preference bias almost entirely. Use it for high-stakes extraction (legal, financial, medical), customer-facing content where errors damage trust, and any task where undetected hallucination is not acceptable.


For borderline classifications, a reasoning field in the output schema surfaces the evidence chain that produced the classification. This is not chain-of-thought prompting; it is a structured output field that forces the model to articulate the key evidence before committing to a label.

{
"classification": {"type": "string", "enum": ["urgent", "standard", "low"]},
"reasoning": {
"type": "string",
"description": "The specific evidence from the input that determined this classification"
},
"confidence": {"type": "number"}
}

When classification: "urgent" and reasoning: "customer explicitly states production outage affecting 10,000 users", a downstream filter can verify the classification in one read. When reasoning is vague or circular (“classified as urgent because it seems urgent”), that is a reliable signal to escalate for human review regardless of the confidence score.


Schema design determines how much of the extraction burden falls on the model versus on downstream validation. Good schemas express what the model genuinely knows; bad schemas force the model to invent values for fields it cannot find.


A confidence score of 0.9 means nothing without a labeled validation set showing that fields labeled 0.9 by this model are actually correct 90% of the time. Uncalibrated confidence scores create a false sense of accuracy.

Building a calibration baseline:

from collections import defaultdict
def calibrate_confidence(
model_outputs: list[dict],
ground_truth: list[dict],
field: str,
bucket_size: float = 0.1
) -> dict:
buckets = defaultdict(lambda: {"correct": 0, "total": 0})
for output, truth in zip(model_outputs, ground_truth):
conf = output.get("confidence", 0.5)
bucket = round(conf / bucket_size) * bucket_size
buckets[bucket]["total"] += 1
if output.get(field) == truth.get(field):
buckets[bucket]["correct"] += 1
return {
bucket: {
"accuracy": data["correct"] / data["total"] if data["total"] > 0 else 0,
"samples": data["total"]
}
for bucket, data in sorted(buckets.items())
}
# Example output:
# {0.9: {"accuracy": 0.91, "samples": 234}} <- well-calibrated
# {0.9: {"accuracy": 0.63, "samples": 234}} <- overconfident, needs adjustment

Per-field thresholds:

Different fields have different error costs. A wrong vendor name on an invoice is annoying; a wrong total amount is a financial error. Set per-field confidence thresholds that route to human review when not met:

REVIEW_THRESHOLDS = {
"vendor_name": 0.70,
"invoice_date": 0.80,
"total_amount": 0.95, # high bar: financial field
"line_items": 0.85
}
def needs_review(extraction: dict, confidence_scores: dict) -> list[str]:
return [
field
for field, threshold in REVIEW_THRESHOLDS.items()
if confidence_scores.get(field, 0) < threshold
]

Accuracy vs confidence plots:

Plot model confidence on the x-axis against actual accuracy on the y-axis. A perfectly calibrated model follows the diagonal. Systematic overconfidence shows up as a curve below the diagonal; systematic underconfidence shows as a curve above it. Both can be corrected with temperature adjustment or post-hoc calibration (Platt scaling).

Calibrate on at least 200 labeled examples per field to get statistically meaningful buckets. Below 100 examples, bucket accuracy estimates are too noisy to act on.


Important: Everything you share with Claude Code is sent to Anthropic servers. Understanding this data flow is critical for protecting sensitive information.

When you use Claude Code, the following data leaves your machine:

Data TypeExampleRisk Level
Your prompts”Fix the login bug”Low
Files Claude reads.env, src/app.tsHigh if contains secrets
MCP query resultsSQL query results with user dataHigh if production data
Command outputsenv | grep API outputMedium
Error messagesStack traces with file pathsLow
ConfigurationRetentionHow to Enable
Default5 years(default state - training enabled)
Opt-out30 daysclaude.ai/settings
Enterprise (ZDR)0 daysEnterprise contract

Immediate action: Disable training data usage to reduce retention from 5 years to 30 days.

1. Block access to sensitive files in .claude/settings.json:

{
"permissions": {
"deny": [
"Read(./.env*)",
"Edit(./.env*)",
"Write(./.env*)",
"Bash(cat .env*)",
"Bash(head .env*)",
"Read(./secrets/**)",
"Read(./**/*.pem)",
"Read(./**/*.key)",
"Read(./**/credentials*)"
]
}
}

Warning: permissions.deny has known limitations. See Security Hardening Guide for details.

2. Never connect production databases to MCP servers. Use dev/staging with anonymized data.

3. Use security hooks to block reading of sensitive files (see Section 7.4).

Full guide: For complete privacy documentation including known risks, community incidents, and enterprise considerations, see Data Privacy & Retention Guide.

Reading time: 5 minutes Goal: Understand the core architecture that powers Claude Code

This section provides a summary of Claude Code’s internal mechanisms. For the complete technical deep-dive with diagrams and source citations, see the Architecture & Internals Guide.

Claude Code runs on a simple while loop:

┌─────────────────────────────────────────────────────────────┐
│ MASTER LOOP (simplified) │
├─────────────────────────────────────────────────────────────┤
│ │
│ Your Prompt │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Claude reasons and selects the next action │ │
│ └───────────────────────┬────────────────────────────┘ │
│ │ │
│ Tool needed? │ │
│ ┌─────┴─────┐ │
│ YES NO │
│ │ │ │
│ ▼ ▼ │
│ Execute Tool Text Response (done) │
│ │ │
│ └──────── Feed result back to Claude │
│ │ │
│ (loop continues) │
│ │
└─────────────────────────────────────────────────────────────┘

Source: Anthropic Engineering Blog

The diagram describes the basic model/tool loop. It does not inventory every current product feature: auto mode can add a permission classifier, and dynamic workflows can coordinate additional agents. The model selects actions within the tools, policy checks and execution controls exposed by the runtime.

The following is a selection of built-in tools, not the complete current inventory:

ToolPurpose
BashExecute shell commands (universal adapter)
ReadRead file contents (max 2000 lines)
EditModify existing files (diff-based)
WriteCreate/overwrite files
GrepSearch file contents (ripgrep-based)
GlobFind files by pattern
AgentSpawn subagents; Task remains a compatibility alias in settings and agent definitions
TodoWriteTrack progress (legacy, see below)

How tool execution works: Claude Code can start executing tools marked as concurrency-safe (read-only operations like Read, Grep, Glob) while the model is still generating its response, reducing total turn time. Non-concurrent tools (writes, bash commands) wait for the response to complete and run serially. When multiple read-only tools appear in a single response, they run in parallel, up to 10 concurrent by default.

Version: Claude Code v2.1.16+ introduced a new task management system

Claude Code provides two task management approaches:

FeatureTodoWrite (Legacy)Tasks API (v2.1.16+)
PersistenceSession memory onlyDisk storage (~/.claude/tasks/)
Multi-session❌ Lost on session end✅ Survives across sessions
Dependencies❌ Manual ordering✅ Task blocking (A blocks B)
CoordinationSingle agent✅ Multi-agent broadcast
Status trackingpending/in_progress/completedpending/in_progress/completed
Description visibility✅ Always visible⚠️ TaskGet only (not in TaskList)
Metadata visibilityN/ANot included in the compact TaskList view
Multi-call overheadNone⚠️ 1 + N calls for N full tasks
Enabled byLegacy selection after task tools are enabledNewer models require opt-in; see below

Available tools:

  • TaskCreate - Create a task; use TaskUpdate for dependency and status changes
  • TaskUpdate - Modify task status, metadata, and dependencies
  • TaskGet - Retrieve individual task details
  • TaskList - List all tasks in current task list
  • TaskOutput was removed in v2.1.278. Use Read on the output path returned by the background task; do not assume a fixed directory.

Core capabilities:

  • Persistent storage: Tasks saved to ~/.claude/tasks/<task-list-id>/
  • Multi-session coordination: Share state across multiple Claude sessions
  • Dependency tracking: Tasks can block other tasks (task A blocks task B)
  • Status lifecycle: pending → in_progress → completed; record failures in the task details rather than inventing a failed state
  • Metadata: Attach custom data (priority, estimates, related files, etc.)

Configuration:

Terminal window
# Opt in on newer models, then select a persistent task list
export CLAUDE_CODE_ENABLE_TODO_TOOLS=1
export CLAUDE_CODE_TASK_LIST_ID="project-name"
claude
# Example: Project-specific task list
export CLAUDE_CODE_TASK_LIST_ID="api-v2-auth-refactor"
claude

⚠️ Important: Use repository-specific task list IDs to avoid cross-project contamination. Tasks with the same ID are shared across all sessions using that ID.

Illustrative task record (not a complete tool-call schema):

{
"id": "task-auth-login",
"subject": "Implement login endpoint",
"description": "POST /auth/login with JWT token generation",
"status": "in_progress",
"blockedBy": [],
"metadata": {
"priority": "high",
"estimated_duration": "2h",
"related_files": ["src/auth/login.ts", "src/middleware/auth.ts"]
}
}

When to use Tasks API:

  • Projects spanning multiple coding sessions
  • Complex task hierarchies with dependencies
  • Multi-agent coordination scenarios
  • Need to resume work after context compaction

⚠️ Tasks API Limitations (Critical)

Field visibility constraint:

ToolVisible FieldsHidden Fields
TaskListid, subject, status, owner, blockedBydescription, activeForm, metadata
TaskGetAll fields-

Impact:

  • Multi-call overhead: Reviewing 10 task descriptions = 1 TaskList + 10 TaskGet calls (11x overhead)
  • No metadata scanning: Cannot filter/sort by custom fields (priority, estimates, tags) without fetching all tasks individually
  • Session resumption friction: Cannot glance at all task notes to decide where to resume

Cost example:

Terminal window
# Inefficient (if you need descriptions)
TaskList # Returns 10 tasks (no descriptions)
TaskGet(task-1), TaskGet(task-2), ..., TaskGet(task-10) # 10 additional calls
# Total: 11 API calls to review 10 tasks

Workaround patterns:

  1. Hybrid approach (Recommended):

    • Use Tasks API for status tracking and dependency coordination
    • Maintain markdown files in repo for detailed implementation plans
    • Example: docs/plans/auth-refactor.md + Tasks for status
  2. Subject-as-summary pattern:

    • Store critical info in subject field (always visible in TaskList)
    • Keep description for deep context (fetch on-demand with TaskGet)
    • Example subjects: "[P0] Fix login bug (src/auth.ts:45)" vs "Fix bug"
  3. Selective fetching:

    • Use TaskList to identify tasks needing attention (status, blockedBy)
    • Only call TaskGet for tasks you’re actively working on

Source: Community practitioner feedback (Gang Rui, Jan 2026)

Tool: TodoWrite - Creates task lists stored in session memory

Capabilities:

  • Simple task tracking within a single session
  • Status tracking: pending/in_progress/completed
  • Lost when session ends or context is compacted

When to use TodoWrite:

  • Single-session, straightforward implementations
  • Quick fixes or exploratory coding
  • Claude Code < v2.1.16
  • Prefer simplicity over persistence

Migration flag (v2.1.19+):

Terminal window
# Opt in to task tools, then select legacy TodoWrite
CLAUDE_CODE_ENABLE_TODO_TOOLS=1 CLAUDE_CODE_ENABLE_TASKS=0 claude
# Opt in to the Tasks API on newer models
CLAUDE_CODE_ENABLE_TODO_TOOLS=1 claude

Task hierarchy design:

Project (parent)
└── Feature A (child)
├── Component A1 (leaf task)
│ ├── Implementation
│ └── Tests (depends on Implementation)
└── Component A2

Dependency management:

  • Add dependencies with TaskUpdate after obtaining the task IDs
  • Use task IDs (not titles) for dependency references
  • Verify dependencies with TaskGet before execution

Status transitions:

  • Mark in_progress when starting work (prevents parallel execution)
  • Update frequently for visibility
  • Only mark completed when fully accomplished (tests passing, validated)
  • Record failure details and blockers in the description or metadata; leave unfinished work uncompleted

Metadata conventions:

{
"priority": "high|medium|low",
"estimated_duration": "2h",
"related_files": ["path/to/file.ts"],
"related_issue": "https://github.com/org/repo/issues/123",
"type": "feature|bugfix|refactor|test"
}

The Diagnostic Principle: When Claude’s task list doesn’t match your intent, the problem sits in your instructions, not in Claude.

Task lists act as a mirror for instruction clarity. If you ask Claude to plan a feature and the resulting tasks surprise you, that divergence is diagnostic information:

Your instruction: "Refactor the auth system"
Claude's task list:
- [ ] Read all auth-related files
- [ ] Identify code duplication
- [ ] Extract shared utilities
- [ ] Update imports
- [ ] Run tests
Your reaction: "That's not what I meant—I wanted to switch from session to JWT"
Diagnosis: Your instruction was ambiguous. "Refactor" ≠ "replace".

Divergence patterns and what they reveal:

Divergence TypeWhat It MeansFix
Tasks too broadInstructions lack specificityAdd WHAT, WHERE, HOW, VERIFY
Tasks too narrowInstructions too detailed, missing big pictureState the goal, not just the steps
Wrong prioritiesContext missing about what mattersAdd constraints and priorities
Missing tasksImplicit knowledge not sharedMake assumptions explicit in prompt
Extra tasksClaude inferred requirements you didn’t intendAdd explicit scope boundaries

Using task divergence as a workflow:

## Step 1: Seed with loose instruction
User: "Improve the checkout flow"
## Step 2: Review Claude's task list (don't execute yet)
Claude generates: [task list]
## Step 3: Compare against your mental model
- Missing: payment retry logic? → Add to instructions
- Unexpected: UI redesign? → Clarify scope (backend only)
- Wrong order: tests last? → Specify TDD approach
## Step 4: Refine and re-plan
User: "Actually, here's what I need: [refined instruction with specifics]"

Pro tip: Run TaskList after initial planning as a sanity check before execution. If more than 30% of tasks surprise you, your prompt needs work. Iterate on the prompt, not the tasks.

→ See: Task Management Workflow for:

  • Task planning phase (decomposition, hierarchy design)
  • Task execution patterns
  • Session management and resumption
  • Integration with TDD and Plan-Driven workflows
  • TodoWrite migration guide
  • Patterns, anti-patterns, and troubleshooting

Context is model/provider dependent: current Opus, Sonnet and Fable models have native 1M windows on the direct API; Haiku 4.5 has 200K. Older variants have separate access rules. See 200K vs 1M comparison. The following sizes are illustrative, not fixed reservations:

ComponentApproximate Size
System prompt5-15K tokens
CLAUDE.md files1-10K tokens
Conversation historyVariable
Tool resultsVariable
Reserved for response40-45K tokens

Native 1M sessions normally auto-compact around 967K tokens. /autocompact can choose a smaller window. Compaction can omit information needed later, so save decisions and verification commands before a handoff. Use /compact at logical breakpoints; a fixed percentage is not a universal quality threshold. See [Session Handoffs](line 2140) and Auto-Compaction Research.

The Agent tool spawns subagents with:

  • Their own context, subject to the chosen subagent type
  • Tools controlled by the agent definition and permission policy
  • Up to three nested layers by default since v2.1.219, configurable with CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH
  • A result returned to the parent instead of injecting the whole working transcript

See the official subagent depth rules.

This limits transcript accumulation in the parent. Ordinary subagents start with fresh context; forked subagents can inherit history. Separate conversation context does not isolate filesystem changes, credentials or external effects. Use a worktree or other isolation when needed; see subagent context.

Agent Teams provide a lead, independently working teammates, shared tasks and direct mailbox messages. Enable them with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1; choose an available model for each teammate.

Task state lives under ~/.claude/tasks/<team-name>/, with team configuration and inboxes under ~/.claude/teams/<team-name>/. File locking prevents simultaneous claims of one task. It does not merge source changes or prevent two agents editing the same file.

Use separate file ownership or worktrees for edits. Ask the lead to stop or redirect teammates when their scope changes. Display modes include in-process and terminal split panes; use Shift+Down to cycle teammates in-process.

Older community material uses the name TeammateTool and inferred operations such as spawnTeam. Treat those as historical implementation notes, not the current documented interface. See Agent Teams and §9.20 for current operation and limitations.

Agent anti-patterns: Roles vs context control

Section titled “Agent anti-patterns: Roles vs context control”

“Subagents are not for anthropomorphizing roles, they are for controlling context” - Dex Horty

Common Mistake: Creating agents as if building a human team with job titles.

❌ Wrong (Anthropomorphizing):

- Frontend Agent (role: UI developer)
- Backend Agent (role: API engineer)
- QA Agent (role: tester)
- Security Agent (role: security expert)

Why this fails: Agents aren’t humans with expertise areas. They’re context isolation tools for computational efficiency.

✅ Right (Context Control):

- Agent for isolated dependency analysis (scope: package.json + lock files only)
- Agent for parallel file processing (scope: batch edits without main context pollution)
- Agent for fresh security audit (scope: security-focused analysis without prior assumptions)
- Agent for independent module testing (scope: test execution without interfering with main workflow)

Key differences:

Anthropomorphizing (Wrong)Context Control (Right)
“Security expert agent""Security audit with isolated context"
"Frontend developer agent""UI component analysis (scope: src/components/ only)"
"Code reviewer agent""PR review without main context pollution”
Mimics human team structureOptimizes computational resources
Based on job rolesBased on scope/context boundaries

When to use agents (good reasons):

  • Isolate context: Prevent pollution of main conversation context
  • Parallel processing: Independent operations that can run concurrently
  • Scope limitation: Restrict analysis to specific files/directories
  • Fresh perspective: Analyze without baggage from previous reasoning
  • Resource optimization: Offload heavy operations to separate context window

When NOT to use agents (bad reasons):

  • ❌ Creating a fake team with job titles
  • ❌ Roleplaying different “expertise” personas
  • ❌ Mimicking human organizational structure
  • ❌ Splitting work by discipline (frontend/backend/QA) instead of by context boundaries

Beyond generic sub-agents, scope-focused orchestration assigns distinct context boundaries to different agents for multi-perspective analysis.

The Pattern: Instead of one agent reviewing everything, spawn scope-isolated agents that each analyze distinct aspects with fresh context:

User: Review the new payment service using scope-focused analysis:
Agent 1 (Security Scope): Analyze authentication, input validation,
injection vectors, secret handling, PCI DSS compliance.
Context: src/payment/, src/auth/, config/security.yml
Agent 2 (Performance Scope): Analyze database queries, N+1 problems,
caching opportunities, response time bottlenecks.
Context: src/payment/repository/, src/database/, slow query logs
Agent 3 (API Design Scope): Analyze error messages, response format
consistency, API discoverability, documentation completeness.
Context: src/payment/api/, docs/api/, tests/integration/
Synthesize all three scoped analyses into a unified review with
prioritized action items.

Implementation with Custom Agents:

.claude/agents/security-audit.md
---
name: security-audit
model: opus
tools: Read, Grep, Glob
---
Analyze code for security issues with isolated context:
- OWASP Top 10 vulnerabilities
- Authentication/authorization flaws
- Input validation gaps
- Secret exposure risks
Scope: Security-focused analysis only. Report findings with severity
ratings (Critical/High/Medium/Low) without considering performance
or UX trade-offs.
.claude/agents/perf-audit.md
---
name: perf-audit
model: sonnet
tools: Read, Grep, Glob, Bash
---
Analyze code for performance bottlenecks with isolated context:
- Database query efficiency (N+1, missing indexes)
- Memory leaks and resource management
- Caching opportunities
- Algorithmic complexity issues
Scope: Performance-focused analysis only. Report findings with estimated
impact (High/Medium/Low) without considering security or maintainability
trade-offs.

When to use scope-focused agents:

  • Analysis requiring 3+ distinct context boundaries (security scope, perf scope, API scope)
  • Competing concerns that benefit from isolated evaluation (performance vs. security vs. DX)
  • Large codebases where full context would pollute analysis of specific aspects

When NOT to use scope-focused agents:

  • Simple reviews (one agent with full context covers all aspects)
  • Time-constrained situations (overhead of synthesis outweighs benefit)
  • Tasks where scopes aren’t genuinely independent (overlapping context needed)

A small model/tool loop is a useful starting point for reasoning about the system. More capable models and additional orchestration still need explicit tool boundaries and verification.

Use that simplified model to locate decisions, tool results and failures. It does not prove that fewer components always improve reliability or that a model-selected action is correct.

TopicWhere
Full architecture detailsArchitecture & Internals Guide
Permission systemSection 7 - Hooks
MCP integrationSection 8.6 - MCP Security
Context management tipsSection 2.2

Quick jump: Memory Files (CLAUDE.md) · .claude/ Folder Structure · Settings & Permissions · Precedence Rules