Skip to content

Claude Code Architecture & Agent Loop

Last updated:

A technical guide to documented Claude Code behavior, with separately attributed community observations. Cited historical analyses do not establish current internals.

Author: Florian BRUNIAUX | Contributions from Claude (Anthropic)

Reading time: ~25 minutes (full) | ~5 minutes (TL;DR only)

Last verified: October 2026 for the tool inventory, context-window and sub-agent claims corrected below. Other sections retain their cited source dates.


This document combines three tiers of sources:

TierDescriptionEvidence limitExample
Tier 1Official Anthropic documentationContract or behavior for the cited version/date and scopecode.claude.com documentation
Tier 2Cited inspection or reverse-engineeringObservation limited to the inspected version and methodPromptLayer analysis
Tier 3Community inferenceUnverified explanation, not a product contractObserved but not officially confirmed

Source labels describe provenance, not measured confidence. Prefer current official documentation; historical observations remain bounded by their source dates and methods.


Where Claude Code sits in the harness stack

Section titled “Where Claude Code sits in the harness stack”

Claude Code is a runtime harness: it owns the iterative model-and-tool loop for a coding task. The model generates tokens; the repository supplies instructions, setup, state, and verification; an orchestrator coordinates multiple runtime sessions. Those layers answer different questions and should not be evaluated as interchangeable products.

Read Agent Harness Engineering for the four-layer model and the mechanics inside a runtime. Use the Agent Harness Map when comparing products that own a coding loop. Use Agent Tools: Beyond Claude Code for the broader set of frameworks, control planes, and runtime-adjacent tools. The glossary defines the terms used across those pages.

Claude Code is the product you run in a terminal, an IDE or the desktop app. The Claude Agent SDK is a library that embeds Claude Code’s agent in your own Python or TypeScript application. According to the official Agent SDK overview, it runs the Claude Code binary and provides the same tools, agent loop and context management, including permissions, sessions, hooks, subagents and MCP. The loop and context mechanics on this page therefore also describe agents built with the SDK. The SDK-only loop limit is covered in Controlling loop depth with max_turns. For how the SDK compares with other agent frameworks, see Agent Tools §3.4.


  1. Agentic loop: The model proposes tools or a response; the harness applies permission checks before executing tools. Auto mode can use a classifier. This loop is a teaching model, not a complete description of every runtime component. Permission system.

  2. Built-in and extensible tools: Claude Code provides file editing, shell access, search, sub-agents and other built-in capabilities. The available set varies by version, model and configuration; the tools reference is the current inventory.

    Search Strategy Evolution: Early Claude Code versions experimented with RAG using Voyage embeddings for semantic code search. Anthropic switched to grep-based (ripgrep) agentic search after internal benchmarks showed superior performance with lower operational complexity: no index sync required, no security liabilities from external embedding providers. This “Search, Don’t Index” philosophy trades latency/tokens for simplicity/security. Community plugins (ast-grep for AST patterns) and MCP servers (Serena for symbols, grepai for RAG) available for specialized needs.

    Source: Latent Space podcast (May 2025), ast-grep documentation

  3. Model-dependent context budget: The context window is shared between instructions, history, tool results and responses. Supported models and account configurations can provide 200K or 1M tokens; model configuration documents availability and auto-compaction controls.

  4. Sub-agent context: Ordinary sub-agents start fresh; forks inherit the parent’s conversation at spawn. Context separation does not isolate filesystem or external effects. Ordinary delegation has a configurable depth limit, three layers below the main conversation by default; forks cannot spawn further forks. Sub-agent modes and limits.

  5. Philosophy: “Less scaffolding, more model.” Trust Claude’s reasoning instead of building complex orchestration systems around it.


Claude Code is not a new AI model. It’s an orchestration layer that wraps Claude (Opus/Sonnet/Haiku) with the ability to read files, run shell commands, navigate repositories, and spawn sub-agents, all in a continuous loop until the task is done.

Your Development Environment

File System

Git Repository

Shell / CLI

MCP Servers

Claude Code — Orchestration Layer

Claude Model\n(Opus / Sonnet / Haiku)

Tool Arsenal\n(Read · Edit · Bash · Agent · Grep…)

Developer

Your Development Environment

File System

Git Repository

Shell / CLI

MCP Servers

Claude Code — Orchestration Layer

Claude Model\n(Opus / Sonnet / Haiku)

Tool Arsenal\n(Read · Edit · Bash · Agent · Grep…)

Developer

Inspired by Mohamed Ali Ben Salem’s architecture diagram. See Architecture Internals diagrams for a deeper breakdown.


  1. The Master Loop
  2. The Tool Arsenal
  3. Context Management Internals
  4. Sub-Agent Architecture
  5. Permission & Security Model
  6. MCP Integration
  7. Advanced Tool Use Patterns (API)
  8. The Edit Tool: How It Actually Works
  9. Session Persistence
  10. Philosophy: Less Scaffolding, More Model
  11. Claude Code vs Alternatives
  12. Sources & References
  13. Appendix: What We Don’t Know

Source category: Tier 1, Official; bounded by the cited version/date and scope. Source: Anthropic Engineering Blog

The diagram shows the central loop, with permission evaluation condensed into the tool step. It omits hook lifecycle, compaction, retries and delegation details.

┌─────────────────────────────────────────────────────────────┐
│ CLAUDE CODE MASTER LOOP │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ Your Prompt │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ CLAUDE REASONS │ │
│ │ (Select the next action) │ │
│ │ │ │
│ └────────────────────────┬─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Tool Call? │ │
│ └───────┬────────┘ │
│ │ │
│ YES │ NO │
│ ┌─────────────────┴─────────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ │
│ │ Evaluate │ │ Text │ │
│ │ permission │ │ Response │ │
│ │ run/refuse │ │ (DONE) │ │
│ └─────┬──────┘ └────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Feed Result │ │
│ │ to Claude │──────────────────┐ │
│ └─────────────┘ │ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ LOOP BACK │ │
│ │ (Next turn) │ │
│ └────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Simplified teaching pseudocode, not an implementation of the permission or hook system:

while (claude_response.has_tool_call):
result = evaluate_permissions_and_run_or_refuse(tool_call)
claude_response = send_to_claude(result)
return claude_response.text

The model selects the next action, subject to harness controls. Permission rules are enforced by Claude Code, and auto mode can use a classifier. Optional workflows and extensions add other control paths; this sketch does not prove their absence. See how Claude Code works and the current tool inventory.

  1. Simplicity: Fewer components = fewer failure modes
  2. Model-driven: Claude’s reasoning is better than hand-coded heuristics
  3. Flexibility: No rigid pipeline constraining what Claude can do
  4. Debuggability: Easy to understand what happened and why

The master loop diagram above shows the flow conceptually, but the Messages API exposes it through concrete stop_reason values. These three common values illustrate the loop; see the official stop-reason reference for the full list.

stop_reasonMeaningLoop action
tool_useClaude wants to call one or more toolsExecute tools, feed results back, continue loop
end_turnClaude decided it has finishedExit loop, return the text response
max_tokensRequested output-token limit reachedRaise the output limit or continue the response

The pseudocode becomes precise with these names:

messages = [{"role": "user", "content": user_prompt}]
while True:
response = client.messages.create(model=model, messages=messages, tools=tools)
if response.stop_reason == "end_turn":
return response.content[0].text # done
if response.stop_reason == "tool_use":
# Process every tool_use block in the response
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result
})
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
# loop continues

