Claude Code 源码架构全景图

5 阅读9分钟

Claude Code 架构全景图

📍 导航指南

这是「从零理解 Claude Code 源码」系列的第零篇——整个系列的地图。根据你的背景,选择合适的阅读路径:


目录

第一部分:系统结构 🗺️

第二部分:运行机制 ⚙️

补充

附录


引言

用户在终端输入一句话:

帮我把这个函数重构一下

Claude Code 是怎么读文件、写代码、执行命令的?

答案不在某一个文件里。它分散在 src/query.tssrc/tools/src/QueryEngine.tssrc/bootstrap/state.ts 等几十个文件的协作中。

这篇文章是整个系列的地图。读完之后,你会知道这个系统由哪些部分组成、它们怎么协作、以及后续每篇文章在讲哪一块。


第一部分:系统结构 🗺️

三种运行模式

Claude Code 不只是一个终端工具。它有三种运行模式,面向不同场景:

模式入口典型场景
Interactive REPLsrc/replLauncher.tsxsrc/screens/REPL.tsx开发者日常使用,有终端 UI
Headless / SDK--print flag,stream-json 输出CI 流水线、自动化脚本
Remote / CCRsrc/bridge/ — WebSocket 远程会话claude.ai/code 背后的机制

三种模式的关键在于:它们共享同一套 query / tool / message 基础设施。无论你是在终端交互,还是在 CI 里跑自动化,底层走的是同一个 query.ts 主循环。

五大核心模块

整个系统可以拆成五个模块:

1. QUERY LOOP — 对话核心

源码:src/QueryEngine.ts(会话对象)、src/query.ts(主循环)

这是整个系统的心脏。query.ts 是一个 AsyncGenerator,每次调用 Anthropic API,拿到响应后决定:继续调用工具,还是把最终答案 yield 给上层。所有推理和工具调度都发生在这里。

2. TOOL RUNTIME — 40+ 工具

源码:src/tools.ts(注册中心)、src/tools/(实现)、src/services/tools/toolOrchestration.ts(并发调度)

工具是模型和真实系统之间的桥梁。每个工具实现 Tool.ts 定义的统一协议:

// src/Tool.ts
interface Tool {
  call(input, context): AsyncGenerator<ToolProgress, ToolResult>
  checkPermissions(input, context): PermissionResult
  render(result): React.ReactNode
  isReadOnly(): boolean
}

3. 四层扩展体系

源码:src/commands/src/plugins/src/services/mcp/src/skills/

  • Commands/commit/review 等 slash 命令
  • Skills:可复用的提示词模板,通过 SkillTool 调用
  • Plugins:本地插件,扩展工具和 Hook
  • MCP:Model Context Protocol,接入外部工具服务器

4. AGENT/TASK 子系统

源码:src/tools/AgentTool/src/Task.ts

Agent 在 Claude Code 里是一级概念。每个子 Agent 有独立的 tool pool、model 配置、权限上下文、可选的 worktree 隔离。

5. 持久化与状态层

源码:src/bootstrap/state.tssrc/utils/sessionStorage.tssrc/memdir/src/history.ts

会话状态、历史消息、记忆文件、文件快照都在这一层管理。bootstrap/state.ts 是全局状态的单一来源,注释里甚至写着:

// DO NOT ADD MORE STATE HERE - BE JUDICIOUS WITH GLOBAL STATE

模块协作关系

graph TD
    REPL[REPL Screen] --> Input[processUserInput]
    Input --> QE[QueryEngine]
    Input --> LocalCmd[Local Commands]

    QE --> QL[Query Loop]
    QL --> API[Anthropic API]
    QL --> TR[Tool Runtime]
    QL --> State[State & Persistence]

    subgraph Tools
        TR --> Builtin[Built-in Tools]
        TR --> Agent[AgentTool / Sub-Agent]
        TR --> Skill[SkillTool / Prompts]
        TR --> MCP[MCP Tools]
    end

    subgraph Extensions
        Plugins[Plugins]
        Plugins -.-> LocalCmd
        Plugins -.-> Skill
        Plugins -.-> MCP
    end

第二部分:运行机制 ⚙️

数据流:一条消息的完整旅程

用户输入
  ↓
REPL 捕获
  ↓
processUserInput(解析 Slash 命令与附件)
  ↓
QueryEngine 组装上下文
  (含:会话历史 / MEMORY.md 记忆注入 / 文件快照 / 系统提示词构建)
  ↓
queryLoop 调用 Anthropic API
  ↓
API 返回 tool_use
  ↓
权限检查(User / Hook / Classifier / Bridge)
  ↓
工具执行(并发调度)
  ↓
tool_result 回填消息列表
  ↓
再次调用 API(循环直到任务完成)
  ↓
Ink 渲染到终端

这个循环是 ReAct 模式的直接实现:

推理(Reasoning)→ 行动(Action)→ 观察(Observation)→ 再推理

直到任务完成。

注意 QueryEngine 的上下文组装步骤:它不只是拼接历史消息,还要注入 MEMORY.md、构建系统提示词、加载文件快照。这一步是首次调用 API 有时较慢的原因之一,011 篇会专门讲上下文压缩如何优化这个过程。

调试视角:关键调用栈

阶段关键文件/函数作用
输入捕获src/screens/REPL.tsxuseInputInk 终端输入监听
预处理src/commands.ts + messageAttachments解析 /commit@file
上下文组装src/QueryEngine.tsbuildMessages()注入记忆、历史、系统提示词
主循环src/query.ts*queryLoop()AsyncGenerator,驱动 ReAct 循环
工具调度src/services/tools/toolOrchestration.tscallTool()并发控制与权限拦截
渲染src/components/ → Ink 组件树流式输出到终端

