Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/00-目录与阅读指引.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
- 对 AI 应用开发感兴趣,想从真实产品中学习
- 希望理解大型 AI CLI 产品的架构设计

> **关于深度匹配**:本书部分章节会触达 Bun bundler、Dead Code Elimination、GrowthBook feature flag、Prompt Cache 字节对齐这类更进阶的话题。如果你对其中某个主题不熟悉,可以先跳过该节,主线不会受影响;想深挖时再回来——每个进阶话题都会自带一句话上下文,不要求你提前掌握。

### 阅读约定

- 正文使用中文,技术术语保留英文原文(如 Agent、Tool、System Prompt)
Expand Down
6 changes: 3 additions & 3 deletions docs/01-项目全景与四种入口形态.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

## 为什么要从全景开始?

当你面对一个约 1900 个源码文件(其中 TypeScript 文件约 1884 个)、核心文件超过 4000 行的大型项目时,最大的挑战不是读懂某个函数,而是**不知道从哪里开始读**。
当你面对一个约 1835 个 TypeScript 源码文件(含 `.tsx`)、最大单文件 `main.tsx` 4683 行的大型项目时,最大的挑战不是读懂某个函数,而是**不知道从哪里开始读**。

Claude Code 是 Anthropic 公司开发的 AI 驱动命令行编程助手。它不是一个简单的 API wrapper —— 它是一个完整的 AI Agent 运行时,包含了从终端 UI 渲染、多 Agent 编排、工具系统、权限安全到 Prompt 工程的全技术栈。理解它的全貌,等于理解了一个生产级 AI 产品的完整架构。

本章将回答四个核心问题:
1. **同一份源码是怎么对外露出的?** — `entrypoints/` 下四种入口形态(CLI / SDK / MCP server / Sandbox runner)共用一份代码
2. **为什么选择这些技术?** — Bun + TypeScript + Ink + Commander.js 的技术栈选型逻辑
3. **程序是怎么启动的?** — 从 `cli.tsx` 到 REPL 的启动链路
4. **代码是怎么组织的?** — 1884 个 TypeScript 文件的模块依赖全景
4. **代码是怎么组织的?** — 约 1835 个 TypeScript 文件的模块依赖全景

---