The tool_use block inside response.content has three fields you act on: id (to match results back), name (which function to call), and input (a dict of arguments). The result you send back must reference tool_use_id so the model can correlate call and response.

fork_session is a higher-level concept built on this loop: it creates an independent branch of the current conversation, sharing the same message history up to the fork point. Both branches can explore different approaches or configurations simultaneously, like git branch but for agent sessions. Each fork runs its own agentic loop independently, useful for comparing responses under different tool configurations or prompt variants without re-running the full conversation from scratch.

max_turns caps the number of assistant/tool iterations before the orchestrator exits. Without an explicit limit, a runaway loop can exhaust budget or context window in ways that are hard to diagnose after the fact.

Practical ranges by task type:

Task typeRecommended max_turns
Simple retrieval (single lookup)5
Research or multi-step coding20-30
Extended autonomous workflows50

max_turns is an Agent SDK loop limit, not a Messages API stop_reason. If this cap is reached, the task may be incomplete. Inspect the SDK’s final result message for subtype == "error_max_turns", as documented in the Python Agent SDK reference:

from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query
# Inside an async function; handle_incomplete is your application callback.
async for message in query(prompt=task, options=ClaudeAgentOptions(max_turns=20)):
if isinstance(message, ResultMessage) and message.subtype == "error_max_turns":
handle_incomplete(message)

Setting max_turns per task type rather than globally prevents a single slow task from starving others in a multi-agent pipeline. A nightly batch job that legitimately needs 50 turns should not inherit the same cap as a quick lookup that should resolve in 5.

Use this checklist to verify you understand Claude Code’s full surface area. Each capability is documented in detail elsewhere in this guide.

The 11 Native Capabilities:

  • Event Hooks: Bash/PowerShell scripts triggered on tool execution

    • PreToolUse, PostToolUse, UserPromptSubmit, Notification
    • See: Section 5 Hooks
  • Skill-Scoped Hooks: Event hooks specific to skill execution context

  • Background Agents: Async task execution (test suites, long operations)

  • Explore Subagent: /explore for codebase analysis

  • Plan Subagent: /plan for read-only planning mode

  • Agent Tool: Hierarchical task delegation to specialized agents

  • Agent Teams: Multi-agent parallel coordination (experimental v2.1.32+)

  • Per-Task Model Selection: Dynamic model switching mid-session

  • MCP Protocol Integration: Model Context Protocol for tool extensions

  • Permission Modes: Fine-grained control over tool execution

  • Session Memory: Persistent context across sessions

Onboarding Tip: If you haven’t explored all 11 capabilities, you’re likely missing productivity opportunities. Focus on the unchecked items above.

Source: Synthesized from Gur Sannikov analysis


Source category: Tier 1, Official; bounded by the cited version/date and scope. Source: code.claude.com/docs

The tools below are examples, not an exhaustive inventory. See the current tools reference for availability by model and configuration.

ToolPurposeKey BehaviorToken Cost
BashExecute shell commandsUniversal adapter, most powerfulLow (command) + Variable (output)
ReadRead file contentsMax 2000 lines, handles truncationHigh for large files
EditModify existing filesDiff-based, requires exact matchMedium
WriteCreate/overwrite filesMust read first if file existsMedium
GrepSearch file contentsRipgrep-based (regex), replaced RAG/embedding approach. For structural code search (AST-based), see ast-grep plugin. Trade-off: Grep (fast, simple) vs ast-grep (precise, setup required) vs Serena MCP (semantic, symbol-aware)Low
GlobFind files by patternPath matching, sorted by mtimeLow
AgentSpawn sub-agents (formerly Task)Fresh or forked context; ordinary nesting configurable (three layers by default); filesystem effects may be sharedDepends on delegation mode
TodoWrite / Task toolsTrack progressAvailable tools and defaults vary by model and configuration; consult the current tool referenceDepends on task list

Key insight: Bash is Claude’s swiss-army knife. It can:

  • Run any CLI tool (git, npm, docker, curl…)
  • Execute scripts
  • Chain commands with pipes
  • Access system state

The model has been trained on massive amounts of shell data, making it highly effective at using Bash as a universal adapter when specialized tools aren’t enough.

Claude decides which tool to use based on the task. There’s no hardcoded routing:

┌─────────────────────────────────────────────────────┐
│ TOOL SELECTION (Model-Driven) │
├─────────────────────────────────────────────────────┤
│ │
│ "Read auth.ts" → Read tool │
│ "Find all test files" → Glob tool │
│ "Search for TODO" → Grep tool │
│ "Run npm test" → Bash tool │
│ "Explore the codebase" → Agent (sub-agent) │
│ "Track my progress" → Available task tools │
│ │
│ The model learns these patterns during training, │
│ not from explicit rules. │
│ │
└─────────────────────────────────────────────────────┘

Beyond the built-in tools listed in the tools reference, Claude Code can use:

MCP Servers (Model Context Protocol):

  • Serena: Symbol-aware code navigation + session memory
  • grepai: Semantic search + call graph analysis (Ollama-based)
  • Context7: Official library documentation lookup
  • Sequential: Structured multi-step reasoning
  • Playwright: Browser automation and E2E testing
  • claude-code-ultimate-guide: 12 tools: guide search, release tracking, compare_versions, security threat lookup (get_threat, list_threats with 28 CVEs + 655 malicious skills), template search (search_examples); install via npx -y claude-code-ultimate-guide-mcp

Community Plugins:

  • ast-grep: AST-based structural code search (explicit invocation)

Claude Code offers multiple ways to search code, each with specific strengths:

Search NeedNative ToolMCP/Plugin AlternativeWhen to Escalate
Exact textGrep (ripgrep)-Never (fastest)
Function nameGrepSerena find_symbolMulti-file refactoring
By meaning-grepai searchDon’t know exact text
Call graph-grepai trace_callersDependency analysis
Structural pattern-ast-grepLarge migrations (>50k lines)
File structure-Serena get_symbols_overviewNeed symbol context

Performance Comparison:

ToolSpeedSetupUse Case
Grep (ripgrep)⚡ ~20ms✅ None90% of searches
Serena⚡ ~100ms⚠️ MCPRefactoring, symbols
grepai🐢 ~500ms⚠️ Ollama + MCPSemantic, call graph
ast-grep🕐 ~200ms⚠️ PluginAST patterns, migrations

Decision principle: Start with Grep (fastest), escalate to specialized tools only when needed.

📖 Deep Dive: See Search Tools Mastery for comprehensive workflows combining all search tools.


Source category: Tier 2, Partially Official; limited to the cited observation and method. Sources:

Claude Code’s context-window size depends on the model, plan and provider. Supported configurations provide 200K or 1M tokens; see extended context.

┌─────────────────────────────────────────────────────────────┐
│ CONTEXT BUDGET (model-dependent) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ System Prompt (variable) │ │
│ │ • Tool definitions │ │
│ │ • Safety instructions │ │
│ │ • Behavioral guidelines │ │
│ │ • See detailed breakdown below ↓ │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ CLAUDE.md Files and Rules (variable) │ │
│ │ • Global ~/.claude/CLAUDE.md │ │
│ │ • Project CLAUDE.md or .claude/CLAUDE.md │ │
│ │ • Native .claude/rules/ files │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Conversation History (variable) │ │
│ │ • Your prompts │ │
│ │ • Claude's responses │ │
│ │ • Tool call records │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Tool Results (variable) │ │
│ │ • File contents from Read │ │
│ │ • Command outputs from Bash │ │
│ │ • Search results from Grep │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Response / compaction allowance (variable) │ │
│ │ • Claude's thinking │ │
│ │ • Generated code/text │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ Measure the session with /context; no fixed free budget │
│ │
└─────────────────────────────────────────────────────────────┘

