1. Purpose, Problem, and Tech Stack
What this is
The tree at /workspaces/src/ is the source of Claude Code, Anthropic's official CLI coding agent. It is referenced by name in the canonical system prompt (constants/prompts.ts:452):
You are Claude Code, Anthropic's official CLI for Claude.
And externally:
- Product URL
https://claude.com/claude-code—constants/product.ts:1 - Docs map
https://code.claude.com/docs/en/claude_code_docs_map.md—constants/prompts.ts:103
It is distributed as a terminal application with three primary shapes:
- Interactive TUI (React + Ink) — the default
claudeinvocation. Entryentrypoints/cli.tsx→main.tsx→components/App.tsx. - Headless / print / SDK mode — programmable use via the Claude Agent SDK. Entry
entrypoints/sdk/+QueryEngine.ts. EmitsSDKMessageevents. - Remote / bridge / daemon modes —
claude remote-control,claude daemon,claude ps|logs|attach|kill,claude environment-runner,claude self-hosted-runner. These turn the CLI into a long-lived session server that can execute work dispatched by Anthropic's CCR (Claude Code Remote) backend or a daemon supervisor (entrypoints/cli.tsx:100-246).
Problem solved
Claude Code turns an LLM into a general-purpose software engineering agent that can:
- Read and edit files on disk, run shell commands, run tests, make commits, open PRs.
- Spawn subagents for parallelizable work (
AgentTool), isolate them in git worktrees, or run them on remote sandboxes. - Consult and update long-lived memory (
memdir/, CLAUDE.md) so context survives across sessions. - Speak the Model Context Protocol (MCP) so external tools/resources/prompts plug in uniformly.
- Be driven from many surfaces: a terminal, the Claude.ai web UI over a WebSocket bridge, an IDE extension, a Chrome extension, an iPhone / iMessage / Telegram channel, a scheduled cron job.
Target users: software engineers and engineering teams. The product has explicit accommodations for Anthropic-internal users (USER_TYPE === 'ant' branches everywhere) plus the external 1P SKU.
Languages and runtime
- TypeScript with
.ts/.tsxthroughout —zod/v4for runtime schemas (Tool.ts:343). - Bun is the runtime and bundler. Files import
from 'bun:bundle'and callfeature(...)for compile-time dead code elimination (entrypoints/cli.tsx:1,QueryEngine.ts:1). Feature gates likefeature('BRIDGE_MODE'),feature('DAEMON'),feature('HISTORY_SNIP'),feature('COORDINATOR_MODE')are folded at build time so external builds strip ant-only paths. - React + Ink for the terminal UI (
components/App.tsx,components/Messages.tsx). Virtualized message list +useSyncExternalStorefor performance. - Node APIs for process and filesystem (
fs/promises,crypto,os). Polyfilled viautils/fsOperationsbehind a small abstraction to let the upstream-proxy relay and sandbox intercept.
Core dependencies (evident in the code)
| Dependency | Why |
|---|---|
@anthropic-ai/sdk |
Direct SDK usage for streaming Messages API (services/api/claude.ts, QueryEngine.ts:2). |
@modelcontextprotocol/sdk |
MCP client and server transports (services/mcp/). |
zod (v4) |
All tool input schemas; SDK public types (entrypoints/sdk/coreSchemas.ts). |
ink + react |
TUI render. |
lodash-es |
Functional helpers (QueryEngine.ts:4). |
strip-ansi |
Sanitizing shell output before emitting (QueryEngine.ts:21). |
commander (implicit from --bare note at cli.tsx:281-285) |
Option parsing for the main CLI path. |
Why these choices (as far as one can tell from the code)
- Bun lets the same file do top-level
import { feature } from 'bun:bundle'with build-time evaluation, which is how the codebase maintains one source tree for internal-rich and external-minimal builds. Theprocess.env.USER_TYPE === 'ant'conditionals everywhere are build-time constant-folded — see the explicit comment atconstants/prompts.ts:617-619: "process.env.USER_TYPE === 'ant'is build-time --define. It MUST be inlined at each callsite (not hoisted to a const) so the bundler can constant-fold it." - Ink was the natural choice in 2023 when this project began; it also means the same React hooks (
hooks/useTextInput.ts,hooks/useCommandQueue.ts, etc.) compose naturally. - TypeScript + Zod gives end-to-end type safety across the tool boundary: each tool declares an
inputSchema: z.ZodType<…>, and both the permission layer and the API call see the same type (Tool.ts:362-400). - MCP lets third parties add tools/resources/prompts without forking the binary; it is the default extension surface.
Size snapshot
Repo is a single flat src/ with ~329 files in utils/ alone. Notable sizes:
main.tsx— 4,683 lines (giant dispatcher: boots the TUI, headless, resume, etc.).query.ts— 1,729 lines (the core agent loop).QueryEngine.ts— 1,295 lines (SDK/headless wrapper aroundquery()).services/api/claude.ts— 3,419 lines (streaming, retry, caching, beta headers).services/compact/compact.ts— 1,705 lines (history compaction).Tool.ts— 792 lines (the tool contract).
You could implement a minimal clone in a fraction of this size. The weight is in production concerns: retries, cache optimization, permission modes, fleet rollouts, telemetry, multi-surface persistence.