模块一:基础认知 | 前置依赖:无 | 预计学习时间:60 分钟
学习目标
完成本课后,你将能够:
- 说清楚 Claude Code 是什么,以及它为什么不仅仅是一个 CLI 工具
- 画出一次用户交互的完整数据流(从输入到响应的 7 个阶段)
- 将 50+ 个源码目录按职责归类到 6 大类别中
- 识别出最核心的 4 个文件及其角色
1.1 Claude Code 到底是什么?
常见误解
很多人第一次接触 Claude Code 时会认为它"只是一个调用 Claude API 的命令行工具"。这个认知大概只对了 10%。
准确定义
Claude Code 是一个基于 React 的终端 AI Agent 系统。 拆开来看这三个关键词:
- 基于 React:它用 React 渲染终端 UI(通过一个叫 Ink 的终端 React 渲染器),拥有组件、状态管理、Context、Hooks — 与你在浏览器中用 React 写 Web 应用的体验高度一致。
- 终端:运行在终端中而非浏览器中,但其 UI 复杂度远超普通 CLI — 有 diff 视图、权限弹窗、进度条、多面板布局。
- AI Agent 系统:不只是"发送消息、接收回复"。它有 40+ 种工具、多层权限体系、子 Agent 生成、多 Agent 协调、后台任务管理、记忆系统、上下文压缩 — 是一个完整的 Agent 运行时。
数字感受规模
| 指标 | 数值 |
|---|---|
| 顶层目录数 | 38 个 |
| 顶层 TS/TSX 文件数 | 18 个 |
| main.tsx 文件大小 | 803 KB / ~4,700 行 |
| 工具(Tool)数量 | 40+ 种 |
| UI 组件数量 | 146 个子目录 |
| Ink 渲染引擎文件数 | 50+ 个 |
| Hook 文件数 | 70+ 个 |
| 服务(Service)数量 | 18 个子模块 |
| 编译时 Feature Flag | 12 个 |
| 迁移脚本 | 16 个 |
这个规模已经远超一般的 CLI 工具,它更接近一个中等规模的 Web 应用。
1.2 核心数据流:一次交互的完整旅程
当你在终端里输入一句话并按下回车,以下 7 个阶段会依次发生:
┌─────────────────────────────────────────────────────────────────┐
│ 一次用户交互的完整数据流 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 用户输入 │
│ │ │
│ ▼ │
│ ① PromptInput 组件接收输入 │
│ │ (components/PromptInput/) │
│ ▼ │
│ ② REPL 处理并创建 UserMessage │
│ │ (screens/REPL.tsx → onSubmit → handlePromptSubmit) │
│ ▼ │
│ ③ query() 构建请求并调用 Claude API │
│ │ (query.ts → queryLoop → callModel) │
│ ▼ │
│ ④ 流式接收 Claude 响应 │
│ │ (包含 text 和/或 tool_use 块) │
│ ▼ │
│ ⑤ 如果有 tool_use → 权限检查 → 执行工具 │
│ │ (Tool.ts → checkPermissions → call) │
│ ▼ │
│ ⑥ 工具结果返回,追加到消息列表 │
│ │ (tool_result → messages → 可能触发下一轮 API 调用) │
│ ▼ │
│ ⑦ 渲染最终响应到终端 │
│ │ (ink/ 渲染引擎 → 终端输出) │
│ ▼ │
│ 等待下一次用户输入... │
│ │
└─────────────────────────────────────────────────────────────────┘
阶段详解
① 输入捕获(PromptInput)
用户在终端中键入文字。components/PromptInput/ 组件负责接收键盘事件,支持多行编辑、Vim 模式、自动补全等。按下回车后,输入文本被传递给 REPL。
② REPL 处理(screens/REPL.tsx)
REPL 是整个应用的主屏幕。它的 onSubmit 回调做以下事情:
- 判断是否是本地命令(如
/help、/clear),如果是则直接处理 - 否则创建一个
UserMessage对象 - 调用
query()函数,启动 Agent 循环
onSubmit(input) → 是本地命令?→ 是 → 直接执行
→ 否 → 创建 UserMessage → query()
③ 构建请求并调用 API(query.ts)
query() 是一个异步生成器函数(async function*),这是整个系统的心脏。它做的事情:
- 检查是否需要压缩上下文(token 预算管理)
- 构建完整的消息数组(历史消息 + 新消息)
- 附加 System Prompt(工具说明、环境信息、记忆等)
- 调用
callModel()发送到 Claude API - 流式接收响应
// query.ts 的核心签名(简化)
export async function* query(params: QueryParams): AsyncGenerator<StreamEvent> {
// ... 压缩检查、消息构建、API 调用、工具执行循环
}
④ 流式响应接收
Claude API 返回的响应是流式的,包含两种内容块:
- text 块:Claude 的文字回复,直接展示给用户
- tool_use 块:Claude 请求调用某个工具(如读取文件、执行命令)
// Claude API 响应示例(简化)
{
"content": [
{ "type": "text", "text": "让我看看这个文件的内容。" },
{ "type": "tool_use", "name": "Read", "input": { "file_path": "/src/index.ts" } }
]
}
⑤ 工具执行
如果响应中包含 tool_use 块,Agent 循环进入工具执行阶段:
- 查找工具:
findToolByName()在注册表中定位对应的 Tool 实现 - 权限检查:
checkPermissions()判断是否需要用户确认 - 用户确认(如果需要):终端弹出权限请求,用户选择 Allow/Deny
- 执行:调用
tool.call()执行实际操作 - 收集结果:将执行结果封装为
tool_result消息
tool_use 块 → findToolByName() → checkPermissions()
→ allow → tool.call() → tool_result
→ deny → 拒绝消息 → tool_result(error)
⑥ 循环继续
工具结果被追加到消息列表中,然后 回到阶段 ③,再次调用 Claude API。Claude 看到工具结果后可能:
- 生成最终的文字回复(循环结束)
- 请求调用更多工具(循环继续)
这就是 Agent 循环的本质:API 调用和工具执行之间不断往返,直到 Claude 决定不再需要调用工具。
while (true) {
response = callAPI(messages)
if (response 包含 tool_use) {
results = executeTools(response.tool_use)
messages.append(results)
continue // 继续循环
} else {
break // 循环结束
}
}
⑦ 渲染输出
最终的文字响应通过 Ink 渲染引擎显示到终端。渲染管线包含三个阶段:
- React 虚拟 DOM → Ink 节点树(
render-node-to-output) - Ink 节点树 → 终端字符矩阵(
render-to-screen) - 字符矩阵 → 终端输出(
terminal.ts)
1.3 目录结构全景
38 个顶层目录和 18 个顶层文件,按职责分为 6 大类别:
类别一:核心引擎(Core Engine)
驱动 Agent 循环运转的基础设施。
| 目录/文件 | 职责 |
|---|---|
entrypoints/ | 三种入口:CLI(cli.tsx)、MCP Server(mcp.ts)、Agent SDK(sdk/) |
main.tsx | 800KB 的粘合层:CLI 参数解析、初始化序列、模块组装 |
query.ts | Agent 循环核心:API 调用 → 流式处理 → 工具分发 → 上下文压缩 |
QueryEngine.ts | 多消息查询引擎,兼容 SDK 模式 |
state/ | 全局状态管理:AppState / Store 模式 / 不可变更新 |
context.ts | 系统上下文构建:Git 状态、环境信息、记忆注入 |
commands.ts | 中央命令注册表,导入 100+ 个命令定义 |
cli/ | CLI 命令解析框架 |
类别二:工具与权限(Tools & Permissions)
Agent 的"手和脚" — 所有与外界交互的能力。
| 目录/文件 | 职责 |
|---|---|
Tool.ts | 工具接口定义:类型体系、生命周期、权限检查 |
tools.ts | 工具注册表:动态导入、Feature Gate 过滤 |
tools/ | 40+ 种工具实现:Bash、FileEdit、Glob、Grep、Agent、MCP、Task 等 |
Task.ts | 后台任务类型定义和状态管理 |
tasks.ts | 任务工厂:返回所有任务实现 |
tasks/ | 任务执行系统(本地、远程、Agent、工作流) |
skills/ | 技能系统:内置技能加载、MCP 技能构建 |
commands/ | 100+ 个命令实现(/commit, /diff, /cost 等) |
类别三:UI 与交互(UI & Interaction)
用户看到和操作的一切。
| 目录/文件 | 职责 |
|---|---|
screens/ | 全屏 UI:REPL(主交互)、Doctor(诊断)、ResumeConversation(会话恢复) |
components/ | 146 个 React 组件:输入框、消息列表、权限弹窗、Diff 视图、设计系统 |
ink/ | 终端 React 渲染引擎(50 文件):渲染管线、按键解析、颜色、布局 |
ink.ts | 渲染入口包装:ThemeProvider 注入 |
keybindings/ | 键绑定系统:默认绑定、解析器、用户自定义加载 |
hooks/ | 70+ 个 React Hook:工具权限、队列处理、设置管理、语音等 |
context/ | React Context 集合:通知、邮箱、语音、性能指标 |
outputStyles/ | 输出格式化策略 |
replLauncher.tsx | REPL 异步初始化入口 |
dialogLaunchers.tsx | 对话框动态加载器 |
interactiveHelpers.tsx | 用户输入事件处理 |
类别四:服务与基础设施(Services & Infrastructure)
后台运行的引擎和管道。
| 目录/文件 | 职责 |
|---|---|
services/ | 18 个子模块:API 客户端、分析、计费、记忆、压缩、MCP、插件等 |
constants/ | 共享常量:System Prompt 组装、Beta 特性、安全指令、API 限制 |
types/ | TypeScript 类型定义:消息、权限、工具、插件 |
schemas/ | Zod Schema 定义 |
utils/ | 330+ 个工具函数:日志、文件操作、Git、认证、安全等 |
migrations/ | 16 个配置迁移脚本:模型默认值、Feature Flag、权限等 |
bootstrap/ | 应用启动序列:状态初始化、配置加载 |
server/ | API 服务端处理 |
cost-tracker.ts | Token 用量和费用计算 |
costHook.ts | 费用摘要展示 Hook |
setup.ts | 首次运行设置和会话初始化 |
history.ts | 会话命令历史 |
projectOnboardingState.ts | 项目引导步骤追踪 |
类别五:扩展与集成(Extension & Integration)
与外部系统对接的能力。
| 目录/文件 | 职责 |
|---|---|
plugins/ | 插件架构:内置插件加载、安装/卸载/启用/禁用 |
coordinator/ | 多 Agent 协调模式:Coordinator-Worker 编排 |
bridge/ | claude.ai 集成(33 文件):JWT 认证、WebSocket 会话、受信设备 |
remote/ | 远程 Agent 通信:会话管理、WebSocket、权限桥接 |
upstreamproxy/ | 上游 API 代理中继:容器感知、反 ptrace、CA 证书 |
native-ts/ | 原生代码绑定和 OS 级集成 |
moreright/ | 扩展面板功能 |
类别六:特殊功能(Special Features)
隐藏的彩蛋和实验性功能。
| 目录/文件 | 职责 |
|---|---|
assistant/ | KAIROS — 始终在线的主动式 Assistant(Feature-gated) |
buddy/ | Tamagotchi 式伴侣宠物系统(Feature-gated) |
voice/ | 语音输入模式(Feature-gated) |
vim/ | Vim 键绑定模式:motions、operators、text objects |
memdir/ | 持久化记忆目录系统 |
query/ | 查询构建和检索 |
public/ | 静态资源(截图等) |
1.4 最核心的四个文件
如果整个代码库只能读 4 个文件,读这四个:
① Tool.ts — 工具接口定义(~300 行类型)
为什么最重要: 工具是 Agent 的核心能力。所有 40+ 种工具都实现这一个接口。理解了 Tool.ts,你就理解了 Claude Code 能做什么、怎么做、以及做之前需要检查什么。
你会看到:
Tool<Input, Output, ProgressData>泛型接口- 核心方法:
call()(执行)、checkPermissions()(权限)、inputSchema(Zod 校验) - 元数据标记:
isReadOnly()、isDestructive()、isConcurrencySafe() - 展示方法:
renderToolUseMessage()、renderToolResultMessage()
② query.ts — Agent 循环核心
为什么最重要: 这是整个系统的"心跳"。每一次用户交互最终都会流经这个文件。理解了 query.ts,你就理解了 Agent 如何"思考-行动-观察"循环运作。
你会看到:
query()异步生成器函数- API 调用与流式处理
- tool_use 检测与工具执行分发
- 上下文压缩触发逻辑
- 错误恢复与模型降级
③ constants/prompts.ts — System Prompt 组装
为什么最重要: System Prompt 决定了 Claude 在 Claude Code 中的"人格"和"能力边界"。这不是一个简单的字符串,而是一个由十几个模块化节段动态拼装的复杂系统。
你会看到:
getSystemPrompt()主组装函数- 静态节(跨用户可缓存)与动态节(每会话变化)的分区
- 工具说明、记忆注入、环境信息、MCP 指令的集成方式
④ state/AppStateStore.ts — 全局状态结构
为什么最重要: 所有运行时数据都存储在 AppState 中。理解了状态结构,你就知道系统在任意时刻"知道"哪些信息。
你会看到:
- messages(对话历史)
- tools(已注册工具列表)
- permissions(权限模式和规则)
- speculation(乐观更新状态)
- MCP connections、notifications、UI state 等
1.5 架构分层视角
从另一个角度理解 Claude Code — 从上到下的六层架构:
┌──────────────────────────────────────────────┐
│ 用户界面层 (UI Layer) │
│ screens/ · components/ · ink/ · keybindings/ │
├──────────────────────────────────────────────┤
│ 交互管理层 (Interaction Layer) │
│ hooks/ · context/ · state/ · commands/ │
├──────────────────────────────────────────────┤
│ Agent 循环层 (Agent Loop Layer) │
│ query.ts · QueryEngine.ts · context.ts │
├──────────────────────────────────────────────┤
│ 工具执行层 (Tool Execution Layer) │
│ Tool.ts · tools.ts · tools/ · skills/ │
├──────────────────────────────────────────────┤
│ 权限与安全层 (Security Layer) │
│ permissions · bashSecurity · pathValidation │
├──────────────────────────────────────────────┤
│ 服务与 API 层 (Service & API Layer) │
│ services/ · constants/ · utils/ · bridge/ │
└──────────────────────────────────────────────┘
每一层只依赖下方的层(少数例外情况存在,但总体遵循这个方向)。这使得你可以自上而下或自下而上学习,而不必同时理解所有层。
1.6 与其他 AI Agent 框架的对比
把 Claude Code 放在更大的 AI Agent 生态中来看:
| 维度 | Claude Code | LangChain/LangGraph | AutoGPT | Cursor |
|---|---|---|---|---|
| 运行环境 | 终端 (React/Ink) | 服务端 (Python) | 服务端 (Python) | IDE (Electron) |
| 工具系统 | 内置 40+,自定义通过 MCP | 社区集成,Tool 接口 | 插件式 | 内置 + LSP |
| 多 Agent | Coordinator-Worker + Swarm | LangGraph 编排 | 任务分解 | 单 Agent |
| 权限模型 | 4 种模式 + ML 分类器 | 无内置 | 无内置 | IDE 沙箱 |
| 记忆系统 | SessionMemory + autoDream | 外部向量数据库 | 文件记忆 | 会话内 |
| 上下文管理 | 多级压缩 + token 预算 | 手动管理 | 简单截断 | 自动 |
Claude Code 的独特之处在于:它是极少数将 Agent 运行时、工具系统、权限模型、记忆系统、UI 渲染全部自包含在一个应用中的产品级实现。大多数框架只解决其中 1-2 个问题。
课后练习
练习 1:绘制模块关系图
用任何工具(纸笔、draw.io、Mermaid)绘制 Claude Code 的核心模块关系图。至少包含以下模块,并标注它们之间的调用/数据流向:
- PromptInput
- REPL
- query()
- Claude API
- Tool Registry
- Permission System
- Ink Renderer
- AppState
- SessionMemory
练习 2:分类 38 个目录
不看本课内容,尝试将所有 38 个顶层目录分到 6 大类别中。然后对照本课的分类,看看你的判断有哪些出入,思考为什么。
练习 3:追踪一次文件读取
假设用户输入"帮我看看 src/index.ts 的内容",追踪这次交互涉及的所有文件和函数。提示:
- 用户输入在哪里被接收?
query()在哪里被调用?- Claude 返回的
tool_use会指定哪个工具? - 权限检查在哪里发生?
- 文件内容在哪里被读取?
- 结果如何返回给 Claude?
练习 4:五个核心目录
在 38 个目录中选出你认为最核心的 5 个,按重要性排序。给每个目录写一句话说明为什么它是核心的。然后与同学/朋友讨论你们的选择差异。
本课小结
| 要点 | 内容 |
|---|---|
| Claude Code 本质 | 基于 React 的终端 AI Agent 系统,不仅仅是 CLI |
| 核心数据流 | 输入 → REPL → query() → API → tool_use → 执行 → 渲染(7 阶段循环) |
| Agent 循环关键 | query.ts 的 while(true) 循环 — 在 API 调用和工具执行之间往返 |
| 目录分类 | 6 大类别:核心引擎、工具权限、UI 交互、服务基础设施、扩展集成、特殊功能 |
| 最核心文件 | Tool.ts、query.ts、constants/prompts.ts、state/AppStateStore.ts |
| 架构特点 | 六层分层架构,自包含的 Agent 运行时 |
下一课预告
第 02 课:技术栈深度解析 — 我们将深入 Bun 运行时的 feature() 编译时替换机制、Ink 终端 React 渲染器的工作原理、以及 Zod 如何同时服务于运行时校验和 TypeScript 类型推导。理解了技术栈,你才能看懂代码中那些"看起来不像普通 TypeScript"的部分。