Source category: Tier 1, Official Anthropic Documentation; bounded by the cited version/date and scope. Sources:

Claude Code’s system prompt is not published, according to its settings documentation. Anthropic’s released Claude.ai/mobile prompts do not establish the current CLI prompt’s text or token size.

Documented context components include instructions, available tool definitions, history and tool results. Tool availability varies by model and configuration. User instructions such as CLAUDE.md shape behavior; permission settings control allowed actions. The exact request layout, prompt size and internal cache allocation remain unverified here.

Important Distinctions:

  • Claude.ai/Mobile: Published prompts available publicly
  • Anthropic API: Different default instructions, configurable by developers
  • Claude Code CLI: Agentic coding assistant with context-gathering behavior

Historical community analysis of Claude-family prompts, not evidence of the current Claude Code prompt:

→ Cross-reference: For security implications, see Section 5: Permission & Security Model

Cache scope: The API prompt-caching contract separates organizations, with workspace isolation on the Claude API, Claude Platform on AWS and Microsoft Foundry; Bedrock and Google Cloud use organization isolation. This contract does not establish Claude Code’s internal cache layout. Fork reuse is documented separately in the sub-agent reference.


Source category: Tier 2, Community-verified with research backing; limited to the cited observation and method.

When context usage exceeds a threshold, Claude Code automatically summarizes older conversation turns:

SourceReported ThresholdNotes
VS Code extension~75% usage (25% remaining)GitHub #11819 (Nov 2025)
CLI version1-5% remainingMore conservative than VS Code
PromptLayer analysis92%Historical observation
Steve Kinney95%Session Management Guide (Jul 2025)
User-triggered /compactAnytimeManual control

What happens during compaction:

  1. Older conversation turns are summarized
  2. Tool results are condensed
  3. Recent context is preserved in full
  4. The model receives a “context was compacted” signal

Performance Impact (Research-backed):

Recent research and practitioner observations confirm quality degradation with auto-compaction:

  • LLM performance drops 50-70% on complex tasks as context grows from 1K to 32K tokens (Context Rot Research, Jul 2025)
  • 11 out of 12 models fall below 50% of their short-context performance at 32K tokens (NoLiMa benchmark)
  • Auto-compact loses nuance and breaks references through repeated compression cycles (Claude Saves Tokens, Forgets Everything, Jan 2026)
  • Attention mechanism struggles with retrieval burden in high-context scenarios

Community Consensus: Manual /compact at logical breakpoints > waiting for auto-compact to trigger.

Recommended Strategy (Lorenz, 2026 (original LinkedIn post unavailable)):

Context %ActionRationale
70%Warning - Plan cleanupEarly awareness
85%Manual handoff recommendedPrevent auto-compact degradation
95%Force handoffSevere quality degradation

User control: Use /compact manually to trigger summarization at logical breakpoints, or use session handoffs (see Session Handoffs) to preserve intent over compressed history.

StrategyWhen to UseHow
Sub-agentsExploratory tasksAgent tool for a separate context; shared effects require coordination
Manual compactProactive cleanup/compact command
Clear sessionFresh start needed/clear command
Specific readsKnow what you needRead exact files, not directories
CLAUDE.mdPersistent contextStore conventions in memory files

Source category: Tier 2, Practitioner studies, arXiv research; limited to the cited observation and method.

Claude Code’s effectiveness degrades predictably under certain conditions:

ConditionObserved ThresholdSymptom
Conversation turns15-25 turnsLoses track of earlier constraints
Token accumulation80-100K tokensIgnores requirements stated early in session
Problem scope>5 files simultaneouslyInconsistent changes, missed files

Success rates by scope (from practitioner studies):

ScopeSuccess RateExample
1-3 files~85%Fix bug in single module
4-7 files~60%Refactor feature across components
8+ files~40%Codebase-wide changes

Mitigation strategies:

  1. Checkpoint prompts: “Before continuing, recap the current requirements and constraints.”
  2. Session resets: Start fresh for new tasks (/clear)
  3. Scope tightly: Break large tasks into focused sub-tasks
  4. Use sub-agents: Delegate exploration to the Agent tool to preserve main context

A separate degradation mode that does not depend on context size: repeated tool failures. When a tool call fails and Claude retries, error output accumulates in the context window. Stack traces, retry noise, and error messages dilute the original intent. Subsequent attempts follow the error narrative rather than the task goal. The context window is not full, but the signal-to-noise ratio has degraded.

This is distinct from compaction drift. Compaction addresses context size; failure re-injection addresses context quality within a bounded window.

Pattern: re-inject the core task instruction on every command failure, not just after /compact. A PostToolUse hook can prefix retried prompts with a condensed version of the original task and constraints:

Terminal window
# PostToolUse hook: re-inject intent after failures
if [[ "$CLAUDE_TOOL_EXIT_CODE" != "0" ]]; then
echo "REMINDER: The current task is: $ORIGINAL_TASK_SUMMARY. Ignore the above error if non-blocking and continue toward that goal."
fi

Source: Nick Tune, Workflow DSL: Domain-Driven Claude Code Workflows (2026-03-01)


Source category: Tier 1, Documented behavior; bounded by the cited version/date and scope. Source: Claude Code sub-agent documentation

Claude Code’s Agent tool delegates work into a separate context. That boundary does not isolate shared files, services or external actions.

This figure describes an ordinary, non-fork sub-agent. Forks inherit the parent’s conversation at spawn; isolation: "worktree" gives separate Git files, not separate external services. Fork behavior.

┌─────────────────────────────────────────────────────────────┐
│ MAIN AGENT │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Context: Full conversation + all file reads │ │
│ │ │ │
│ │ Agent("Explore authentication patterns") │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ SUB-AGENT (Spawned) │ │ │
│ │ │ │ │ │
│ │ │ • Own fresh context window │ │ │
│ │ │ • Task, definition and applicable context │ │ │
│ │ │ • Tools vary by agent and permission settings │ │ │
│ │ │ • May delegate (default depth: 3 layers) │ │ │
│ │ │ • Returns: summary text only │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ Result: "Found 3 auth patterns: JWT in..." │ │
│ │ (Only this text enters main context) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Sub-agents can delegate up to three layers below the main conversation by default. The depth limit can be configured; a sub-agent without the agent tool cannot delegate. Each agent uses its own context and contributes to usage limits, so nested delegation needs explicit task boundaries.

Forks cannot spawn further forks. Fresh sub-agents may also load applicable instructions and preloaded skills; they receive more than the task string. Startup context.

Built-in types and tool restrictions vary by version and configuration. The current reference lists:

TypePurposeTools Available
ExploreCodebase explorationAll read-only tools
PlanResearch during plan modeRead-only tools; Write and Edit denied
general-purposeComplex multi-stepTools available to sub-agents, subject to permissions
Other helpersSession-specific assistanceDepends on helper and configuration
Use CaseWhy Sub-Agent Helps
Searching large codebasesKeeps main context clean
Parallel explorationMultiple searches simultaneously
High-volume explorationIntermediate output stays in a separate context; shared effects still need controls
Specialized analysisDifferent “mindset” for different tasks

