Inside Claude Code: How Anthropic Built a Secure, Scalable Local Agent Runtime
This article dissects Claude Code’s open‑source repository, revealing how its startup sequence, context assembly, main loop, tool contracts, permission pipeline, and long‑task handling are engineered layer by layer to create a performant, secure local AI agent runtime.
When Claude Code’s source was leaked, the community rushed to examine the implementation. Unlike the model weights, the disclosed code reveals the engineering of a local Agent Runtime, showing how Anthropic structures startup, context composition, the main loop, tool contracts, and permission handling.
Key Takeaways (TL;DR)
The leak contains only the implementation layer, not the model itself.
The most valuable path is not a feature list but the chain: startup → context assembly → main loop → tool contracts → permission pipeline → long‑task continuation. src/main.tsx shows the runtime is optimized for long‑term interaction, not a one‑off CLI. src/constants/prompts.ts and src/utils/queryContext.ts treat prompts as an assembly layer rather than static text. src/QueryEngine.ts, src/utils/processUserInput/processUserInput.ts, and src/query.ts form the core execution chain.
Tool definitions ( src/Tool.ts, src/tools.ts, src/tools/FileEditTool/*) expose Anthropic’s “read‑then‑write” and conservative default safety policies. src/utils/permissions/permissions.ts implements a multi‑stage permission decision pipeline.
Context compression operates in three tiers (microcompact, autocompact, full compression) and separates long‑task memory from session state.
High permissions increase attack surface: hooks, MCP, and Skill entries can be poisoned for silent remote code execution.
Establishing the Boundary
The leak makes it clear that the value lies in Claude Code’s product implementation, not the Claude model itself. Understanding the system’s boundaries prevents the discussion from drifting into two unhelpful directions: treating the system as a mysterious model extension or as a mere feature catalog.
From an engineering perspective, the focus should be on how the runtime collects context, orchestrates the main loop, constrains tools, manages long tasks, and mitigates risk in a high‑privilege local environment.
Follow the Main Execution Chain
main.tsx– Parallelizes startup tasks (profile checkpoint, MDM read, keychain prefetch) to reduce launch latency. QueryEngine.submitMessage() – Prepares cwd, tools, commands, MCP clients, thinking config, budget, and session state, then fetches system prompts. fetchSystemPromptParts() – Assembles system, user, and custom prompts, caching each component. processUserInput() – Handles slash commands, attachments, IDE selections, and executes executeUserPromptSubmitHooks() for possible interception. query.ts – Drives the Agent Loop: message preparation, tool invocation, token budgeting, stop hooks, continuation, and compact decisions.
Tool system executes read, write, search, command, and MCP actions.
Permission system participates at tool, rule, and mode layers, forming a governance pipeline.
When context grows too large, the system triggers compacting; long‑task state is handed off to a memory subsystem for continuation.
Understanding this chain clarifies why Claude Code feels “heavy” – the complexity is distributed across state management rather than isolated in a single module.
Prompt Assembly as a Runtime Layer
Prompts are not static strings. getSystemPrompt() builds them section‑by‑section, separating static prefixes ( SYSTEM_PROMPT_DYNAMIC_BOUNDARY) from dynamic parts. fetchSystemPromptParts() caches three key pieces: defaultSystemPrompt, userContext, and systemContext. This design emphasizes reuse, per‑turn perception, and clear delineation between session and system context.
Each tool also carries its own prompt.ts, embedding safety protocols such as the “Git Safety Protocol” in BashTool/prompt.ts, which are read by the AI rather than human users.
Tool System: Declaring Boundaries First
Tools are defined with explicit safety attributes ( isReadOnly, isConcurrencySafe, isDestructive, needsUserInteraction, checkPermissions). The default values are conservative (both isReadOnly and isConcurrencySafe default to false), ensuring that any tool lacking a clear declaration is treated as potentially unsafe.
File editing tools illustrate this approach: FileEditTool/prompt.ts mandates a prior read operation, and FileEditTool.ts normalizes paths, checks permissions, blocks denied directories, protects large files, and handles missing or ambiguous content.
Permission Pipeline: More Than a Popup
The permission file ( src/utils/permissions/permissions.ts) implements a multi‑stage decision process:
Check deny list.
Check ask list.
Invoke tool‑specific checkPermissions.
Apply content‑level ask rules and safety checks.
Consider current mode (e.g., bypassPermissions).
Apply always‑allow overrides.
Consolidate into final passthrough decision.
This pipeline can be extended with classifiers, hooks, MCP rule matching, and denial tracking, making it a continuously governable security layer.
Long‑Task Management: Compact + Memory
Claude Code separates history compression from state continuation. Three compression levels exist:
Microcompact – Removes old tool results while preserving the main dialogue thread.
Autocompact – Triggers automatically when token usage reaches ~87% of the context window.
Full compression – Generates a concise summary and replaces the entire history, with a strict “TEXT ONLY” directive to avoid further tool calls.
Memory services ( src/services/extractMemories/prompts.ts and src/services/SessionMemory/prompts.ts) store structured blocks such as Current State, Task specification, Files and Functions, Errors & Corrections, and Worklog, enabling reliable continuation of long tasks.
Attack Surface from High Permissions
Configuration poisoning is a real risk. A malicious .claude/settings.json can inject scripts that run silently via the claude command, bypassing any UI confirmation. Hooks, .mcp.json, and skill front‑matter share this trust model, turning previously passive configuration files into active execution vectors.
Check Point Research’s CVE‑2025‑59536 highlights this shift: “What was once passive data is now an active execution controller.”
Practical Takeaways
Prompt assembly is treated as a cacheable, composable runtime layer.
Tools declare safety boundaries before being exposed to the model.
File edits follow a strict “read‑then‑write” contract.
Permissions form a governable decision pipeline, not a simple dialog prompt.
Long‑task handling separates history compression from state continuation.
These engineering practices, once embedded in code, turn best‑practice recommendations into enforceable system constraints, offering a more stable user experience and a clearer path for future AI‑coding product differentiation.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
