Esc
输入关键词开始搜索
Agent

Claude Code 深读(一):系统总览与启动序列

Claude Code 深读(一):系统总览与启动序列

:::note[系列导航] 本文是 Claude Code 源码深度研究系列的第一篇。

  1. 系统总览与启动序列(本文)— 入口、全局状态、模块依赖、五层架构
  2. QueryEngine 与 query.ts — 会话主循环、上下文压缩、API 集成
  3. Tool 协议、权限系统与工具调度 — 工具协议、23 种攻击检测、并发调度
  4. Skills/Commands/MCP 注入 Runtime — 能力加载、命令注册、MCP transport
  5. Anthropic 内部如何使用 Skills — 官方实践
  6. 源码泄漏深度技术解读 — 全景式 11 维度硬核分析 :::

这篇文章基于 @anthropic-ai/claude-code v2.1.88 的 npm source map 还原出的 1884 个 TypeScript 源文件。所有文件路径、函数签名、常量值均来自实际源码阅读。


一、为什么 Claude Code 值得拆

Claude Code 不是一个普通的聊天 CLI。从源码结构看,它更接近一个面向终端与本地开发工作流的 Agent Runtime,同时具备:

  • CLI / slash command 系统(55+ 命令)
  • 会话主循环(QueryEngine + query.ts,合计 3024 行)
  • 40+ 工具注册与 6 层权限系统
  • MCP 集成(7 种 transport)
  • Skills / Plugins 机制(17 个内置技能)
  • React/Ink TUI 界面(定制 fork,45+ 文件)
  • 远程会话、桥接、工作树、任务与多 Agent 协作

二、源码树总览

src/
  entrypoints/          # 6 个入口模块(cli, init, mcp, sdk, sandbox, control)
  bootstrap/            # 全局状态与启动引导(state.ts: 1600+ 行)
  main.tsx              # 巨型编排器(3806+ 行)
  QueryEngine.ts        # 会话主循环内核(1295 行)
  query.ts              # query loop 状态机(1729 行)
  Tool.ts               # 工具类型系统(793 行)
  tools.ts              # 工具注册中心(390 行)
  commands.ts           # 命令注册中心(755 行)
  tools/                # 40+ 工具实现
  commands/             # 70+ 命令实现(含子目录)
  skills/               # Skills 体系与 17 个内置技能
  services/             # API / MCP / compact / analytics 等服务层
  state/                # AppState 与 Store(454 行)
  context/              # 上下文拼装
  constants/            # 零依赖常量(betas, apiLimits, xml, system, oauth, toolLimits)
  utils/                # 300+ 工具函数
  assistant/            # Kairos 助手模式
  coordinator/          # Coordinator 多 Agent 编排
  bridge/ remote/       # IDE 桥接与远程会话
  buddy/                # 电子宠物系统(16 种物种)
  memdir/               # Kairos 长期记忆
  ink/                  # 定制版 Ink 渲染器(45+ 文件)
  plugins/              # 插件基础设施

三、五层架构

[1] Entrypoint / CLI Layer
    entrypoints/cli.tsx → main.tsx → commands.ts

[2] Session Runtime Layer
    QueryEngine.ts → query.ts → processUserInput(...)