A proposed hub-and-spoke pattern assigns integration to one coordinator. The following diagram expresses that coordination policy, not a restriction on peer messaging or context inheritance.

┌─────────────────────┐
│ COORDINATOR │
│ (Hub / Orchestrator)│
│ │
│ • Decomposes goal │
│ • Passes context │
│ • Aggregates results│
│ • Resolves conflicts│
└──┬──────┬──────┬───┘
│ │ │
┌──────────┘ │ └──────────┐
│ │ │
┌──────▼──────┐ ┌───────▼─────┐ ┌───────▼─────┐
│ WORKER A │ │ WORKER B │ │ WORKER C │
│ │ │ │ │ │
│ Specific │ │ Specific │ │ Specific │
│ task only │ │ task only │ │ task only │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└────────────────►│◄────────────────┘
(results flow back to coordinator only)

Check the delegation mode. Fresh sub-agents need explicit task context; forks inherit a snapshot. Neither automatically receives a sibling’s later findings. Pass those findings or coordinate through supported messages and shared files. Startup context and forks.

Explicit context passing pattern:

# Teaching pseudocode, not a Claude Code API
# Independent fresh workers do not automatically share findings
task_a = delegate_fresh("Analyze auth.py and find the session token logic")
task_b = delegate_fresh("Find all callers of the session token logic")
# Wait for the result, then supply it to the next fresh worker
result_a = await_result(task_a)
task_b = delegate_fresh(f"Find all callers of {result_a} across the codebase")

Coordinator responsibilities:

  1. Decompose: Break the goal into independent subtasks with clear boundaries
  2. Pass context explicitly: Each worker task description must be self-contained
  3. Aggregate: Collect text results from all workers, combine into coherent output
  4. Resolve cross-cutting questions: Assign integration decisions to the coordinator in this pattern

In this proposed pattern, route dependencies through the coordinator. Peer communication is also supported when the selected session exposes messaging tools; choose a coordination policy that fits the task.


Source category: Tier 1, Official; bounded by the cited version/date and scope. Sources:

Claude Code has a layered security model:

┌─────────────────────────────────────────────────────────────┐
│ PERMISSION LAYERS │
├─────────────────────────────────────────────────────────────┤
│ │
│ Layer 1: INTERACTIVE PROMPTS │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Claude wants to run: rm -rf node_modules │ │
│ │ [Allow once] [Allow always] [Deny] [Edit command] │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Layer 2: ALLOW/DENY RULES (settings.json) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ { │ │
│ │ "permissions": { │ │
│ │ "allow": ["Bash(npm *)", "Read"], │ │
│ │ "deny": ["Bash(rm -rf *)"] │ │
│ │ } │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Layer 3: HOOKS (Pre/Post execution) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ PreToolUse: Validate before execution │ │
│ │ PostToolUse: Audit after execution │ │
│ │ PermissionRequest: Override permission prompts │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Layer 4: SANDBOX MODE (Optional isolation) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Filesystem isolation + Network restrictions │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Source category: Tier 2, Observed but not exhaustive; limited to the cited observation and method.

Claude Code appears to flag certain patterns for extra scrutiny:

PatternRiskBehavior
rm -rfDestructive deletionAlways prompts
sudoPrivilege escalationAlways prompts
curl | shRemote code executionAlways prompts
chmod 777Insecure permissionsAlways prompts
git push --forceHistory destructionAlways prompts
DROP TABLEData destructionAlways prompts

This is not a complete blocklist. Patterns are likely detected through model training rather than explicit rules.

Source category: Tier 1, Official; bounded by the cited version/date and scope. Source: code.claude.com/docs/en/sandboxing

Claude Code includes built-in native sandboxing using OS-level primitives for process-level isolation:

┌──────────────────────────────────────────────────────┐
│ Native Sandbox Architecture │
├──────────────────────────────────────────────────────┤
│ │
│ Bash Command Request │
│ │ │
│ ▼ │
│ Sandbox Wrapper (Seatbelt/bubblewrap) │
│ │ │
│ ├─ Filesystem: read all, write CWD only │
│ ├─ Network: SOCKS5 proxy + domain filtering │
│ ├─ Process: isolated environment │
│ │ │
│ ▼ │
│ OS Kernel Enforcement │
│ │ │
│ ├─ Allowed: operations within boundaries │
│ ├─ Blocked: violations at system call level │
│ └─ Notify: user receives alert on violation │
│ │
└──────────────────────────────────────────────────────┘

OS Primitives:

PlatformMechanismNotes
macOSSeatbelt (TrustedBSD MAC)Built-in, kernel-level system call filtering
Linux/WSL2bubblewrap (namespaces + seccomp)Requires: sudo apt-get install bubblewrap socat
WSL1❌ Not supportedbubblewrap needs kernel features unavailable
Windows❌ Not supportedCommands run unsandboxed; use WSL2

Isolation Model:

  1. Filesystem:

    • Read: Entire computer (except denied paths)
    • Write: Current working directory only (configurable)
    • Blocked: Modifications outside CWD, credentials directories (~/.ssh, ~/.aws)
  2. Network:

    • Proxy: All connections routed through SOCKS5 proxy
    • Domain filtering: Allowlist/denylist mode
    • Default blocked: Private CIDRs, localhost ranges
  3. Process:

    • Shared kernel: Vulnerable to kernel exploits (unlike Docker microVM)
    • Child processes: Inherit same sandbox restrictions
    • Escape hatch: dangerouslyDisableSandbox parameter for incompatible tools

Sandbox Modes:

  • Auto-allow mode: Bash commands auto-approved if sandboxed (recommended for daily dev)
  • Regular permissions mode: All commands require explicit approval (high-security)

Security Trade-offs:

AspectNative SandboxDocker Sandboxes (microVM)
Kernel isolation❌ Shared kernel✅ Separate kernel per VM
Setup0 deps (macOS), 2 pkgs (Linux)Docker Desktop 4.58+
OverheadMinimal (~1-3% CPU)Moderate (~5-10% CPU)
Use caseDaily dev, trusted codeUntrusted code, max security

Security Limitations:

⚠️ Domain fronting: CDNs (Cloudflare, Akamai) can bypass domain filtering ⚠️ Unix sockets: Misconfigured allowUnixSockets grants privilege escalation ⚠️ Filesystem: Overly broad write permissions enable attacks on $PATH directories

When to use:

  • ✅ Native Sandbox: Daily development, trusted team, lightweight setup
  • ✅ Docker Sandboxes: Untrusted code, kernel exploit protection, Docker-in-Docker needed

Deep dive: See Native Sandboxing Guide for complete technical reference, configuration examples, and troubleshooting.

Hooks allow programmatic control over Claude’s actions:

{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "/path/to/validate-command.sh"
}]
}
],
"PostToolUse": [
{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "/path/to/audit-log.sh"
}]
}
]
}
}

Hook capabilities:

CapabilitySupportedHow
Block executionYesExit code 2
Modify parametersYesReturn modified JSON
Log actionsYesWrite to file in hook
Async processingYesSet async: true in hook config (v2.1.0+)

Hook JSON payload (passed via stdin):

{
"session_id": "abc123",
"transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",
"cwd": "/path/to/project",
"permission_mode": "default",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm install lodash"
}
}

