Skip to main content

Key Design Patterns & Engineering Practices

This chapter summarizes the recurring design patterns and engineering practices found throughout the Claude Code source, helping you understand its design philosophy.

1. Async Generator Pipeline

The most fundamental architectural pattern -- nearly all data flows use async generators.

// Producer
async function* query(params): AsyncGenerator<StreamEvent | Message, Terminal> {
for await (const event of callModel(...)) {
yield event;
}
yield* runTools(...);
}

// Consumer
for await (const event of query(params)) {
onQueryEvent(event);
}

Used in: query(), queryModelWithStreaming(), runAgent(), runToolUse(), runTools().

Why: Incremental delivery (stream to UI immediately), backpressure control (consumer controls pace), composability (yield* nests generators seamlessly), cancellation propagation (.return() propagates through the chain).

2. Explicit State Machine

queryLoop is not a simple while-true but a state machine with explicit state and transitions.

type State = {
messages: Message[]
turnCount: number
transition: Continue | undefined // why previous iteration continued
// ...
}

// Each continue site replaces entire state
state = { ...state, messages: newMessages, transition: { reason: 'tool_use' } };
continue;

Benefits: State changes are centrally visible, tests can assert transition reasons, no implicit state leakage.

3. Dependency Injection

Core external dependencies are injected via QueryDeps for testability:

type QueryDeps = {
callModel: typeof queryModelWithStreaming
microcompact: typeof microcompactMessages
autocompact: typeof compactConversation
uuid: () => string
}

Scoped intentionally -- only for query loop core dependencies, not a global DI container.

4. Factory + Defaults

Tools are built via buildTool() with safe defaults:

const TOOL_DEFAULTS = {
checkPermissions: () => ({ result: 'allow' }),
isConcurrencySafe: false,
isReadOnly: () => false,
};

export function buildTool(def) { return { ...TOOL_DEFAULTS, ...def }; }

New tools only define necessary fields; defaults are safe (not concurrent, not read-only).

5. Layered Config Merge

Multi-source configs merge by priority, supporting user to enterprise override:

userSettings < projectSettings < localSettings < flagSettings < policySettings

Security-related settings (permission rules) use merge semantics rather than override.

6. React in Terminal

Declarative UI paradigm for managing complex terminal UI state:

React Component Tree -> react-reconciler -> Yoga Layout (Flexbox)
-> Cell Buffer (character grid) -> TTY Diff (delta output to terminal)

Benefits: declarative UI, hook ecosystem, component reuse, familiar programming model.

7. Tool Batch Partitioning

Tool execution balances concurrency and safety via partitioning:

  • Concurrent-safe batch: isConcurrencySafe: true tools (FileRead, Glob, Grep) run in parallel
  • Serial batch: isConcurrencySafe: false tools (FileWrite, Bash) run sequentially

StreamingToolExecutor overlaps tool execution with LLM streaming.

8. File-Based Mailbox

Swarm teammates use filesystem JSON inboxes for inter-process communication:

.claude/teams/<session>/inboxes/<agent-id>.json

Why files over IPC: Cross-process (tmux/iTerm teammates are separate processes), persistent (survive crashes), simple (no socket connections), observable (can inspect files for debugging).

9. Compile-Time Dead Code Elimination

bun:bundle's feature() completely removes disabled code paths at compile time:

const SleepTool = feature('PROACTIVE')
? require('./tools/SleepTool/SleepTool.js').SleepTool
: null;

Notable flags: PROACTIVE, KAIROS, BRIDGE_MODE, DAEMON, VOICE_MODE, AGENT_TRIGGERS, REACTIVE_COMPACT, MCP_SKILLS.

10. Parallel Prefetch

Startup leverages ES module side effects to run expensive I/O in parallel with module loading:

profileCheckpoint('main_tsx_entry');
startMdmRawRead(); // Start MDM subprocess
startKeychainPrefetch(); // Start Keychain reads
// Subsequent ~135ms of imports run in parallel with above I/O

Memory prefetch uses using syntax for guaranteed cleanup on all exit paths.

11. Prompt Cache Boundary

SYSTEM_PROMPT_DYNAMIC_BOUNDARY in the system prompt optimizes Anthropic API's prompt caching: static content before the boundary is cacheable across turns, while dynamic content after it changes freely.

12. Session-Scoped Section Cache

Dynamic system prompt sections are computed once and cached per session:

systemPromptSection('memory_instructions', () => loadMemoryPrompt())
// Computed once, cached until /clear or compact

DANGEROUS_uncachedSystemPromptSection('env', () => getEnvInfo())
// Always recomputed (name warns about performance)

Design Philosophy Summary

PrincipleManifestation
Incremental deliveryFull-chain async generators, UI responds immediately
Safe defaultsTools default to non-concurrent, permissions default to ask
TestabilityQueryDeps DI, VCR recording/playback
Performance firstParallel prefetch, compile-time elimination, prompt cache
Clear layeringEntry -> Core -> Service -> UI -> Infrastructure
Extension friendlyPlugins, skills, MCP, custom agent types
Progressive complexitySimple cases are simple (single tool), complex cases composable (swarm)

To deeply understand a specific pattern:

  1. Async Generator Pipeline: Start from queryLoop in query.ts, follow yield* to callModel and runTools
  2. State Machine: Read the State type in query.ts, then search all continue sites
  3. Tool System: Start from Tool.ts interface, then checkPermissionsAndCallTool in toolExecution.ts
  4. React in Terminal: Start from the Ink class in ink/ink.tsx
  5. Config Merge: Start from SETTING_SOURCES in settings/constants.ts, then settings.ts

Congratulations on completing the full Claude Code source tutorial! You should now have a systematic understanding of the architecture, core loop, tool system, security model, and engineering practices.

Hands-on Experiment

This chapter has a corresponding Python experiment:

Lab 16 — Design Patterns

Covers: 6 patterns cookbook (async generators, immutable state, DI, factory, config merge, batch partitioning)

cd experiments && python -m exp_16_design_patterns.main --mock