
The Anatomy of Claude Code's Architecture
Model reasons; the harness enforces. ~1.6% of Claude Code is AI decision-making; 98.4% is infrastructure. A one-pager on the agent loop, permissions, context shapers, tools, subagents, and session persistence.
Model reasons; the harness enforces. Roughly 1.6% of the logic is AI
decision-making; 98.4% is infrastructure. The core agent loop is a simple
while-loop - almost everything that makes Claude Code safe, resumable, and
extensible lives in the systems around it. A single queryLoop powers every
interface (CLI, headless, SDK, IDE).
TL;DR: Claude Code is less a chat wrapper than an operating harness: one execution engine for every surface, deny-first permissions, aggressive context management under a ~200K-token ceiling, and append-only session transcripts that favor auditability over query power. This one-pager maps seven system components, the nine-step turn pipeline, five pre-model context shapers, the permission stack, extensibility injection points, subagent delegation, and how sessions survive resume without replaying trust.
1 · System at a Glance - 7 Components
User → Interfaces → Agent Loop, with three systems hanging off the loop: Permission System (allow / ask / deny), Tools (tool results), and State & Persistence (load / persist) - all reaching the Execution Environment (files / shell / web / MCP).
| # | Component | Role |
|---|---|---|
| 1 | User | Submits prompts, approves permissions, reviews output |
| 2 | Interfaces | Interactive CLI, headless (claude -p), Agent SDK, IDE / Desktop / Browser |
| 3 | Agent Loop | queryLoop async generator: model call → tool dispatch → result → repeat |
| 4 | Permission System | Deny-first rules + auto-mode ML classifier + hook interception |
| 5 | Tools | Up to 54 built-in + MCP, assembled via assembleToolPool |
| 6 | State & Persistence | Append-only JSONL transcripts, prompt history, subagent sidechains |
| 7 | Execution Environment | Shell (sandboxed), filesystem, web fetch, MCP connections |
Four design questions every coding agent must answer - Claude Code's answers: Reasoning lives in the model (the harness enforces) · one execution engine for all surfaces · default safety is deny-first · the binding constraint is the ~200K-token context window.
2 · The Turn Loop - 9-Step Pipeline
Runtime turn flow:
- Settings resolution
- State init
- Context assembly
- Five pre-model shapers
- Model call
- Tool dispatch
- Permission gate
- Tool execution (sync / subagent / background)
- Stop-condition check
On deny, deny feedback loops back for more iterations. The turn ends with no tool use → assistant response.
Recovery: max-output-token escalation (≤3 retries/turn) · reactive compaction (≤once/turn) · prompt-too-long → context-collapse overflow → reactive compaction → terminate · streaming and fallback-model switching.
3 · Context Construction & the 5 Pre-Model Shapers
Five context shapers run sequentially before every model call, cheapest first:
| Stage | Strategy | Trigger |
|---|---|---|
| Budget Reduction | Per-message size caps | Always active |
| Snip | Trim older history | Feature-gated (HISTORY_SNIP) |
| Microcompact | Cache-aware fine-grained compression | Always (time-based) |
| Context Collapse | Read-time virtual projection (non-destructive) | Feature-gated (CONTEXT_COLLAPSE) |
| Auto-Compact | Full model-generated summary (last resort) | When all else fails |
9 ordered context sources: System prompt → Environment info → CLAUDE.md hierarchy → Path-scoped rules → Auto-memory → Tool metadata → Conversation history → Tool results → Compact summaries.
CLAUDE.md hierarchy (4 levels): Managed (/etc/claude-code/) · User
(~/.claude/) · Project (CLAUDE.md, .claude/rules/*.md) · Local
(CLAUDE.local.md, gitignored).
Critical choice: CLAUDE.md is user context (probabilistic compliance), not system prompt - permission rules provide the deterministic enforcement layer.
File-based memory: no embeddings / no vector DB - an LLM scans memory-file headers and selects ≤5 relevant files on demand. Fully inspectable, editable, and version-controllable.
4 · Permission System - Deny-First
Tool use → Policy Core (Rules · Modes · Hooks) → decision: Deny (denied result) / Allow (execute) / Ask (user or auto-classifier). Deny always overrides allow, even when allow is more specific.
7 permission modes (trust ↑): plan · default · acceptEdits · auto
(ML classifier) · dontAsk · bypassPermissions · bubble (internal
subagent escalation).
Seven independent safety layers - a request must pass all applicable ones:
- Tool pre-filtering (denied tools removed from the model's view)
- Deny-first rule evaluation
- Permission-mode constraints
- Auto-mode ML classifier (separate LLM safety call)
- Shell sandboxing (filesystem + network isolation)
- Non-restoration on resume (permissions never persist across sessions)
- Hook-based interception (PreToolUse hooks modify / block)
5 · Tools & Extensibility - 3 Injection Points
Tool pool assembly (5 steps): Base enumeration (≤54) → Mode filtering → Deny pre-filtering → MCP integration → Deduplication.
Four extension mechanisms (graduated context cost):
| Mechanism | Cost | Capability |
|---|---|---|
| Hooks | Zero | 27 events · 4 execution types (shell, LLM, webhook, subagent verifier) |
| Skills | Low | SKILL.md (15+ frontmatter fields), injected via SkillTool meta-tool |
| Plugins | Medium | 10 component types (commands, agents, skills, hooks, MCP, LSP, styles…) |
| MCP Servers | High | External tools via 7 transports (stdio, SSE, HTTP, WebSocket, SDK, IDE) |
Three injection points:
assemble()- what the model seesmodel()- what it can reachexecute()- whether / how an action runs
6 · Subagent Delegation
SkillTool vs AgentTool: SkillTool injects instructions into the current context (cheap, same window); AgentTool spawns a new isolated context window (≈7× tokens, but context-safe).
6 built-in types (+ custom .claude/agents/*.md): Explore · Plan ·
General-purpose · Claude Code Guide · Verification · Statusline-setup.
3 isolation modes: Worktree (git filesystem isolation) · Remote (internal-only) · In-process (default) - shared filesystem, isolated conversation.
Sidechains: each subagent writes its own .jsonl; only the summary
returns to the parent - full history never enters parent context.
Multi-instance coordination via POSIX flock(), zero external deps.
7 · Session Persistence
3 persistence channels:
| Channel | Purpose |
|---|---|
| Session transcripts | Append-only JSONL, chain-patched at compaction boundaries |
| Global prompt history | history.jsonl, reverse-read for ↑-arrow recall |
| Subagent sidechains | Separate JSONL per subagent |
Compaction flow: remove old tool outputs → generate session summary → mark compact boundary. Checkpoints enable Rewind / Resume / Fork.
Safety: permissions are never restored on resume - trust is re-established each session (accepted friction to keep the invariant). Trade-off: append-only JSONL favors auditability and simplicity over query power - every event is human-readable and reconstructable without special tooling.