Common fields sent to all events: session_id, transcript_path, cwd, permission_mode, hook_event_name. Event-specific fields (e.g., tool_name/tool_input for PreToolUse) are added on top.

→ Cross-reference: See Section 7 - Hooks in the main guide for complete examples.


Source category: Tier 1, Official; bounded by the cited version/date and scope. Source: code.claude.com/docs/en/mcp

MCP (Model Context Protocol) servers extend Claude Code with additional tools.

💡 Visual Guide: The following diagram illustrates how MCP creates a secure control layer between LLMs and real systems. The LLM layer has no direct data access - the MCP Server enforces security policies before tools can interact with databases, APIs, or files.

MCP Architecture - 7-Layer Security Model

Figure 1: MCP Architecture showing separation between thinking (LLM), control (MCP Server), and execution (Tools). Design inspired by Dinesh Kumar’s LinkedIn visualization, recreated under Apache-2.0 license.

Key security boundaries:

  • Yellow layer (LLM): Reasoning only - No Data Access
  • Orange layer (MCP Server): Security control point (policies, validation, logs)
  • Grey layer (Real Systems): Protected data - Hidden From AI
┌─────────────────────────────────────────────────────────────┐
│ MCP INTEGRATION │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ CLAUDE CODE │ │
│ │ │ │
│ │ Native Tools MCP Tools │ │
│ │ ┌─────────┐ ┌─────────────────────────┐ │ │
│ │ │ Bash │ │ mcp__serena__* │ │ │
│ │ │ Read │ │ mcp__context7__* │ │ │
│ │ │ Edit │ │ mcp__playwright__* │ │ │
│ │ │ ... │ │ mcp__custom__* │ │ │
│ │ └─────────┘ └───────────┬─────────────┘ │ │
│ │ │ │ │
│ └──────────────────────────────────┼──────────────────┘ │
│ │ │
│ JSON-RPC 2.0 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MCP SERVER │ │
│ │ │ │
│ │ stdio/HTTP transport │ │
│ │ Tool definitions (JSON Schema) │ │
│ │ Tool implementations │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
AspectBehavior
ProtocolJSON-RPC 2.0 over stdio or HTTP
Tool namingmcp__<server>__<tool> convention
Context sharingOnly via tool parameters and return values
LifecycleServer starts on first use, stays alive during session
PermissionsSame system as native tools
LimitationExplanation
Access conversation historyOnly sees tool params, not full context
Maintain state across callsEach call is independent (unless server implements caching)
Modify Claude’s system promptTools only, no prompt injection
Bypass permissionsSame security layer as native tools

→ Cross-reference: See Section 8.6 - MCP Security for security considerations.

Status: Stable (January 26, 2026) Spec: SEP-1865 on GitHub Co-authored by: OpenAI, Anthropic, MCP-UI creators

MCP Apps is the first official extension to the Model Context Protocol, enabling MCP servers to deliver interactive user interfaces alongside traditional tool responses.

The problem solved: Traditional text-based responses create friction for workflows requiring exploration. Each interaction (sort, filter, drill-down) demands a new prompt cycle. MCP Apps eliminates this “context gap” by rendering interactive UIs directly in the conversation.