Expand Down Expand Up @@ -379,7 +379,7 @@ export async function launchRepl(

---

## 三、模块依赖全景:约 1900 个文件的组织方式
## 三、模块依赖全景:约 1835 个文件的组织方式

Claude Code 的源码按职责划分为 10+ 个顶层模块:

Expand Down
16 changes: 16 additions & 0 deletions docs/04-配置迁移即代码.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ resetProToOpusDefault.ts

11 个文件全部是顶层文件——没有子目录、没有公共基类、没有"框架",每个文件导出一个同名的无参函数,函数名就是它做的那件事。这种克制的组织方式背后有一个很清楚的意图:**每一次破坏性的配置改动,都是一段可以被独立 review、独立删除、独立写测试的小代码片段**。你不需要去理解一个"迁移引擎"——只需要打开你感兴趣的那个文件,从头读到尾,三五十行内它就讲完了自己的故事。

**11 个迁移函数速查表**

| 函数 | 分组 | 触发条件 | 一句话作用 | 错误处理 |
|---|---|---|---|---|
| `migrateAutoUpdatesToSettings` | 搬家(§2) | 无条件 | 把 `~/.claude.json` 的 `autoUpdates` 搬到 `~/.claude/settings.json` | try/catch + logError |
| `migrateBypassPermissionsAcceptedToSettings` | 搬家(§2) | 无条件 | 把 `bypassPermissionsModeAccepted` 搬到 settings | try/catch + logError |
| `migrateEnableAllProjectMcpServersToSettings` | 搬家(§2) | 无条件 | 把 `enableAllProjectMcpServers` 搬到 settings | try/catch + logError |
| `resetProToOpusDefault` | 模型字符串(§3) | 无条件 | Pro 默认从 Sonnet 翻成 Opus,靠横幅时间戳兜底 | 幂等早退 |
| `migrateSonnet1mToSonnet45` | 模型字符串(§3) | 无条件 | 把 `sonnet[1m]` 别名展开成 `sonnet-4-5-20250929[1m]` 显式串 | 幂等早退 |
| `migrateLegacyOpusToCurrent` | 模型字符串(§3) | 无条件 | 把 `claude-opus-4-0` 这种远古串收敛到 `opus` 别名 | 幂等早退 |
| `migrateSonnet45ToSonnet46` | 模型字符串(§3) | 无条件 | 把 `sonnet-4-5-*` 卷回 `sonnet` 别名 | 幂等早退 |
| `migrateOpusToOpus1m` | 模型字符串(§3) | 无条件 | 把 `opus` 升级成 `opus[1m]` | 幂等早退 |
| `migrateFennecToOpus` | 模型字符串(§3) | 仅内部版(`"external" === 'ant'`) | 把内部代号模型迁到 `opus` | 幂等早退 |
| `migrateReplBridgeEnabledToRemoteControlAtStartup` | 键名清理(§4) | 无条件 | `replBridgeEnabled` → `remoteControlAtStartup` | 幂等早退 |
| `resetAutoModeOptInForDefaultOffer` | 键名清理(§4) | `feature('TRANSCRIPT_CLASSIFIER')` | 让接受过老两选项弹窗的用户重看新三选项 | try/catch + 内层 completion flag |

本章按下面的顺序拆这 11 个函数:先看 `main.tsx` 里那条把它们串起来的流水线(§1),再分三组挨个看 —— 把字段从一处搬到另一处的 3 个(§2)、围绕模型字符串做重命名的 6 个(§3)、围绕"旧键名 / 旧弹窗选项"做清理的 2 个(§4),最后把贯穿全章的几条纪律收束起来(§5)。

---
Expand Down
4 changes: 2 additions & 2 deletions docs/06-SystemPrompt与OutputStyle注入.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ const codeStyleSubitems = [
]
```

注意最后一组注释指令**仅对内部版启用**(`process.env.USER_TYPE === 'ant'`)。源码中的注释标签 `@[MODEL LAUNCH]` 说明这是针对特定模型版本(Capybara)调整的 — 因为该模型默认过度注释,需要明确的反向引导。
注意最后一组注释指令**仅对内部版启用**(`process.env.USER_TYPE === 'ant'`)。源码中的注释标签 `@[MODEL LAUNCH]` 说明这是针对特定模型版本上线时的临时引导 — 因为该模型默认过度注释,需要明确的反向引导。

### 4.3 工具使用优先级:让模型用对工具

Expand Down Expand Up @@ -490,7 +490,7 @@ const providedToolSubitems = [
] : []),
```

这揭示了一个实际的模型问题 — AI 会倾向于「虚报成功」。源码注释 `@[MODEL LAUNCH]: False-claims mitigation for Capybara v8 (29-30% FC rate vs v4's 16.7%)` 表明 Capybara v8 模型的虚报率高达 29-30%,相比 v4 的 16.7% 显著上升,因此需要更强的提示词约束
这揭示了一个实际的模型问题 — AI 会倾向于「虚报成功」。源码注释 `@[MODEL LAUNCH]` 的措辞表明这是在新模型上线时观察到虚报率上升后加上的针对性约束,需要更强的提示词来兜底

### 4.5 输出效率:内外版的风格分水岭

Expand Down
2 changes: 1 addition & 1 deletion docs/08-PromptCache横切.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ Global cache 模式的核心思想是:**静态部分用 `global` scope 标记

当有非 defer 的 MCP 工具时,主查询路径会将 `globalCacheStrategy` 设为 `'none'`(`claude.ts:1225-1229`),并通过 `skipGlobalCacheForSystemPrompt` 使 System Prompt 降级到 `org` scope。这是因为 MCP 工具定义是用户级别的(不同用户配置的 MCP 服务器不同),使用 `global` scope 缓存 System Prompt 但工具定义不同,前缀无法整体匹配。

> **源码考古**:`GlobalCacheStrategy` 类型定义中还保留了 `'tool_based'` 值(`services/api/logging.ts:46`),但当前主查询路径只会产生 `'system_prompt'` 或 `'none'``'tool_based'` 可能是早期设计的遗留,或为未来的工具级缓存标记预留
> **源码考古(dead code 路径)**:`GlobalCacheStrategy` 类型定义中还保留了 `'tool_based'` 值(`services/api/logging.ts:46`),但当前主查询路径只会产生 `'system_prompt'` 或 `'none'`,**`'tool_based'` 在运行时永远不会出现**。它属于早期设计的遗留枚举值或为未来工具级缓存预留的占位——读者读到这里时知道它是 dead code 即可,不必再花精力理解它和当前缓存策略的关系

### 2.3 `systemPromptSection()` vs `DANGEROUS_uncachedSystemPromptSection()`

Expand Down
Loading