关键架构判断

理解这三个设计决策,能帮你更快读懂源码:

消息驱动

用户输入、模型输出、工具进度、系统事件——全部抽象成 Messagesrc/types/message.ts 定义了所有消息类型。整个系统是一个消息流,而不是函数调用链。→ 这意味着你可以在任意位置插入一个消息监听器,而不需要修改调用链。

Prompt Cache 优先

工具列表按名称稳定排序,系统提示词用 DYNAMIC_BOUNDARY 分界,目的是最大化 Anthropic API 的 prompt cache 命中率。这是一个对成本和延迟都有直接影响的设计。→ 这意味着阅读源码时,你会发现工具定义列表的排序是固定的,系统提示词的变动极其保守——任何破坏 DYNAMIC_BOUNDARY 的改动都会导致 cache miss,成本和延迟双双飙升。

Agent 是一级概念

子 Agent 不是"调用自己的递归",而是一个独立的执行单元,有自己的 tool pool、model、权限、甚至 git worktree。这让多 Agent 协作成为可能,也是 Claude Code 能处理复杂任务的基础。→ 这意味着你可以给子 Agent 配置完全不同的模型和权限策略,主 Agent 和子 Agent 之间只通过输入/输出通信,互不污染上下文。worktree 隔离是可选的,取决于调用时的配置——不是每个子 Agent 都会创建独立的 git worktree。


技术栈速览 🔧

技术用途
Bun运行时,替代 Node.js,启动更快,内置 bun:bundle feature flag 机制
TypeScript全栈类型安全,.tsx 用于终端 UI 组件
React 组件模型 + Ink 终端渲染引擎用 React 组件模型管理 UI 状态,Ink 负责将组件树渲染到终端(src/replLauncher.tsx 里直接写 JSX)
@anthropic-ai/sdk流式 SSE 调用,AsyncGenerator 消费响应流
Commander.jsCLI 参数解析(@commander-js/extra-typings 提供类型安全)
chalk终端颜色输出

快速上手与调试指南

如果你想在本地跑起 Claude Code 并调试源码:

  1. 安装依赖:项目使用 Bun 运行时。
    bun install
    
  2. 本地运行
    bun run dev
    
  3. 关键断点:建议在 src/query.tsqueryLoop 生成器起始处,以及 src/services/tools/toolOrchestration.tscallTool 处打断点。
  4. 环境变量:确保 ANTHROPIC_API_KEY 已正确配置。

本系列文章导航

建议阅读顺序:

000(本页,全景图)
  ↓
001queryLoop 执行引擎)→ 002(工具系统设计)→ 003-009(各类工具)
  ↓
010(四层扩展体系)→ 013(系统提示词)
  ↓
011(上下文压缩)→ 012(状态持久化)→ 014(记忆系统)
  ↓
015(Hook 系统)→ 016(可观测性)

001 是核心必读,理解 queryLoop 之后其他模块才能串起来。010 是横向扩展,可以按需跳读。

编号文章对应模块
001queryLoop 执行引擎总览QUERY LOOP
002工具系统设计总览 + 权限机制TOOL RUNTIME
003普通工具实现(Read/Write/Edit/Todo)TOOL RUNTIME
004plan 工具TOOL RUNTIME
005askUserQuestion 工具TOOL RUNTIME
006subagent 工具(AgentTool)AGENT/TASK
007MCP 工具扩展体系
008skill 工具扩展体系
009多 Agent 协作:task/team/worktreeAGENT/TASK
010Commands / Skills / Plugins / MCP 的关系扩展体系
011五层上下文压缩全解析QUERY LOOP
012状态管理与会话持久化持久化层
013系统提示词的构建与注入QUERY LOOP
014记忆系统:MEMORY.md 的实现持久化层
015Hook 系统:三类 Hook 的设计扩展体系
016日志与链路追踪基础设施

系列导航


常见问题 FAQ

Q: 这篇文章说的"五大核心模块"是官方划分吗?

A: 不是,是我读源码后归纳的。官方没有公开架构文档。这个划分是为了帮助理解,不是源码里的命名。

Q: query.ts 和 QueryEngine.ts 有什么区别?

A: QueryEngine.ts 是会话对象,管理一次完整对话的上下文、历史、配置;query.ts 是主循环函数,负责单次"调用 API → 处理工具 → 再调用"的迭代。QueryEngine 持有并调用 query。

Q: 为什么用 Bun 而不是 Node.js?

A: 主要是启动速度和内置的 bun:bundle API。Claude Code 用 feature('FLAG_NAME') 做运行时 feature flag,这个机制依赖 Bun 的 bundle 能力,在 Node.js 下无法直接运行。

Q: 为什么终端 UI 用 React?CLI 不是直接打印字符串就行了吗?

A: 简单 CLI 确实可以。但 Claude Code 的终端 UI 有实时流式输出、工具执行进度、多行动态更新等需求。React + Ink 让你用组件模型管理这些状态,比手动操控 ANSI 转义码要可维护得多。

Q: 子 Agent 和主 Agent 共享上下文吗?

A: 不共享。子 Agent 有独立的消息历史和 tool pool,通过 AgentTool 的输入/输出与主 Agent 通信。这是有意的隔离设计,防止子任务污染主上下文。