项目全景与模块地图
今天不写代码。目标:搞清"这是个什么项目、用什么造的、代码分成哪几大块",在脑子里建立一张地图。今天是第 1 周(建立心智)的起点,为明天 Day 02 追启动链打地基。
它到底是什么
我们要读的仓库叫 claude-code-best(简称 CCB)。package.json 第 2-3 行写得很清楚:
"name": "claude-code-best",
"version": "2.8.3",
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal"
翻译过来:它是 Anthropic 官方 Claude Code CLI(那个在终端里跟你结对编程的 AI 助手)的逆向工程 / 反编译后完整重写的 TypeScript 版本。CLAUDE.md:7 也明说 "This is a reverse-engineered / decompiled version of Anthropic's official Claude Code CLI tool."
🎯 一句话:它是跑在终端里的 AI 编程 Agent——你用自然语言下命令,它自己调用工具(读写文件、跑命令、搜代码…)把编程任务干完。我们要逐层读懂"这样一个 Agent 内部怎么运转"。
它甚至比官方版功能更多:README(README.md:19-37)列出它额外实现了 Goal 持续驱动、Artifacts HTML 托管、Ultracode 多 Agent 编排、Remote Control 远程控制、Voice 语音、Web Search 等——而且"关闭了外部封控点"、完全兼容官方配置文件。
逆向 ≠ 薄封装
很多人以为"复刻一个 CLI"就是包一层调官方的包。CCB 完全不是。它没有运行时依赖官方 @anthropic-ai/claude-code 包,而是自己从头重实现了每一个子系统:agent 循环、工具系统、终端 UI、MCP、skills、hooks、workflow 引擎……
官方的 @anthropic-ai/claude-agent-sdk 只作为 devDependency(package.json:85)存在——只用来对齐类型/协议定义,运行时一点不依赖它。
先建立"一个 AI Agent"的直觉
零基础最需要先有的一个直觉——Agent 不是"聊天机器人",它会"动手"。区别在于:
- 聊天机器人:你问,它答(只输出文字)。
- Agent:你给个目标,它自己反复调用工具(读文件、改代码、跑测试),观察结果,再决定下一步,直到把事办完。
所以这个 CLI 的灵魂是一个循环(就是总目录页那个转圈动画):
这个循环在本项目由 src/query.ts + src/QueryEngine.ts 驱动(Day 03、06 细讲)。今天你只要记住"Agent = 模型 + 工具 + 一个不停转的循环"。
把 README 里所有 "颜色" 改成 "color"🗣️ 聊天机器人:输出一段文字"你可以打开 README,用查找替换……"(只是教你怎么做)。
🤖 Agent(本项目):调
Read 读 README → 调 Edit 真替换 → 调 Read 复查 → 回一句已改 3 处 ✅(它自己动手把事办完了)。👶 小白:那它会不会一直转、停不下来?
👨🏫 老师:不会。每一轮模型都会明确表态——"我还要调工具" 就继续转,"我说完了(没有工具请求)" 循环就停,把结果显示给你。判断"继续还是停"的那段代码 Day 03 会单步走给你看。
技术栈
| 方面 | 选型 | 出处 / 备注 |
|---|---|---|
| 运行时 | Bun(不是 Node!) | .tool-versions 锁 bun 1.3.13;产物也兼容 node |
| 语言 | TypeScript(strict) | tsconfig.json:8,ESM 模块 |
| 终端 UI | React 19 + Ink(自研 fork @anthropic/ink) | 用 React 写、渲染到终端;Day 04 细讲 |
| CLI 框架 | Commander | 解析命令行参数/子命令 |
| 校验 | zod | 工具输入 schema 等 |
| Lint/格式化 | Biome | biome.json |
| 构建 | Bun.build + Vite 双管线 | Day 02/20 细讲 |
| 模型供应商 | Anthropic + OpenAI + Bedrock + Vertex + Gemini + Grok… | 7 个供应商,Day 17 讲 |
Ink 是"能用 React 写终端界面"的库——你写的还是
<Box><Text> 这种组件,但它渲染成的不是网页,而是终端里的字符。这就是为什么这个 CLI 里有 700+ 个 .tsx 文件。
项目规模画像
先有个体量的心理准备(别怕,我们会拆开读):
src/ 下按文件数排:utils/(773)、components/(418)、commands/(400)、services/(301)、hooks/(119)…… 数量最大的是工具函数和 UI 组件,这很正常——一个成熟 CLI 大量代码花在"界面"和"打杂"上,真正的"agent 大脑"反而集中在少数几个文件里。
src/query.ts + src/QueryEngine.ts(大脑)、src/Tool.ts + packages/builtin-tools(手脚)、src/screens/REPL.tsx(界面)。本教程主要围绕它们,不会让你陷进 773 个 utils 里。核心模块地图
这是本教程最重要的一张图——记住这几大块各在哪、干什么,后面每天都是往里钻:
① Agent 查询循环
核心大脑:发消息、处理流式响应、执行 tool calls、管理一轮对话。Day 03/06/10
② 工具系统
手脚:~60 个工具(读写文件、Bash、搜索、子代理…)。Day 07/08
③ 终端 UI (Ink)
脸面:消息列表、输入框、权限弹窗,全用 React 渲染到终端。Day 04/18
④ Slash 命令
"/help /model /compact" 等斜杠命令。Day 11
⑤ Services 服务层
API 客户端、MCP、分析、oauth、SessionMemory 等后台服务。Day 17
⑥ MCP / Skills / Hooks
扩展能力:接外部工具、技能、生命周期钩子。Day 12/13/14
⑦ Workflow 引擎
多 Agent 编排(Ultracode)。Day 19
⑧ Bridge / Remote
远程控制:手机/web 控制终端里的 Claude Code。Day 19
monorepo 包一览
package.json:32-36 定义 workspaces = packages/*、packages/@ant/*、packages/@anthropic-ai/*。关键包:
| 包 | 用途 |
|---|---|
builtin-tools | ★ 内置工具集(~60 个 tool 实现)。Day 08 精读 |
agent-tools | 子代理相关工具 |
mcp-client | ★ MCP 客户端库。Day 12 |
workflow-engine | 确定性 JS 脚本编排引擎(多 agent,端口适配器模式)。Day 19 |
remote-control-server | 自托管远程控制服务端(React+Vite Web UI,Docker 部署)。Day 19 |
@ant/ink | ★ fork 的 Ink 终端 UI 框架本体。Day 04 |
acp-link / cloud-artifacts / weixin | ACP 桥接 / HTML 托管 / 微信集成 |
*-napi(audio/image/color-diff/modifiers/url) | 原生能力(音频/图像/颜色/键盘修饰键/URL)。Day 20 |
packages/* 里每个子目录都是一个能独立发布的包,但它们共享顶层的依赖锁和构建。napi 指用原生代码(非 JS)实现的能力,比如音频捕获——JS 干不了的活交给原生。bin 入口:命令怎么映射到代码
装好后你会得到几个命令行入口(package.json:27-31):
"bin": {
"ccb": "dist/cli-node.js", // 用 node 跑
"ccb-bun": "dist/cli-bun.js", // 用 bun 跑
"claude-code-best": "dist/cli-node.js"
}
这些 cli-*.js 是构建生成的极薄 shim(就一行 import "./cli.js"),真正的产物是 dist/cli.js,它打包自源码入口 src/entrypoints/cli.tsx。所以完整映射链是:
你敲 ccb
→ dist/cli-node.js (#!/usr/bin/env node, 一行 import)
→ dist/cli.js (打包产物)
→ src/entrypoints/cli.tsx (真正的源码入口 ★)
src/entrypoints/cli.tsx 这个入口文件——明天 Day 02 我们就从它开始,一步步追到界面渲染出来。读任何 CLI 项目,"找到真正的入口文件"永远是第一步。读源路线 & 必知的坑
三条主线(贯穿本教程)
纵向:跟一次对话走完全程
从 cli.tsx 启动 → REPL 界面 → 你输入 → query 循环 → 调工具 → 返回。这是理解全局的主线。
横向:吃透工具系统
从 Tool 接口到一个具体工具(如 Edit)的完整生命周期。理解 Agent"手脚"的主线。
扩展:MCP / Skills / Hooks / Workflow
Agent 如何被外部能力增强。理解可扩展性的主线。
⚠️ 必知的坑
- 文档滞后于代码:
CLAUDE.md里写"当前版本 2.2.1"、"main.tsx ~5674 行",而实际package.json是 2.8.3、main.tsx 5640 行。一律以源码为准,文档是快照。 - CLAUDE.md 和 AGENTS.md 几乎是同一份(AGENTS.md 开头标题甚至写着 "# CLAUDE.md")——两个副本供不同 AI 读取,别以为是两份不同文档。
- 用的是 Bun 不是 Node:很多 import、构建、执行走 Bun API。产物靠构建时打补丁做到 node/bun 双跑(Day 02 讲)。
- 用的是自研 fork 的 Ink(
@anthropic/ink),不是社区ink包;还用了 React Compiler(产物里满是_c()memo 调用)。
今日小结 + 动手
🧠 今天你应该能回答
- CCB 是什么?(逆向重写的 Claude Code CLI,不是薄封装,功能更多)
- "Agent" 和"聊天机器人"的区别?(Agent 会调工具、循环干活)
- 技术栈?(Bun + TS + React/Ink)
- 核心模块地图的 8 大块 + 各在哪个目录?
- 真正的源码入口是哪个文件?(
src/entrypoints/cli.tsx)
✋ 动手 5 分钟(可选)
# 1. 确认项目身份
cd claude-code
head -10 package.json # 看 name/description
sed -n '1,10p' CLAUDE.md # 看"逆向"声明
# 2. 感受规模
find src -name '*.ts' -o -name '*.tsx' | wc -l
for d in src/*/; do echo "$(find $d -name '*.ts*'|wc -l) $d"; done | sort -rn | head
# 3. 看 bin 映射和入口
sed -n '27,36p' package.json
ls src/entrypoints/
# 4. 看 monorepo 包
ls packages/
src/entrypoints/cli.tsx 出发,看清"敲下 ccb 到终端里出现交互界面"这一路上代码到底怎么跑——一个巨大的 fast-path 分发器、Bun 构建、以及 REPL 是怎么挂载起来的。