Two core primitives:

  1. Tools with UI metadata:

    {
    "name": "query_database",
    "description": "Query customer database",
    "_meta": {
    "ui": {
    "resourceUri": "ui://dashboard/customers"
    }
    }
    }
  2. UI Resources (ui:// scheme):

    • Server-side HTML/JavaScript bundles
    • Rendered in sandboxed iframes by host
    • Bidirectional JSON-RPC communication via postMessage

Communication flow:

┌─────────────────────────────────────────────────────────┐
│ MCP APPS ARCHITECTURE │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ MCP Client │◄───────►│ MCP Server │ │
│ │ (Claude/IDE) │ JSON-RPC│ (Your App) │ │
│ └──────┬───────┘ └──────────────┘ │
│ │ │
│ │ Fetches ui:// resource │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Sandboxed Iframe (UI Render) │ │
│ │ ┌───────────────────────────────────┐ │ │
│ │ │ HTML/JS Bundle from Server │ │ │
│ │ │ - Interactive dashboard │ │ │
│ │ │ - Forms with validation │ │ │
│ │ │ - Real-time data visualization │ │ │
│ │ └───────────────────────────────────┘ │ │
│ │ │ │
│ │ postMessage ◄─────► JSON-RPC │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘

Multi-layered protection:

LayerProtection
Iframe sandboxRestricted permissions (no direct system access)
Pre-declared templatesHosts review HTML/JS before rendering
Auditable messagingAll UI-to-host communication via JSON-RPC logs
User consentOptional requirement for UI-initiated tool calls
Content blockingHosts can reject suspicious resources pre-render

→ Cross-reference: See Section 8.6 - MCP Security for broader MCP security considerations.

Installation:

Terminal window
npm install @modelcontextprotocol/ext-apps

Core API (framework-agnostic):

import { App } from '@modelcontextprotocol/ext-apps';
const app = new App();
// 1. Establish communication with host
await app.connect();
// 2. Receive tool results from host
app.ontoolresult = (result) => {
// Update UI with tool execution results
updateDashboard(result.data);
};
// 3. Call server tools from UI
await app.callServerTool('fetch_analytics', {
timeRange: '7d',
metrics: ['users', 'revenue']
});
// 4. Update model context asynchronously
await app.updateModelContext({
selectedFilters: ['region:EU', 'status:active']
});
// Additional capabilities:
app.logDebug('User action', { filter: 'applied' });
app.openBrowserLink('https://docs.example.com');
app.sendFollowUpMessage('Applied filters: EU, Active');

Standard communication: All features operate over postMessage (no framework lock-in).

PlatformMCP Apps SupportNotes
Claude Desktop✅ Available nowclaude.ai/directory (Pro/Max/Team/Enterprise)
Claude Cowork🔄 Coming soonAgentic workflow integration planned
VS Code✅ Insiders buildOfficial blog post
ChatGPT🔄 Rolling outWeek of Jan 26, 2026
Goose✅ Available nowOpen-source CLI with UI support
Claude Code CLI❌ N/ATerminal text-only (no iframe rendering)

Direct usage: None (CLI is text-only, cannot render iframes)

Indirect benefits:

  1. Ecosystem understanding: MCP Apps represents the future of agentic workflows
  2. MCP server development: If building custom MCP servers, Apps is now a design option
  3. Hybrid workflows:
    • Use Claude Desktop to explore data with Apps (dashboards, visualizations)
    • Switch to Claude Code CLI for implementation (scripting, automation)
  4. Context for configuration: MCP servers may advertise UI capabilities in metadata

Official example servers (in ext-apps repository):

  • threejs-server: 3D visualization and manipulation
  • map-server: Interactive geographic data exploration
  • pdf-server: Document viewing with inline highlights
  • system-monitor-server: Real-time metrics dashboards
  • sheet-music-server: Music notation rendering

Production adoption (January 2026):

ToolProviderCapabilities
AsanaAsanaProject timelines, task boards
SlackSalesforceMessage drafting with formatting preview
FigmaFigmaFlowcharts, Gantt charts in FigJam
AmplitudeAmplitudeAnalytics charts with interactive filtering
BoxBoxFile search, document previews
CanvaCanvaPresentation design with real-time customization
ClayClayCompany research, contact discovery
HexHexData analysis with interactive queries
monday.commonday.comWork management boards

Coming soon: Salesforce (Agentforce 360)

MCP Apps standardizes patterns pioneered by:

  • MCP-UI: Early UI extension for MCP (community project)
  • OpenAI Apps SDK: Parallel effort for interactive tools

Both frameworks continue to be supported. MCP Apps provides a unified specification (SEP-1865) co-authored by maintainers from both ecosystems plus Anthropic and OpenAI.

Migration path: Straightforward for existing MCP-UI and Apps SDK implementations.

Decision tree for MCP server developers:

Building a custom MCP server?
├─ Users need to SELECT from 50+ options? → MCP Apps (dropdown, multi-select UI)
├─ Users need to VISUALIZE data patterns? → MCP Apps (charts, maps, graphs)
├─ Users need MULTI-STEP workflows with conditional logic? → MCP Apps (wizard forms)
├─ Users need REAL-TIME updates? → MCP Apps (live dashboards)
└─ Simple data retrieval or actions only? → Traditional MCP tools (sufficient)

Trade-off: UI complexity and implementation effort vs. user experience improvement.


Source category: Tier 1, Official; bounded by the cited version/date and scope. Source: anthropic.com/engineering/advanced-tool-use

Since v2.1.7 (January 2026), Claude Code uses lazy loading for MCP tool definitions instead of preloading all tools into context. This is powered by Anthropic’s Advanced Tool Use API feature.

The problem solved:

  • MCP tool definitions consume significant context (e.g., GitHub MCP alone: ~46K tokens for 93 tools)
  • Developer Scott Spence documented 66,000+ tokens consumed before typing a single prompt
  • This “context pollution” limited practical MCP adoption

How Tool Search works:

┌─────────────────────────────────────────────────────────────┐
│ MCP TOOL SEARCH FLOW │
├─────────────────────────────────────────────────────────────┤
│ │
│ WITHOUT Tool Search (eager loading): │
│ ┌──────────────────────────────────────────────────────┐ │
│ │All 100+ tool definitions loaded upfront (~55K tokens)│ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ WITH Tool Search (lazy loading): │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Step 1: Only search tool loaded (~500 tokens) │ │
│ │ Step 2: Claude determines needed capability │ │
│ │ Step 3: Tool Search finds matching tools (regex/BM25)│ │
│ │ Step 4: Only matched tools loaded (~600 tokens each) │ │
│ │ Step 5: Tool invoked normally │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ Result: 55K tokens → ~8.7K tokens (85% reduction) │
│ │
└─────────────────────────────────────────────────────────────┘

Measured improvements (Anthropic benchmarks):

MetricBeforeAfterImprovement
Token overhead (5-server setup)~55K~8.7K85% reduction
Opus 4 tool selection accuracy49%74%+25 points
Opus 4.5 tool selection accuracy79.5%88.1%+8.6 points
Opus 4.6 adaptive thinkingN/AAuto-calibratedDynamic depth

Configuration (v2.1.9+):

Terminal window
# Environment variable
ENABLE_TOOL_SEARCH=auto # Default (10% context threshold)
ENABLE_TOOL_SEARCH=auto:5 # Aggressive (5% threshold)
ENABLE_TOOL_SEARCH=auto:20 # Conservative (20% threshold)
ENABLE_TOOL_SEARCH=true # Always enabled
ENABLE_TOOL_SEARCH=false # Disabled (eager loading)
ThresholdRecommended for
auto:20Lightweight setups (5-10 tools)
auto:10Balanced default (20-50 tools)
auto:5Power users (100+ tools)

→ As Simon Willison noted: “Context pollution is why I rarely used MCP. Now that it’s solved, there’s no reason not to hook up dozens or even hundreds of MCPs to Claude Code.” (via X/Twitter, January 14, 2026)


Source category: Tier 1, Official Anthropic Engineering; bounded by the cited version/date and scope. Source: Anthropic Engineering: Advanced Tool Use | Programmatic Tool Calling Docs

Four API-level features released as generally available on February 18, 2026 (with Opus/Sonnet 4.6). These are relevant to developers building agents on the Anthropic API or Agent SDK. They are not available directly in the Claude Code CLI.

FeatureProblem SolvedAvailability
Programmatic Tool Calling (PTC)Agent loops burn tokens on round tripsAPI + Foundry
Dynamic FilteringWeb search bloats context with noiseAPI + Foundry
Tool Search ToolToo many tool definitions bloat contextAPI + Foundry
Tool Use ExamplesSchema alone can’t express usage patternsAPI + Foundry

Strategic layering: address your biggest bottleneck first:

  • Context bloated by tool definitions → Tool Search Tool
  • Large intermediate results → Programmatic Tool Calling
  • Web research returning noise → Dynamic Filtering
  • Parameter errors despite correct schema → Tool Use Examples

The paradigm shift: instead of calling tools one at a time with a full model round trip each, Claude writes Python code that orchestrates all tool calls internally. Only the final stdout enters the context window.

Traditional: prompt → Claude → tool 1 → response 1 → Claude → tool 2 → response 2 → Claude → answer
(3 tools = 3 inference passes, 3× intermediate results in context)
PTC: prompt → Claude → writes Python → code calls tool 1, 2, 3 → stdout → Claude → answer
(3 tools = 1 inference pass, only final output in context)

Configuration: mark tools callable from the code execution sandbox with allowed_callers:

{
"tools": [
{ "type": "code_execution_20250825", "name": "code_execution" },
{
"name": "query_database",
"description": "Execute SQL. Returns rows as JSON: id (str), name (str), revenue (float).",
"input_schema": {
"type": "object",
"properties": { "sql": { "type": "string" } },
"required": ["sql"]
},
"allowed_callers": ["code_execution_20250825"]
}
]
}
allowed_callers valueBehavior
omitted / ["direct"]Traditional calling only
["code_execution_20250825"]Callable from Python sandbox only
["direct", "code_execution_20250825"]Both modes, not recommended (confuses Claude)

Patterns (all run in 1 inference pass):

  • Batch processing: loop over N items, aggregate, print summary
  • Early termination: break as soon as success criteria are met
  • Conditional tool selection: pick lightweight vs heavy tool based on intermediate result
  • Data filtering: reduce what Claude sees (errors = [l for l in logs if "ERROR" in l])

Token efficiency: tool results from programmatic calls never enter Claude’s context; only final stdout does. 10 programmatic tool calls ≈ 1/10th the context tokens of 10 direct calls. The ~37% overall token reduction claim is community-reported (Shayan Tabe’s analysis) and not officially confirmed by Anthropic.

Constraints: API and Foundry only (not Bedrock/Vertex). No MCP tools, no web search/fetch, no strict: true tools. Container lifetime ~4.5 minutes. Not covered by Zero Data Retention.

Web search and fetch tools dump full HTML into context: navigation, ads, boilerplate included. Dynamic Filtering lets Claude write Python to pre-process and filter results before they enter its context window.

Configuration: use updated tool type versions with a beta header:

{
"tools": [
{ "type": "web_search_20260209", "name": "web_search" },
{ "type": "web_fetch_20260209", "name": "web_fetch" }
]
}

Header required: anthropic-beta: code-execution-web-tools-2026-02-09. Filtering is enabled by default when using these tool type versions with Sonnet 4.6 or Opus 4.6.

Official benchmark results (Anthropic, BrowseComp dataset):

ModelWithout FilteringWith FilteringImprovement
Sonnet 4.633.3%46.6%+13.3 pp
Opus 4.645.3%61.6%+16.3 pp

Average input token reduction: ~24%. Best suited for multi-step research, citation verification, and extracting specific data points from large pages.

JSON schemas define structure but can’t express when to include optional parameters, which combinations make sense, or format conventions. Add input_examples to tool definitions to show concrete usage patterns:

{
"name": "create_ticket",
"input_schema": { ... },
"input_examples": [
{ "title": "Login page 500 error", "priority": "critical", "assignee": "oncall-team", "labels": ["bug", "auth"] },
{ "title": "Add dark mode", "priority": "low", "labels": ["feature-request"] },
{ "title": "Update API docs for v2" }
]
}

Accuracy on complex parameter handling: 72% → 90% in Anthropic’s benchmarks. Use 1-5 realistic examples per tool, covering minimal, partial, and full specifications.

FeatureClaude Code CLIAction for CLI users
Tool Search (MCP lazy loading)Built-in since v2.1.7 as MCPSearch auto modeTune ENABLE_TOOL_SEARCH=auto:N (documented in §6 above)
Tool Use ExamplesNot configurable from CLIRelevant for custom MCP server authors; add input_examples to tool schemas
Programmatic Tool CallingNot available in CLIRelevant for Agent SDK developers building custom agents
Dynamic FilteringNot available in CLIRelevant for Agent SDK users doing web research pipelines

Source category: Tier 2, Verified through behavior; limited to the cited observation and method. Sources:

The Edit tool is more sophisticated than it appears.

┌─────────────────────────────────────────────────────────────┐
│ EDIT TOOL FLOW │
├─────────────────────────────────────────────────────────────┤
│ │
│ Input: old_string, new_string, file_path │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ Step 1: EXACT MATCH │ │
│ │ Search for literal old_string │ │
│ └────────────────┬─────────────────────┘ │
│ │ │
│ Found? ────┴──── Not found? │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────────────┐ │
│ │ REPLACE │ │ Step 2: FUZZY │ │
│ │ (done) │ │ MATCH │ │
│ └──────────┘ └────────┬─────────┘ │
│ │ │
│ Found? ────┴──── Not found? │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ REPLACE │ │ ERROR │ │
│ │ + WARN │ │ (mismatch) │ │
│ └──────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

When exact match fails, the Edit tool attempts:

  1. Whitespace normalization: Ignore trailing spaces, normalize indentation
  2. Line ending normalization: Handle CRLF vs LF differences
  3. Context expansion: Use surrounding lines to locate the right spot

If fuzzy matching also fails, the tool returns an error asking Claude to verify the old_string.

Before applying changes, the Edit tool:

CheckPurpose
File existsPrevent creating files via Edit
old_string foundEnsure we’re editing the right place
Single matchold_string must be unique (or use replace_all)
New content differsPrevent no-op edits
ErrorCauseClaude’s Response
”old_string not found”Content changed since last readRe-reads file, tries again
”Multiple matches”old_string isn’t uniqueUses more context lines
”File not found”Wrong pathSearches for correct path

Source category: Tier 1, Official; bounded by the cited version/date and scope. Source: code.claude.com/docs

Sessions can be resumed across terminal sessions.

CommandBehavior
claude --continue / claude -cResume most recent session
claude --resume <id> / claude -r <id>Resume specific session by ID
PersistedNot Persisted
Conversation historyLive tool state
Tool call resultsPending operations
Session IDFile locks
Working directory contextEnvironment variables

Source category: Tier 3, Inferred; unverified explanation.

Sessions appear to be stored as JSON/JSONL files in ~/.claude/ but:

  • Format is not publicly documented
  • Not intended as a stable API
  • May change between versions

Do not rely on session file format for external tooling.


10. Philosophy: Less scaffolding, more model

Section titled “10. Philosophy: Less scaffolding, more model”

Source category: Tier 1, Official; bounded by the cited version/date and scope. Source: Daniela Amodei (Anthropic Co-founder & President) - Public statements

The core philosophy behind Claude Code:

“Do more with less. Smart architecture choices, better training efficiency, and focused problem-solving can compete with raw scale.”

Traditional ApproachClaude Code Approach
Intent classifier → Router → SpecialistModel-driven actions subject to permission controls
RAG with embeddingsGrep + Glob (regex search)
DAG task orchestrationCentral agentic loop; optional workflows and delegation
Tool-specific plannersModel-driven tool selection
Complex state machinesConversation as state
Prompt engineering frameworksTrust the model
  1. Model capability: Claude 4+ is capable enough to handle routing decisions
  2. Reduced latency: Fewer components = faster response
  3. Simpler debugging: When something fails, there’s one place to look
  4. Better generalization: No hand-coded rules to break on edge cases
AdvantageDisadvantage
SimplicityLess fine-grained control
FlexibilityHarder to enforce strict behaviors
Fewer bugsModel errors affect everything
Fast iterationRequires good model quality

The “native capabilities first” approach is increasingly validated by external practitioners. Embedded engineering teams (including former Cursor power users) converge on Agent Skills standard over external orchestration frameworks, demonstrating the viability of trusting Claude’s native reasoning over adding scaffolding layers.

Example: Gur Sannikov (embedded engineering) adopted ADR-driven workflows using only native Claude Code capabilities (hooks, skills, Task Tool) without external frameworks, validating the architectural philosophy documented in this guide.

This convergence suggests that the “less scaffolding, more model” approach scales beyond initial expectations, even for complex engineering domains like embedded systems development.


Source category: Tier 2, Based on March 2026 fact-checked data; limited to the cited observation and method. Sources: Official documentation, Perplexity research March 2026, vendor changelogs

DimensionClaude CodeGitHub CopilotCursorAmazon Q Developer
Architecturewhile(tool) loopIDE agent + cloud coding agentEvent-driven + cloudAWS-integrated agents
ExecutionLocal terminalLocal (agent mode) + cloud VMsLocal + cloudCloud/local hybrid
ModelClaude (single provider)GPT, Claude, Codex (selectable)Multiple (adaptive)Amazon Titan + others
ContextModel and configuration dependent (200K or 1M tokens)Full codebase (agent mode)Codebase-aware (Composer)Varies (AWS-scoped)
TransparencyHigh (visible reasoning)MediumMediumLow
CustomizationCLAUDE.md + hooks + MCPAGENTS.md, MCP (GA), custom agentsMCP Apps, .cursorrulesMCP (native), AWS integration
MCP SupportNativeYes (GA, auto-approve)Yes (MCP Apps v2.6)Yes (native)
PricingPro $20 / Max $100-200Free / Pro $10 / Pro+ $39 / Biz $19/seatFree / Pro $20 / Biz $40/seatFree / Pro $19/seat / Enterprise
ScenarioClaude CodeAlternative
Deep codebase explorationExcellentGood
Terminal-native workflowExcellentLimited
Custom automation (hooks)ExcellentLimited
Team standardizationGood (CLAUDE.md)Varies
IDE integrationLimited (VS Code ext)Cursor/Copilot better
Enterprise complianceVia Anthropic enterpriseVaries

SourceURLTopics
Engineering Bloganthropic.com/engineering/claude-code-best-practicesMaster loop, philosophy
Setup Docscode.claude.com/docs/en/setupInstall, auth, release channels
Commands Referencecode.claude.com/docs/en/commandsSource of truth for every built-in slash command, aliases, bundled skills and workflows
CLI Referencecode.claude.com/docs/en/cli-referenceLaunch-time flags and subcommands
Context Windowsplatform.claude.com/docs/en/build-with-claude/context-windowsToken limits
Hooks Referencecode.claude.com/docs/en/hooksHook system
Hooks Guidecode.claude.com/docs/en/hooks-guideHook examples
MCP Docscode.claude.com/docs/en/mcpMCP integration
Sandboxingcode.claude.com/docs/en/sandboxingSecurity model
llms.txt (index)code.claude.com/docs/llms.txtLLM-optimized doc index, ~65 pages
llms-full.txtcode.claude.com/docs/llms-full.txtFull documentation (~98 KB text)
SourceURLTopics
PromptLayer Analysisblog.promptlayer.com/claude-code-behind-the-scenes-of-the-master-agent-loop/Internal architecture
Steve Kinney Coursestevekinney.com/courses/ai-development/claude-code-*Permissions, sessions
SourceTopics
GitHub Issues (anthropics/claude-code)Edge cases, bugs, feature discussions
Reddit r/ClaudeAIUser experiences, workarounds
YouTube tutorialsVisual walkthroughs

Transparency about gaps in our understanding:

TopicWhat We Don’t KnowConfidence in Current Understanding
Exact compaction thresholdIs it 75%? 85%? 92%? Varies by model?40%
System prompt contentsFull text not public, varies by model version30%
Token counting methodExact tokenizer, overhead for tool schemas50%
Model fallbackDoes Claude Code fallback if a model fails?20%
Internal cachingIs there result caching between sessions?20%
Rate limiting logicHow rate limits are applied per-tool40%

These are intentionally not documented by Anthropic:

  • Session file format (internal implementation detail)
  • System prompt variations between models
  • Internal component names/architecture
  • Token usage breakdown per component
  • Exact permission evaluation order
  1. Official changelog: Watch anthropic.com/changelog
  2. GitHub releases: github.com/anthropics/claude-code/releases
  3. Community Discord: Various Claude-focused servers
  4. This guide: Updated periodically based on verified information

Found an error? Have verified new information? Contributions welcome:

  1. For official facts: Cite the Anthropic source
  2. For observations: Describe how you verified the behavior
  3. For corrections: Explain what’s wrong and why

Last updated: February 2026 Claude Code version: v2.1.34 Document version: 1.1.0


Three API-level features that architects must understand for production systems: the Message Batches API for cost-optimized bulk processing, tool_choice for guaranteed structured output, and strict-mode JSON schema enforcement.


The Batches API submits up to 100 messages in a single HTTP request and processes them asynchronously within a 24-hour window. The cost is 50% of the synchronous rate: same quality, half the price, at the cost of latency.

When to use it:

Use caseSync APIStreamingBatch API
Interactive chatyesyesno
Real-time analysisyesyesno
Bulk document processingnonoyes (50% cheaper)
Multi-turn tool loopsyesyesno (not supported)
Nightly classification pipelinenonoyes
Large-scale data extractionnonoyes

The Batches API does not support multi-turn conversations or tool_use continuation across turns. Each request in a batch is a single stateless call.

Submit, poll, retrieve:

import anthropic
import time
client = anthropic.Anthropic()
batch = client.messages.batches.create(
requests=[
{
"custom_id": f"doc-{i}",
"params": {
"model": "claude-opus-5-5",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": f"Classify this document: {doc}"}
]
}
}
for i, doc in enumerate(documents)
]
)
# Poll until done (processing_status: "in_progress" | "ended")
while batch.processing_status == "in_progress":
time.sleep(60)
batch = client.messages.batches.retrieve(batch.id)
# Stream results — each entry has a custom_id and a result
for result in client.messages.batches.results(batch.id):
match result.type:
case "succeeded":
output = result.message.content[0].text
process(result.custom_id, output)
case "errored":
log_error(result.custom_id, result.error.error.message)
case "expired":
requeue(result.custom_id)

