第2章:源码全景地图

打开宝箱之前,先看看地图

想象你要去一座大城市旅游。你不会一下飞机就到处乱逛——你会先看看地图,了解城市的大致布局:市中心在哪里、主要道路怎么走、各个景点分布在哪里。

读源码也是一样。在我们深入任何一个文件之前,先让我们从高空俯瞰整个项目的结构。

项目的数字

让我们先用一些数字来感受这个项目的规模:

指标数值
TypeScript 文件数~1,884 个
总代码行数~512,000 行
主要目录数55 个
工具数量40+ 个
斜杠命令数50+ 个
React 组件数146 个
React Hooks 数87 个

50 万行代码是什么概念?如果你每天读 500 行,需要将近三年才能全部读完。但别担心——我们不需要读每一行。就像读一本字典,你不需要读完每个词条,只需要知道怎么查找就好。

目录结构总览

Claude Code 的源代码都在 src/ 目录下。让我们看看最重要的几个目录:


src/
├── main.tsx              ← 程序入口,一切从这里开始
├── query.ts              ← 查询引擎,处理与 AI 的对话
├── QueryEngine.ts        ← 查询引擎核心,管理 API 调用
├── tools.ts              ← 工具注册中心
├── Tool.ts               ← 工具的类型定义
├── commands.ts           ← 命令注册中心
│
├── tools/                ← 所有工具的实现(45 个子目录)
│   ├── BashTool/         ← 执行终端命令
│   ├── FileReadTool/     ← 读取文件
│   ├── FileEditTool/     ← 编辑文件
│   ├── FileWriteTool/    ← 创建文件
│   ├── GlobTool/         ← 按模式搜索文件名
│   ├── GrepTool/         ← 搜索文件内容
│   ├── AgentTool/        ← 创建子智能体
│   ├── WebFetchTool/     ← 获取网页内容
│   ├── WebSearchTool/    ← 搜索网页
│   └── ...               ← 还有很多
│
├── commands/             ← 所有斜杠命令的实现(103 个子目录)
│   ├── commit/           ← /commit 命令
│   ├── compact/          ← /compact 命令
│   ├── review/           ← /review 命令
│   └── ...
│
├── components/           ← 终端 UI 组件(146 个文件)
│   ├── App.tsx           ← 根组件
│   ├── FullscreenLayout/ ← 主界面布局
│   ├── PermissionRequest/← 权限请求对话框
│   └── ...
│
├── hooks/                ← React Hooks(87 个文件)
│   ├── useCanUseTool.ts  ← 权限检查
│   ├── useArrowKeyHistory← 上下键历史
│   └── ...
│
├── services/             ← 服务层(38 个模块)
│   ├── api/              ← Claude API 调用
│   ├── mcp/              ← MCP 协议实现
│   ├── analytics/        ← 数据分析
│   └── ...
│
├── state/                ← 全局状态管理
├── types/                ← TypeScript 类型定义
├── utils/                ← 工具函数(331 个文件)
├── context/              ← 上下文收集
├── bridge/               ← IDE 集成桥接
├── coordinator/          ← 多智能体协调
├── skills/               ← 技能系统
├── plugins/              ← 插件系统
├── memdir/               ← 记忆系统
├── entrypoints/          ← 不同启动模式
├── screens/              ← 全屏界面
├── keybindings/          ← 快捷键配置
├── tasks/                ← 任务管理
├── remote/               ← 远程会话
├── vim/                  ← Vim 模式
├── voice/                ← 语音输入
├── server/               ← 服务器模式
├── migrations/           ← 配置迁移
└── constants/            ← 常量定义

用"城市"来理解架构

如果把 Claude Code 比作一座城市,那么:

🏛️ 市政厅——main.tsx

这是整个城市的行政中心。所有的事情都从这里开始。当你在终端输入 claude 命令时,main.tsx 是第一个被执行的文件。它负责:

  • - 解析你输入的命令行参数
  • - 初始化各种服务
  • - 启动终端界面

🧠 大脑——query.tsQueryEngine.ts

这是城市的"大脑",负责与 Claude AI 的所有对话。当你问 Claude 一个问题时,你的消息会经过这里被处理、发送给 API、然后把回复带回来。

query.ts 有约 68,000 行代码,是整个项目中最大的文件之一。它就像城市的交通指挥中心——所有的信息流都经过这里。

🔧 工具工厂——tools/ 目录

这是城市的"工业区",有 45 个"工厂",每个工厂生产一种"工具"。当 Claude 说"我需要读一个文件"时,FileReadTool 工厂就会启动;当它说"我需要运行一个命令"时,BashTool 工厂就会开工。

🎨 显示屏——components/ 目录

这是城市的"展览中心",负责把所有信息漂亮地显示在你的终端里。它用 React 和 Ink 框架来"画"终端界面——没错,终端里也能用 React!

🛡️ 安保系统——权限相关的代码

这是城市的"警察局",负责确保 AI 不会做危险的事情。每当 AI 想执行一个操作时,安保系统都会检查:"这个操作安全吗?用户允许吗?"

📮 邮局——services/ 目录

这是城市的"邮局",负责与外部世界的通信:调用 API、连接 MCP 服务器、收集分析数据等。

📝 档案馆——state/memdir/ 目录

