第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.ts 和 QueryEngine.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. 如果你能访问 Claude Code 的源码,试着用
ls命令列出src/下的所有目录,和本章的描述对照看看 - 2. 打开
src/tools/目录,数一数里面有多少个子目录——每个子目录就是一个工具 - 3. 想想看:如果你要给 Claude Code 加一个新工具(比如一个"翻译工具"),你觉得应该在哪里加代码?
一个重要的能力:读代码
在正式深入源码之前,分享一个重要的技巧:读代码和写代码是不同的能力。
写代码时,你是从零开始创造。读代码时,你需要理解别人的思路。两者需要不同的策略。
读大型源码的策略:
- 1. 先看地图,再看细节(本章就是地图)
- 2. 跟踪数据流——选一个输入,跟踪它是怎么流过系统的
- 3. 从入口开始——找到 main 函数,从那里开始读
- 4. 善用搜索——看到一个函数调用,搜索它的定义
- 5. 不要试图一次读完——每次专注于理解一个模块
最重要的是:不要害怕看不懂。 即使是经验丰富的工程师,第一次看一个新项目也会一头雾水。理解一个大型项目需要时间和耐心。
下一章,我们将快速复习 TypeScript 和 React 的基础知识,为深入源码做准备。
本书由 everettjf 使用 Claude Code 分析泄露源码编写 | 保留出处即可自由转载