Results stay available for 29 days after the batch ends, then are deleted automatically.

Error handling at scale:

Per-request errors do not fail the entire batch. A batch with 100 requests where 3 fail still returns 97 successful results. The pattern for resilient pipelines:

  1. Process all succeeded results immediately.
  2. Collect errored custom_ids for retry with exponential backoff.
  3. Treat expired as a soft failure: the request never ran, so requeue it.

Retry economics:

Retrying individual failed items synchronously costs 2x the batch rate. If your error rate is below 5%, retrying synchronously is still net-cheaper than splitting batches further. Above 10% error rate, investigate the prompt before retrying at all.


tool_choice governs whether and which tools the model can call. Four modes:

ValueBehavior
{"type": "auto"}Model decides; may or may not call tools (default)
{"type": "any"}Model must call at least one tool from the provided list
{"type": "tool", "name": "X"}Model must call tool X specifically
{"type": "none"}No tool calls allowed; model responds in prose

The any and specific-tool modes request a tool call where supported. Inspect stop_reason and the returned blocks; a refusal or output limit is not proof that the model ignored an instruction.

Forcing a tool is model-dependent. Check thinking compatibility before using any or a named tool. Do not infer success from the requested choice alone: handle refusals, output limits, and the actual response blocks. For schema-constrained JSON, use the dedicated format below.