这是城市的"档案馆",保存着程序的当前状态和跨会话的记忆。

数据流:一条消息的旅程

让我们跟踪一条消息,看看它在"城市"里是怎么流动的。

假设你输入了:帮我看看 index.ts 文件里有什么


1. 你的输入进入 main.tsx(市政厅)
   ↓
2. 经过 processUserInput()(安检处)
   - 检查:这是斜杠命令吗?不是
   - 检查:有没有需要执行的钩子?
   - 结果:这是一条普通消息
   ↓
3. 到达 query.ts(大脑)
   - 构建系统提示词(告诉 AI 它能做什么)
   - 组织对话历史
   - 发送给 Claude API
   ↓
4. Claude API 返回流式响应
   - AI 决定:"我需要用 FileReadTool 读取这个文件"
   - 返回一个 tool_use 块
   ↓
5. 进入权限检查(安保系统)
   - 检查:用户允许读取文件吗?
   - 结果:允许(读取是安全操作)
   ↓
6. FileReadTool 执行(工具工厂)
   - 读取 index.ts 的内容
   - 返回文件内容
   ↓
7. 工具结果返回给 Claude API
   - AI 看到了文件内容
   - AI 生成自然语言回复
   ↓
8. 回复显示在终端(显示屏)
   - 用 React/Ink 渲染
   - 代码有语法高亮
   ↓
9. 保存到会话记录(档案馆)

这就是一条消息的完整旅程。看起来很复杂,但每一步都有清晰的职责划分。

分层架构

Claude Code 的代码组织遵循一种叫做"分层架构"的模式。想象一个蛋糕,每一层都有不同的作用:


┌─────────────────────────────────────┐
│          UI 层(components/)        │  ← 你看到的界面
├─────────────────────────────────────┤
│        命令层(commands/)           │  ← 斜杠命令处理
├─────────────────────────────────────┤
│      查询层(query.ts)              │  ← 与 AI 对话
├─────────────────────────────────────┤
│      工具层(tools/)                │  ← 执行具体操作
├─────────────────────────────────────┤
│      服务层(services/)             │  ← 外部通信
├─────────────────────────────────────┤
│    状态层(state/)                  │  ← 数据存储
├─────────────────────────────────────┤
│   基础设施层(utils/)               │  ← 通用工具
└─────────────────────────────────────┘

每一层只依赖它下面的层,不依赖它上面的层。这就像一栋楼:一楼不需要知道二楼有什么,但二楼需要一楼的支撑。

这种设计的好处是:改变一层的实现,不会影响其他层。 比如,如果有一天 Claude Code 想把终端界面换成网页界面,只需要改 UI 层,其他层完全不用动。

核心设计理念

通过观察目录结构,我们已经可以看出 Claude Code 的几个核心设计理念:

1. 模块化

每个工具、每个命令、每个组件都是独立的模块,放在自己的目录里。这样你要理解 BashTool 是怎么工作的,只需要看 tools/BashTool/ 目录就好,不需要翻遍整个项目。

2. 关注点分离

界面的代码不知道 AI 怎么工作,AI 的代码不知道界面怎么画——每个部分只关心自己的事情。

3. 可扩展性

想加一个新工具?只需要在 tools/ 下新建一个目录,实现标准接口就行。想加一个新命令?在 commands/ 下新建目录就好。这种"插件式"的设计让系统很容易扩展。

4. 安全优先

权限系统、沙箱机制、危险命令检测——安全相关的代码占了很大的比重。这反映了一个重要理念:当 AI 能执行代码时,安全必须是第一优先级。

本章小结

  • - Claude Code 有约 50 万行代码,组织在 55 个主要目录中
  • - 核心文件包括:main.tsx(入口)、query.ts(查询引擎)、tools/(工具集)
  • - 代码采用分层架构:UI → 命令 → 查询 → 工具 → 服务 → 状态 → 基础设施
  • - 核心设计理念:模块化、关注点分离、可扩展、安全优先

动手练习

  1. 1. 如果你能访问 Claude Code 的源码,试着用 ls 命令列出 src/ 下的所有目录,和本章的描述对照看看
  2. 2. 打开 src/tools/ 目录,数一数里面有多少个子目录——每个子目录就是一个工具
  3. 3. 想想看:如果你要给 Claude Code 加一个新工具(比如一个"翻译工具"),你觉得应该在哪里加代码?

一个重要的能力:读代码

在正式深入源码之前,分享一个重要的技巧:读代码和写代码是不同的能力。

写代码时,你是从零开始创造。读代码时,你需要理解别人的思路。两者需要不同的策略。

读大型源码的策略:

  1. 1. 先看地图,再看细节(本章就是地图)
  2. 2. 跟踪数据流——选一个输入,跟踪它是怎么流过系统的
  3. 3. 从入口开始——找到 main 函数,从那里开始读
  4. 4. 善用搜索——看到一个函数调用,搜索它的定义
  5. 5. 不要试图一次读完——每次专注于理解一个模块

最重要的是:不要害怕看不懂。 即使是经验丰富的工程师,第一次看一个新项目也会一头雾水。理解一个大型项目需要时间和耐心。

下一章,我们将快速复习 TypeScript 和 React 的基础知识,为深入源码做准备。


本书由 everettjf 使用 Claude Code 分析泄露源码编写 | 保留出处即可自由转载