[3] Tool Protocol Layer
    Tool.ts → tools.ts → tools/*

[4] Service / Integration Layer
    services/* → MCP / API / auth / plugins / skills / analytics

[5] UI / Interaction Layer
    ink/ → components/ → REPL.tsx(895KB)

核心设计取向:把”模型循环”当作核心,但绝不把整个系统都塞进模型循环里。


四、入口:两阶段启动序列

4.1 CLI 快速路径(entrypoints/cli.tsx,302 行)

cli.tsx 是二进制入口。它在加载 main.tsx 之前,先做了大量快速路径优化——对于不需要完整 runtime 的命令,在导入重模块之前就直接返回:

快速路径Feature Gate说明
--version / -v零导入,写 MACRO.VERSION 后退出
--dump-system-promptant-only导出系统提示
--claude-in-chrome-mcpChrome MCP 服务
--daemon-workerDAEMON守护进程 worker
remote-control / rc / bridgeBRIDGE_MODEIDE 桥接
daemonDAEMON守护进程管理
ps / logs / attach / kill / --bgBG_SESSIONS后台会话
new / list / replyTEMPLATES模板系统
environment-runnerBYOC_ENVIRONMENT_RUNNERBYOC 环境
self-hosted-runnerSELF_HOSTED_RUNNER自托管 runner

每个快速路径都有显式 return,确保不触发完整 CLI 加载。

4.2 主初始化(entrypoints/init.ts,341 行)

初始化分为两个阶段——遥测只在用户明确信任后才启动。

Phase 1 — 主初始化(不依赖信任状态,行 57-214):

export const init = memoize(async (): Promise<void> => {
  profileCheckpoint('init_function_start')
  enableConfigs()                          // 1. 配置系统启用
  applySafeConfigEnvironmentVariables()    // 2. 安全环境变量(信任前子集)
  applyExtraCACertsFromConfig()            // 3. CA 证书(Bun 要求 NODE_EXTRA_CA_CERTS)
  setupGracefulShutdown()                  // 4. 优雅退出处理
  // 5-8. Fire-and-forget 异步任务(并行启动)
  //   - 1P 事件日志、OAuth 填充、JetBrains 检测、GitHub 仓库检测
  // 9-10. loadRemoteManagedSettings(), loadPolicyLimits()(非阻塞)
  recordFirstStartTime()                   // 11. 首次启动时间
  configureGlobalMTLS()                    // 12. mTLS
  configureGlobalAgents()                  // 13. HTTP Agent(代理/mTLS)
  preconnectAnthropicApi()                 // 14. ⚡ TCP+TLS 预连接(性能优化)
  // 15-18: 上游代理、Windows 适配、LSP、团队清理、Scratchpad
})

第 14 步的 preconnectAnthropicApi() 提前建立 TCP+TLS 连接,让首次 API 调用跳过握手延迟。

Phase 2 — 信任后遥测初始化(行 247-340):

export function initializeTelemetryAfterTrust(): void {
  // 有远程设置资格 → 等待设置加载 → 重新应用环境变量 → 初始化遥测
  // 无远程设置资格 → 直接初始化遥测
}
async function setMeterState(): Promise<void> {
  // 延迟加载 OpenTelemetry(400KB+ 模块推迟到此刻)
  const { metrics, logs } = await import('@opentelemetry/api')
  // 创建 counter: session, loc, pr, commit, cost, token, codeEditToolDecision, activeTime
}

4.3 主编排器(main.tsx,3806+ 行)

main.tsx系统 bootloader + runtime assembler,执行序列:

1. profileCheckpoint('main_function_start')          // 行 586
2. 信号处理器 & 警告初始化
3. Direct Connect URL 解析(DIRECT_CONNECT feature)
4. 预动作钩子阶段(行 910-967):
   ├─ ensureMdmSettingsLoaded() + ensureKeychainPrefetchCompleted()
   ├─ await init()          ← Phase 1 完成
   ├─ initSinks()           ← 日志 sink 附加
   ├─ 注入 --plugin-dir 内联插件
   ├─ runMigrations()
   └─ 后台启动远程设置 & 策略限制加载
5. 信任对话阶段(行 2239-2242):
   └─ await showSetupScreens()  ← 用户信任确认
6. 信任后设置(行 2593-2607):
   ├─ applyConfigEnvironmentVariables()   ← 完整环境变量
   ├─ initializeTelemetryAfterTrust()     ← Phase 2 完成
   └─ processSessionStartHooks('startup')
7. 模型/功能解析 → 工具/命令/MCP 装配 → 进入交互或 headless 模式

Feature Gate 清单main.tsx 中出现的 feature('...')):

COORDINATOR_MODE, KAIROS, BRIDGE_MODE, DAEMON, VOICE_MODE, WORKFLOW_SCRIPTS, HISTORY_SNIP, TORCH, BUDDY, BG_SESSIONS, TEMPLATES, UPLOAD_USER_SETTINGS, AGENT_MEMORY_SNAPSHOT, ULTRAPLAN, FORK_SUBAGENT, PROACTIVE, UDS_INBOX

这意味着 Claude Code 不是单一产品形态,而是多产品模式共用同一运行时底座


五、全局状态

5.1 bootstrap/state.ts(1600+ 行)

文件顶部有两道防线:

// DO NOT ADD MORE STATE HERE - BE JUDICIOUS WITH GLOBAL STATE  // 行 31
// ALSO HERE - THINK THRICE BEFORE MODIFYING                     // 行 259

State 类型目前 257 行,包含以下类别:

类别代表字段说明
会话元数据originalCwd, projectRoot, sessionId, parentSessionId, kairosActive, isRemoteMode入口时确定
成本追踪totalCostUSD, totalAPIDuration, totalAPIDurationWithoutRetries, totalToolDuration实时累计
轮次统计turnHookDurationMs, turnToolDurationMs, turnClassifierDurationMs, turnToolCount, turnHookCount每轮重置
模型信息modelUsage: { [name]: ModelUsage }, mainLoopModelOverride, initialMainLoopModel, modelStrings动态切换
遥测meter, sessionCounter, locCounter, prCounter, commitCounter, costCounter, tokenCounterPhase 2 后填充
缓存cachedClaudeMdContent, systemPromptSectionCache, planSlugCache, promptCache1hAllowlist热缓存
特性开关scheduledTasksEnabled, sessionBypassPermissionsMode运行时切换
Prompt Cache 控制afkModeHeaderLatched, fastModeHeaderLatched, cacheEditingHeaderLatched, thinkingClearLatched锁存器模式

初始状态工厂(行 260-299)通过 realpathSync(rawCwd).normalize('NFC') 解析符号链接,确保路径一致性。

5.2 AppStatestate/AppStateStore.ts,454 行)

与全局 State 不同,AppStateReact 感知的运行时状态,使用 DeepImmutable<{...}> 类型标记:

export type AppState = DeepImmutable<{
  settings: SettingsJson
  mainLoopModel: ModelSetting
  toolPermissionContext: ToolPermissionContext
  remoteConnectionStatus: 'connecting' | 'connected' | 'reconnecting' | 'disconnected'
  replBridgeEnabled / replBridgeConnected / ...  // Bridge 6 字段
  selectedIPAgentIndex: number                   // Agent Swarm
  viewSelectionMode: 'none' | 'selecting-agent' | 'viewing-agent'
  mcp: { commands: Command[] }                   // MCP 命令
  loadedPlugins: LoadedPlugin[]
  speculationState: SpeculationState             // 推测执行
  // ...(共 150+ 属性)
}>

SpeculationState 透露了未公开的优化——用户思考时推测性预执行:

export type CompletionBoundary =
  | { type: 'complete'; completedAt: number; outputTokens: number }
  | { type: 'bash'; command: string; completedAt: number }
  | { type: 'edit'; toolName: string; filePath: string; completedAt: number }
  | { type: 'denied_tool'; toolName: string; detail: string; completedAt: number }

六、模块依赖关系

entrypoints/              ← 入口层

bootstrap/ (state, init)  ← 引导层

main.tsx                  ← 编排层

QueryEngine.ts / query.ts ← 运行时内核

services/ (api, compact, tools, mcp, auth)  ← 服务层

tools/ (40+ 工具实现)     ← 工具层

utils/ (permissions, sandbox, hooks, worktree)  ← 函数层

constants/ (零依赖叶子节点)  ← 常量层

constants/ 下的文件被特意保持零依赖,防止循环引用。部分模块用运行时 require() 替代静态 import 来打破循环依赖(如 TeamCreateToolSendMessageTool)。


七、关键常量

7.1 Beta Headers(constants/betas.ts,53 行)

18 个 beta header,相当于 Anthropic API 的内部路线图:

CLAUDE_CODE_20250219_BETA_HEADER      = 'claude-code-20250219'
INTERLEAVED_THINKING_BETA_HEADER      = 'interleaved-thinking-2025-05-14'
CONTEXT_1M_BETA_HEADER                = 'context-1m-2025-08-07'
CONTEXT_MANAGEMENT_BETA_HEADER        = 'context-management-2025-06-27'
STRUCTURED_OUTPUTS_BETA_HEADER        = 'structured-outputs-2025-12-15'
WEB_SEARCH_BETA_HEADER                = 'web-search-2025-03-05'
TOOL_SEARCH_BETA_HEADER_1P            = 'advanced-tool-use-2025-11-20'
TOOL_SEARCH_BETA_HEADER_3P            = 'tool-search-tool-2025-10-19'
EFFORT_BETA_HEADER                    = 'effort-2025-11-24'
TASK_BUDGETS_BETA_HEADER              = 'task-budgets-2026-03-13'
PROMPT_CACHING_SCOPE_BETA_HEADER      = 'prompt-caching-scope-2026-01-05'
FAST_MODE_BETA_HEADER                 = 'fast-mode-2026-02-01'
REDACT_THINKING_BETA_HEADER           = 'redact-thinking-2026-02-12'
TOKEN_EFFICIENT_TOOLS_BETA_HEADER     = 'token-efficient-tools-2026-03-28'
ADVISOR_BETA_HEADER                   = 'advisor-tool-2026-03-01'
// Feature-gated:
SUMMARIZE_CONNECTOR_TEXT_BETA_HEADER   // CONNECTOR_TEXT feature
AFK_MODE_BETA_HEADER                   // TRANSCRIPT_CLASSIFIER feature
CLI_INTERNAL_BETA_HEADER               // ant-only

Bedrock 兼容:BEDROCK_EXTRA_PARAMS_HEADERS 集合定义了哪些 header 需通过 extraBodyParams 发送。

7.2 API 限制(constants/apiLimits.ts,97 行)

API_IMAGE_MAX_BASE64_SIZE  = 5 * 1024 * 1024     // 5 MB
IMAGE_MAX_WIDTH / HEIGHT   = 2000                 // px
PDF_TARGET_RAW_SIZE        = 20 * 1024 * 1024     // 20 MB
API_PDF_MAX_PAGES          = 100
PDF_MAX_PAGES_PER_READ     = 20
API_MAX_MEDIA_PER_REQUEST  = 100

7.3 工具结果限制(constants/toolLimits.ts,57 行)

DEFAULT_MAX_RESULT_SIZE_CHARS      = 50_000       // 单工具结果字符上限
MAX_TOOL_RESULT_TOKENS             = 100_000      // 单工具结果 token 上限
BYTES_PER_TOKEN                    = 4
MAX_TOOL_RESULT_BYTES              = 400_000      // = 100K × 4
MAX_TOOL_RESULTS_PER_MESSAGE_CHARS = 200_000      // 每条消息所有工具结果总限
TOOL_SUMMARY_MAX_LENGTH            = 50

7.4 系统提示前缀(constants/system.ts,96 行)

const DEFAULT_PREFIX = "You are Claude Code, Anthropic's official CLI for Claude."
const AGENT_SDK_CLAUDE_CODE_PRESET_PREFIX = 
  "You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK."
const AGENT_SDK_PREFIX = "You are a Claude agent, built on Anthropic's Claude Agent SDK."

选择逻辑:Vertex 固定 DEFAULT_PREFIX;非交互模式根据 hasAppendSystemPrompt 选择 SDK 前缀。

7.5 Attribution Header

x-anthropic-billing-header: cc_version={version}; cc_entrypoint={entrypoint}; cch=00000; cc_workload={workload};

cch=00000NATIVE_CLIENT_ATTESTATION feature gate 下的原生客户端认证占位符。cc_workload 提供 QoS 路由提示。

7.6 XML Tag 体系(constants/xml.ts,87 行,26+ 常量)

// 命令元数据
COMMAND_NAME_TAG, COMMAND_MESSAGE_TAG, COMMAND_ARGS_TAG
// 终端输出
BASH_INPUT_TAG, BASH_STDOUT_TAG, BASH_STDERR_TAG
LOCAL_COMMAND_STDOUT_TAG, LOCAL_COMMAND_STDERR_TAG, LOCAL_COMMAND_CAVEAT_TAG
// 任务通知
TASK_NOTIFICATION_TAG, TASK_ID_TAG, TOOL_USE_ID_TAG, STATUS_TAG, SUMMARY_TAG
// 工作树
WORKTREE_TAG, WORKTREE_PATH_TAG, WORKTREE_BRANCH_TAG
// 远程与 Swarm
ULTRAPLAN_TAG, TEAMMATE_MESSAGE_TAG, CHANNEL_MESSAGE_TAG, CROSS_SESSION_MESSAGE_TAG
// Fork
FORK_BOILERPLATE_TAG, FORK_DIRECTIVE_PREFIX = 'Your directive: '

7.7 OAuth 配置(constants/oauth.ts,235 行)

CLIENT_ID: '9d1c250a-e61b-44d9-88ed-5944d1962f5e'   // 生产
// Staging (ant-only): '22422756-60c9-4084-8eb7-27705fd5cf9a'

// OAuth Scopes
CLAUDE_AI_OAUTH_SCOPES = [
  'user:profile', 'user:inference', 'user:sessions:claude_code',
  'user:mcp_servers', 'user:file_upload'
]

八、QueryEngine.ts:会话运行时内核

8.1 类定义(行 184-207)

export class QueryEngine {
  private config: QueryEngineConfig
  private mutableMessages: Message[]
  private abortController: AbortController
  private permissionDenials: SDKPermissionDenial[]
  private totalUsage: NonNullableUsage
  private hasHandledOrphanedPermission = false
  private readFileState: FileStateCache
  private discoveredSkillNames = new Set<string>()
  private loadedNestedMemoryPaths = new Set<string>()
}

8.2 QueryEngineConfig(行 130-173)

export type QueryEngineConfig = {
  cwd: string
  tools: Tools
  commands: Command[]
  mcpClients: MCPServerConnection[]
  agents: AgentDefinition[]
  canUseTool: CanUseToolFn
  getAppState: () => AppState
  setAppState: (f: (prev: AppState) => AppState) => void
  initialMessages?: Message[]
  readFileCache: FileStateCache
  customSystemPrompt?: string
  appendSystemPrompt?: string
  userSpecifiedModel?: string
  fallbackModel?: string
  thinkingConfig?: ThinkingConfig
  maxTurns?: number
  maxBudgetUsd?: number
  taskBudget?: { total: number }
  jsonSchema?: Record<string, unknown>
  handleElicitation?: ToolUseContext['handleElicitation']
  // ... replayUserMessages, includePartialMessages, setSDKStatus, abortController, snipReplay
}

8.3 submitMessage()(行 209-212)

async *submitMessage(
  prompt: string | ContentBlockParam[],
  options?: { uuid?: string; isMeta?: boolean },
): AsyncGenerator<SDKMessage, void, unknown>

返回 AsyncGenerator<SDKMessage> 而非 Promise<string>——在内核层就选择了事件流式 agent runtime


九、工具与命令概览

9.1 工具注册表(tools.ts,390 行)

getAllBaseTools() 按加载策略分三类:

直接导入(核心工具):AgentTool, BashTool, FileReadTool, FileEditTool, FileWriteTool, GlobTool, GrepTool, NotebookEditTool, WebFetchTool, TodoWriteTool, WebSearchTool, AskUserQuestionTool, SkillTool, EnterPlanModeTool

条件加载(feature gate):

工具条件
REPLToolUSER_TYPE === 'ant'
SleepToolPROACTIVE | KAIROS
CronToolsAGENT_TRIGGERS
WebBrowserToolWEB_BROWSER_TOOL
WorkflowToolWORKFLOW_SCRIPTS
SnipToolHISTORY_SNIP

9.2 工具过滤管道

getAllBaseTools()
  → getTools(permissionContext)
    → CLAUDE_CODE_SIMPLE 模式(只保留 Bash/Read/Edit)
    → filterToolsByDenyRules()
    → .isEnabled() 过滤
  → assembleToolPool(permissionContext, mcpTools)
    → 合并 MCP 工具,按名称去重(内置优先)
    → 稳定排序(保持 prompt cache 命中率)

9.3 commands 与 tools 分离

Claude Code 维护两套平面:

  • commandscommands.ts):给用户控制 runtime(/config, /status, /memory, /permissions…)
  • toolstools.ts):给模型在 query loop 中执行

详细分析见第三篇第四篇


十、调用链图

User Input


cli.tsx → 快速路径检查 → 若命中直接返回


main.tsx → 两阶段初始化 → 信任确认 → 工具/命令/MCP 装配


QueryEngine.submitMessage(prompt, options)
  ├─ 包装 canUseTool 记录权限拒绝
  ├─ 解析主模型与 thinking 配置
  ├─ fetchSystemPromptParts() → { defaultSystemPrompt, userContext, systemContext }
  ├─ 构造 ProcessUserInputContext
  └─ 调用 processUserInput(...)


processUserInput(...) → slash command 拦截 / attachments / hooks / allowedTools 覆写
  │ → 决定是否进入 query loop

query(params) → queryLoop(params) → while (true)
  ├─ memory prefetch + skill discovery prefetch
  ├─ applyToolResultBudget() → snipCompactIfNeeded() → microcompact()
  ├─ contextCollapse.applyCollapsesIfNeeded() → autocompact()
  ├─ 构建 full system prompt → queryModelWithStreaming()
  └─ runTools() / StreamingToolExecutor


工具执行 → contextModifier 回写 → 结果注入消息流 → 继续循环或退出

十一、技术选型

维度选择说明
运行时Node.js >= 18Bun bundler 打包,编译时 feature gate 死代码消除
UI 框架Ink(React 终端渲染器)定制 fork:src/ink/ 含自定义 reconciler、布局引擎
Schema 校验Zod与 TypeScript 类型系统深度集成
状态管理自研 createStore()类 Zustand 模式
依赖管理零运行时依赖全部 bundle 进 cli.js(16667 行 minified),仅 Sharp 为 optional

十二、对 Agent 工程的 6 条启发

  1. 主循环必须是一等公民 — 独立成 runtime kernel(QueryEngine),不埋在 UI 或 handler 里
  2. 工具协议先于工具实现 — 先定义 context / permission / progress 协议(Tool.ts 793 行)
  3. 用户控制面和模型执行面分开 — commands 与 tools 分离是长期可维护性的关键
  4. 会话是对象,不是数组 — 单纯的 message array 对 coding agent 很快不够用
  5. 性能工程要前置preconnectAnthropicApi(), keychain 预取, 快速路径优化
  6. Agent 系统最终会长成操作系统 — session, tools, commands, plugins, remote, policies 已超出 “LLM app” 范畴

附:核心源文件索引

文件行数角色
entrypoints/cli.tsx302二进制入口,快速路径分发
entrypoints/init.ts341两阶段初始化(memoized)
main.tsx3806+系统 bootloader + runtime assembler
bootstrap/state.ts1600+全局状态中心(257 行类型定义)
state/AppStateStore.ts454React 感知的运行时状态(DeepImmutable
QueryEngine.ts1295会话主循环内核
query.ts1729query loop 状态机
Tool.ts793工具类型系统
tools.ts390工具注册中心
commands.ts755命令注册中心
constants/betas.ts5318 个 Beta Header
constants/system.ts96系统提示前缀 + Attribution
constants/toolLimits.ts57工具结果限制
constants/apiLimits.ts97API 尺寸限制
constants/oauth.ts235OAuth 配置
constants/xml.ts8726+ XML Tag 常量