Structured outputs are generally available. Use output_config.format for JSON responses, or strict: true at the tool-definition level for validated tool arguments. The old beta header and output_format examples are obsolete. Official structured outputs documentation.

import json
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
output_config={"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"vendor_name": {"type": ["string", "null"]},
"total_amount": {"type": ["number", "null"]},
},
"required": ["vendor_name", "total_amount"],
"additionalProperties": False,
},
}},
messages=[{"role": "user", "content": invoice_text}],
)
if response.stop_reason != "end_turn":
raise RuntimeError(f"Incomplete or refused extraction: {response.stop_reason}")
text = next(block.text for block in response.content if block.type == "text")
fields = json.loads(text)

For tools, strict sits alongside name, description, and input_schema, not inside the schema. Schema conformance does not establish semantic accuracy. Validate extracted values against the document and handle refusals or truncated output before consuming the result.

Nullable fields prevent hallucination of defaults:

Without nullable, the model must fill every required field and will invent a value rather than leave it empty. Nullable fields give the model an explicit out:

"vendor_name": {"type": ["string", "null"]}

The model returns null when the field cannot be found, rather than guessing.

Extensible enums with companion fields:

Closed enums break when inputs don’t fit any category. The solution: add "other" as the last enum value and a companion detail field:

{
"document_type": {
"type": "string",
"enum": ["invoice", "purchase_order", "receipt", "credit_note", "other"]
},
"document_type_detail": {
"type": ["string", "null"],
"description": "Populate when document_type is 'other'; describe the actual document type"
}
}

This preserves the type-safety of the enum for the 95% case while capturing the 5% gracefully.

detected_pattern for false-positive analysis:

In classification pipelines, a detected_pattern field surfaces the evidence the model used. This turns opaque classifications into debuggable decisions:

{
"is_complaint": {"type": "boolean"},
"detected_pattern": {
"type": ["string", "null"],
"description": "Quote the specific phrase or pattern that triggered the classification"
},
"confidence": {"type": "number"}
}

When is_complaint: true with detected_pattern: "your service is terrible", a human reviewer can validate the classification in seconds. When detected_pattern: null and confidence: 0.6, that is a signal to escalate for manual review rather than auto-process.

  • Examples - ready-to-use Claude Code templates
  • Workflows - end-to-end workflow guides