This repository is not the original Anthropic development repository. It is an extracted TypeScript source tree reconstructed from the published source map that shipped with @anthropic-ai/claude-code version 2.1.88.
That matters for two reasons:
If your goal is to understand how Claude Code works internally, this repository is detailed enough to do that.
Claude Code is not a thin wrapper around an LLM API. It is a fairly large agent runtime with these major responsibilities:
The architecture is easiest to understand as five layers:
CLI and startup layerSession and UI layerPrompt/query orchestration layerTool and integration layerPersistence and extensibility layerIf you want the shortest path to understanding the system, read these files in order:
cli.jssrc/entrypoints/cli.tsxsrc/main.tsxsrc/entrypoints/init.tssrc/setup.tssrc/QueryEngine.tssrc/query.tssrc/Tool.tssrc/tools.tssrc/commands.tssrc/utils/processUserInput/processUserInput.tssrc/services/tools/toolOrchestration.tssrc/utils/sessionStorage.tssrc/services/mcp/client.tssrc/bridge/bridgeMain.tsThat sequence shows the lifecycle from process startup to a full agent turn, then moves into integrations and persistence.
This layer decides what mode Claude Code is running in and prepares the process.
Key files:
cli.jssrc/entrypoints/cli.tsxsrc/main.tsxsrc/entrypoints/init.tssrc/setup.tsResponsibilities:
--version.This layer owns the interactive experience.
Key files:
src/replLauncher.tsxsrc/components/App.tsxsrc/screens/REPL.tsxsrc/state/AppStateStore.tssrc/ink.tsResponsibilities:
This is the core agent loop.
Key files:
src/QueryEngine.tssrc/query.tssrc/utils/processUserInput/processUserInput.tssrc/query/config.tssrc/query/deps.tssrc/query/tokenBudget.tsResponsibilities:
This layer is what makes Claude Code an engineering agent rather than a chat client.
Key files:
src/Tool.tssrc/tools.tssrc/services/tools/toolOrchestration.tssrc/services/mcp/client.tssrc/commands.tsResponsibilities:
This layer lets the system survive across turns and become user-customizable.
Key files:
src/utils/sessionStorage.tssrc/history.tssrc/skills/loadSkillsDir.tssrc/tools/AgentTool/loadAgentsDir.tssrc/utils/plugins/pluginLoader.tsResponsibilities:
cli.jsThe root cli.js file is intentionally tiny. It only loads the built CLI entrypoint from dist/src/entrypoints/cli.js.
This separation exists because the package is shipped as compiled JavaScript, while the repository keeps the extracted TypeScript source.
src/entrypoints/cli.tsxThis file is the real bootstrap dispatcher.
Important characteristics:
Examples of fast paths handled here:
--version--dump-system-promptps, logs, attach, killThe design goal is clear: do not pay the cost of loading the entire app unless the chosen command actually needs it.
src/main.tsxsrc/main.tsx is the heavyweight application entrypoint.
This file does a very large amount of orchestration:
One important pattern appears all over this file: feature(...) gates and lazy require(...) calls. This lets the compiled build eliminate internal-only or experimental capabilities.
src/entrypoints/init.tsThis file performs global process initialization.
It is responsible for:
This is a critical architectural clue: Claude Code treats startup as a staged pipeline with trust-sensitive and non-trust-sensitive work separated.
src/setup.tssetup.ts finishes session-specific startup.
It handles things like:
Conceptually, init.ts is global process initialization, while setup.ts is session initialization.
Claude Code is really multiple products sharing the same runtime.
This is the default terminal chat-and-tools experience.
Flow:
AppState.This uses QueryEngine without the full interactive REPL.
Typical use cases:
The repository also exposes entrypoints for MCP-compatible flows. Claude Code is not only an MCP client; parts of it can also participate in external automation protocols.
This turns the local environment into a remotely reachable execution environment and session host.
This supports detached sessions that can be listed, attached to, tailed, or terminated later.
Some tools can spawn subagents, teams, remote workers, or background tasks. This is why the runtime has explicit task state, agent registries, and special transcript handling for subagents.
src/replLauncher.tsx is simple but important. It lazy-loads App and REPL, then renders them through the Ink root.
That design keeps the main startup path smaller until the application commits to interactive mode.
The UI is built with Ink and React. This is significant because it means the runtime is structured like a React app, not like a hand-written curses loop.
Consequences of that decision:
src/state/AppStateStore.ts defines an extremely rich application state object.
The state includes:
This reveals a major design principle:
Claude Code centralizes cross-cutting session state in one durable store because many features need to cooperate in real time. Tool execution, background tasks, permissions, UI overlays, and remote integrations all depend on shared state.
The relevant file is src/utils/processUserInput/processUserInput.ts.
This module sits between raw terminal input and the model query loop.
Claude Code uses both:
That is a strong design choice. It means the product can expose deterministic commands for explicit user actions while still letting the model act agentically inside a turn.
Before a query runs, input processing can invoke hook systems such as user-prompt-submit hooks. These can:
This gives the system a policy and automation layer before model inference even starts.
The most important file for understanding the core agent architecture is src/QueryEngine.ts.
QueryEngine is effectively the session brain for one conversation.
It owns:
submitMessage() doesAt a high level, submitMessage():
ToolUseContext.query().This split is good architecture. QueryEngine owns session-level state, while query.ts owns turn-loop mechanics.
If you were implementing a similar tool, this is a pattern worth copying:
Session object owns durable state across turns.Turn executor owns one turn's streaming and tool loop.That boundary makes resumability and programmatic embedding much easier.
query.ts: The Actual Turn LoopIf QueryEngine is the session owner, src/query.ts is the runtime loop for one agentic turn.
The exported query() function and its internal queryLoop() function handle the iterative cycle:
The query loop is designed for long-running sessions. It tracks and triggers context compaction when history becomes too large.
This is not an add-on feature. It is first-class.
That tells you something fundamental about the product: Claude Code assumes sessions are long, stateful, and costly enough that context management must be built directly into the agent runtime.
The loop contains logic for handling max_output_tokens and prompt-too-long style errors. It can recover by compacting or continuing rather than simply failing.
Claude Code distinguishes several resource concepts:
This is another clue that the runtime is optimized for long, autonomous work rather than single-shot chat.
The loop can create synthetic summaries of tool usage. That helps compress or preserve useful state without storing every raw detail in the active prompt window.
Claude Code uses a rich message model rather than just user and assistant strings.
You can see this in files such as:
src/types/message.tssrc/utils/messages.tssrc/utils/sessionStorage.tsMessage categories include concepts like:
This is one of the most important lessons from the codebase.
If you want to build a serious agent tool, do not model the conversation as plain strings. You need structured message types that can represent:
Otherwise you will eventually lose correctness or resumability.
The tool system is centered around src/Tool.ts and src/tools.ts.
Tool.tsThis file defines the shared tool interfaces and tool use context.
The ToolUseContext is a particularly important abstraction. It carries:
This is the internal runtime contract that every tool depends on.
tools.tsThis file is the canonical tool registry.
It assembles the full tool list from:
Representative built-in tools include:
AgentToolBashToolFileReadToolFileEditToolFileWriteToolNotebookEditToolGlobToolGrepToolWebFetchToolWebSearchToolAskUserQuestionToolTodoWriteToolListMcpResourcesToolReadMcpResourceToolSkillToolThe tool list is not hardcoded into a prompt only. It is a typed runtime registry with enablement rules and concurrency behavior. That is much stronger than an LLM wrapper that merely tells the model about tools in text.
The execution logic is in src/services/tools/toolOrchestration.ts.
When assistant output includes tool-use blocks:
isConcurrencySafe.This is a strong, pragmatic design.
It avoids two common failures in agent systems:
For example:
This is exactly the kind of systems thinking required for real agent tools.
The command registry lives in src/commands.ts.
Commands are user-invoked, explicit control surfaces, usually slash commands.
Examples:
/init/review/security-review/compact/memory/plugin/agents/tasks/teleport/branch/permissionsThese commands are often lazy-loaded and may produce:
Tools are model-usable execution capabilities.
Examples:
This is one of the best design decisions in the codebase.
Commands are for deliberate user control. Tools are for model autonomy.
If you merge those concepts, your system becomes harder to reason about and harder to secure.
The permission context is represented through shared types referenced by Tool.ts, app state, and permission utilities.
Before a tool runs, the system can:
The tool permission context includes:
Claude Code is designed to run in many environments:
A single boolean like allowTools would not be enough. The codebase instead treats permissions as context-aware policy.
This is the correct design for a serious agent platform.
The most important persistence file is src/utils/sessionStorage.ts.
Claude Code persists much more than plain conversation text.
It stores:
JSONL is a good fit because:
The code distinguishes transcript messages from ephemeral progress messages. Progress messages are UI state, not durable conversation state.
That distinction is crucial. If you persist transient UI progress into the canonical conversation chain, resume logic becomes unreliable.
There are multiple persistence concerns in this repository:
Those are separate concerns and the codebase treats them separately.
Claude Code has substantial machinery for long-context operation.
Relevant areas include:
src/query.tssrc/services/compact/src/services/contextCollapse/Agentic coding sessions can be very long and tool-heavy. If the system keeps every message verbatim forever, three things happen:
Claude Code solves this by making compaction a core runtime concern.
If you are building a similar tool, do not add summarization later as a patch. Design your transcript and turn loop with explicit compaction boundaries from day one.
The MCP client logic lives in src/services/mcp/client.ts, with supporting types and config code under src/services/mcp/.
MCP gives Claude Code a structured way to connect to external tool and resource providers.
Supported transport styles include:
This is not a toy MCP integration. It includes:
That means MCP is treated as a first-class production integration surface.
If you want your tool to be extensible, an external tool protocol like MCP is a very strong design choice. It decouples your core runtime from the long tail of integrations.
The bridge subsystem is centered on src/bridge/bridgeMain.ts and its neighboring files.
Bridge mode allows the local machine or environment to act as a remotely controlled Claude Code execution target.
bridgeMain.ts revealsThis subsystem manages:
Claude Code is not limited to a single terminal on a single machine. It is designed to support remote orchestration, web-connected sessions, and cloud-backed execution environments.
If you want to build something similar, keep the following separate:
Claude Code follows that separation well.
This is one of the richest parts of the repository.
Skills are loaded primarily through markdown-based definitions, handled by src/skills/loadSkillsDir.ts.
A skill can contribute:
This is a lightweight way to package reusable workflows and domain knowledge.
Custom and built-in agents are handled through src/tools/AgentTool/loadAgentsDir.ts and the broader AgentTool subsystem.
Agent definitions can specify:
This means an agent is treated as a configurable runtime persona with execution constraints, not just a different prompt.
Plugins are handled by src/utils/plugins/pluginLoader.ts and related helpers.
A plugin can provide:
The loader handles:
Claude Code offers three extension levels:
skills for lightweight reusable prompts and workflowsagents for semi-autonomous specialized workersplugins for packaged, distributable extension bundlesThat layering is excellent and worth copying.
build.mjs is especially useful because it shows how this extracted repo is meant to become a runnable JavaScript distribution.
src/ and vendor/ TypeScript into dist/bun:bundle and bun:ffi imports with runtime shimssrc/... bare imports into relative paths for Node.js.jsx imports after transpilation.d.ts runtime importsThe build script confirms that the source tree is derived from a Bun-aware internal codebase, but adapted here for Node.js execution.
It also shows how heavily the codebase relies on build-time feature gating.
The easiest way to understand the whole system is to follow one interactive prompt.
claude.cli.js loads src/entrypoints/cli.tsx.main.tsx loads the main runtime.init.ts initializes config, env, telemetry, proxy, trust-sensitive services, and cleanup.setup.ts configures session-local state such as cwd, hooks, watchers, and worktree behavior.replLauncher.tsx.processUserInput.ts normalizes the input, handles slash commands or attachments, and invokes applicable hooks.QueryEngine.submitMessage() prepares the session-level context.query.ts sends a request to the model and starts streaming output.toolOrchestration.ts executes them with concurrency rules and permission checks.sessionStorage.ts.Claude Code is a stateful event-driven agent runtime wrapped in a terminal UI.
That is the right way to think about it.
It is not merely:
It is closer to an operating environment for a coding agent.
Several recurring design pressures explain the structure of the codebase.
Because coding sessions can last a long time, the system needs:
Because some actions must be explicit and some can be agentic, the system has both:
Because the product can edit files and run shell commands, it needs:
Because users want custom workflows, the system supports:
Because the same codebase runs in local terminals, remote environments, background daemons, and internal workflows, the architecture is highly feature-gated and modular.
From an engineering perspective, several things are especially strong.
QueryEngine.ts versus query.ts is a good split.
The transcript system is serious and production-minded.
ToolUseContext carries the right kind of shared runtime contract.
Skills, agents, plugins, and MCP are distinct but composable.
Tool orchestration does not blindly serialize everything or parallelize everything.
The codebase clearly optimizes startup and module loading.
The codebase is strong, but it is also complex.
main.tsx is extremely denseIt acts as a high-gravity orchestration module. That is understandable for a CLI entrypoint, but it also means many features converge there.
The heavy use of feature(...) is operationally useful, but it makes static comprehension harder.
A broad app state object helps feature composition, but also increases coupling between systems.
For example: config, env vars, managed settings, telemetry, policy limits, and auth can influence one another during startup.
These are normal tradeoffs for a mature agent runtime, not signs of bad engineering.
This section distills the architectural lessons from Claude Code into a practical blueprint.
Do not start with the mindset of "I need a CLI that calls an LLM".
Start with this mindset instead:
"I am building a runtime that manages sessions, tools, policy, persistence, and context for an agent."
That framing changes the design in the right way.
If you are implementing a similar tool, aim for these subsystems from the beginning:
CLI bootstrapglobal initializationsession managerturn executortool registrypermission enginetranscript storeUI layerintegration layerextension layerResponsibilities:
Recommended pattern:
Responsibilities:
Recommendation:
Separate global process init from session init.
Create a SessionRuntime or QueryEngine equivalent that owns:
This object should survive across multiple turns.
Implement a pure-ish turn loop that:
Recommendation:
Keep this separate from the session object so it is testable.
Do not use plain strings as your canonical transcript representation.
You need message variants for at least:
Model every tool with:
Also create a shared ToolContext with:
Do not bolt security on later.
Build a permission engine that can answer:
Use append-only JSONL or event-sourcing.
Persist:
Design resumption before you ship, not after.
Design your transcript format so you can summarize old segments while preserving continuity.
At minimum, store:
Copy Claude Code's layered approach:
skills for reusable prompt workflowsagents for specialized autonomous workersplugins for packaged extensionsMCP or equivalent for external integrationsThis is much better than one monolithic plugin abstraction.
If you were building a similar tool from scratch, a sensible sequence would be:
Build:
Avoid at this phase:
Add:
Add:
Add:
Add:
This sequencing mirrors the natural dependency order in the Claude Code architecture.
If you are implementing a similar product, these ideas are especially worth reusing.
session object plus separate turn loopToolUseContextcommands and toolsThe most instructive trio in the whole repository is:
src/QueryEngine.tssrc/query.tssrc/Tool.tsThose files capture the central idea of Claude Code:
Everything else is either supporting infrastructure, UI, persistence, or extension on top of that core.
Claude Code works because it treats coding assistance as a systems problem, not only as a prompting problem.
Its core architecture combines:
If you want to build a similar tool, that is the real lesson from this codebase.
Do not start with the prompt. Start with the runtime.