15 KiB
15 KiB
Claude Code 源码深度分析 (fazxes/Claude-code)
基于 2026年3月31日泄露源码重建版本 v2.1.88
源码: https://github.com/fazxes/Claude-code | ⭐218 | TypeScript | Bun
一、总览
Claude Code 是 Anthropic 的终端 AI 编程代理工具,核心思想是:
"一只生活在终端里的 AI,理解你的代码库,通过自然语言帮你写代码、执行任务"
技术栈:
- 运行时: Bun(不是 Node.js)
- 语言: TypeScript
- 编译: 单文件
build.ts→ 打包成dist/cli.js(~23MB单文件) - UI渲染: 自研 Ink 分支(
src/ink/)+ React 前端渲染 - 编排: Commander.js CLI 框架
- AI模型: Anthropic Claude (通过
@anthropic-ai/sdk)
二、核心架构(8层解构)
┌──────────────────────────────────────────────┐
│ CLI 入口 │
│ src/main.tsx → src/entrypoints/cli.tsx │
│ Commander.js 命令行解析 │
├──────────────────────────────────────────────┤
│ Session / Query 引擎 │
│ src/query.ts (68KB) — 核心对话循环 │
│ 路由、工具调用、权限、压缩、记忆 │
├──────────────────────────────────────────────┤
│ 系统提示词 (灵魂) │
│ src/constants/prompts.ts — 176行原则 │
│ 任务执行准则、工具使用、代码风格 │
├──────────────────────────────────────────────┤
│ 45个工具 (tools/) │
│ FileEdit/FileRead/FileWrite/Bash/Grep/ │
│ Glob/WebSearch/WebFetch/Agent/Task/ │
│ Skill/MCP/TodoWrite/AskUserQuestion... │
│ 每个工具独立目录,继承 Tool 基类 │
├──────────────────────────────────────────────┤
│ Hook 系统 (155文件) │
│ src/utils/hooks/ │
│ PreToolUse / PostToolUse / SessionStart │
│ / Notification / Stop / PreCompact... │
├──────────────────────────────────────────────┤
│ 插件系统 (65+文件) │
│ src/utils/plugins/ │
│ 加载 .claude/plugins/,支持bin/可执行文件 │
├──────────────────────────────────────────────┤
│ 权限系统 (精准控制) │
│ src/utils/permissions/ │
│ yoloClassifier.ts (52KB) — 自动模式逻辑 │
│ 三级权限: allow / ask / deny │
├──────────────────────────────────────────────┤
│ 服务层 (services/) │
│ MCP / LSP / 压缩 / 记忆 / 分析 / OAuth │
└──────────────────────────────────────────────┘
三、灵魂精华:系统提示词设计 (prompts.ts)
这是整个项目最重要的文件——它告诉 Claude 怎么当一个好的编程助手。
3.1 核心人格定义
你是一个交互式AI编程助手。
你的输出在等宽字体终端中渲染,使用 GitHub Flavored Markdown。
3.2 代码原则(最精华的 6 条)
- 只做被要求的 — 不增加需求以外的功能、重构、文档、类型注解
- 不做无谓防御 — 不为不可能发生的场景加错误处理/兼容代码
- 不做过早抽象 — 三次重复才考虑提取,一次性操作用完即弃
- 只加必要注释 — 只有 WHY 不明显时才注释,不说 WHAT(好变量名已经做到)
- 不留历史垃圾 — 不保留未用变量、空导出、
// removed注释 - 不说空话 — 不用"Great question!"、"I'd be happy to help"这样的 filler
3.3 风险和后果分层
| 风险级别 | 示例操作 | 策略 |
|---|---|---|
| 可逆+本地 | 编辑文件、跑测试 | 自由执行 |
| 中等风险 | 推送代码、修改CI/CD | 透明沟通后确认 |
| 高风险 | 删库、rm -rf、force-push | 必须确认 |
| 不可逆 | 删除分支、覆盖未提交变更 | 调查后再操作 |
3.4 遇到障碍时的行为准则
- 失败后先诊断原因,不盲目重试
- 不把破坏性操作当作"捷径"
- 遇到意外状态(陌生文件/分支/配置)先调查,不直接删除
- 冲突合并优先于丢弃变更
- "量两次,裁一次"(Measure twice, cut once)
3.5 工具使用纪律
专用工具优先于 Bash:
FileRead代替catFileEdit代替sed/awkFileWrite代替cat > heredocGlob代替findGrep代替grep/rg
并行调用: 能并发的工具调用全部并行发送,最大化效率
3.6 报告诚实原则
- 测试失败 → 如实报告,附完整输出
- 没做验证 → 说没做,不假装做了
- 状态确认 → 通过就说过,失败就说失败,不捏造"全部通过"
四、工具系统设计
4.1 Tool 基类 (src/Tool.ts, ~29KB)
export class Tool {
// 工具描述(发送给模型)
description(params: ToolDescriptionParams): string
// JSON Schema 输入定义
readonly inputSchema: z.ZodTypeAny
// 工具提示词(注入系统提示词)
get prompt(): string | undefined
// 权限检查
checkPermissions(input, context): PermissionResult
// 执行
call(input, context): ToolResultBlockParam[]
// 可被搜索到(ToolSearch)
isToolSearchable(): boolean
}
4.2 工具列表(45个)
| 分类 | 工具名 | 功能 |
|---|---|---|
| 文件 | FileReadTool | 读取文件(和bash跟踪联动) |
| FileEditTool | 精确编辑文件 | |
| FileWriteTool | 创建文件 | |
| GlobTool | 文件搜索 | |
| GrepTool | 内容搜索 | |
| 代码 | BashTool | 执行shell命令 |
| LSPTool | 语言服务器协议 | |
| NotebookEditTool | Jupyter Notebook 编辑 | |
| 网络 | WebSearchTool | 网页搜索 |
| WebFetchTool | 抓取网页内容 | |
| 任务 | TaskCreateTool | 创建任务 |
| TodoWriteTool | 写待办 | |
| TaskListTool | 列出任务 | |
| TaskUpdateTool | 更新任务 | |
| TaskOutputTool | 获取子任务输出 | |
| TaskStopTool | 停止任务 | |
| 代理 | AgentTool | 创建子代理(Explore/Plan/Verify) |
| SkillTool | 调用技能 | |
| MCP | MCPTool | MCP协议工具 |
| McpAuthTool | MCP认证 | |
| ReadMcpResourceTool | 读取MCP资源 | |
| ListMcpResourcesTool | 列出MCP资源 | |
| 交互 | AskUserQuestionTool | 向用户提问 |
| SendMessageTool | 发送消息 | |
| 计划 | EnterPlanModeTool | 进入计划模式 |
| ExitPlanModeTool | 退出计划模式 | |
| 其他 | SleepTool | 睡眠延迟 |
| ScheduleCronTool | 定时任务 | |
| VerifyPlanExecutionTool | 计划验证 | |
| BriefTool | 摘要 | |
| ToolSearchTool | 搜索工具 | |
| ConfigTool | 配置管理 | |
| RemoteTriggerTool | 远程触发 | |
| 内部 | REPLTool | REPL模式(仅Ant-内部) |
| TungstenTool | 调试工具(仅Ant-内部) | |
| SuggestBackgroundPRTool | 后台PR(仅Ant-内部) |
4.3 工具间的智能联动
Edit工具能看见Bash读过的文件:
// BashTool.tsx — 跟踪 cat/sed/head/tail 的输出
// 当用户用 bash 看过文件后, Edit 不需要再 Read
// "Edit works on files viewed via Bash"
子代理 Fork 模式:
fork = 后台子代理,不占主对话的 context
主对话可以继续跟用户聊天,fork 在后台工作
完成后通过进度通知告知结果
五、Hook 系统(155文件)
5.1 Hook 事件类型
| Hook 事件 | 触发时机 |
|---|---|
| SessionStart | 会话启动 |
| PreToolUse | 工具调用前 |
| PostToolUse | 工具调用后 |
| Notification | 通知发生时 |
| Stop | 回复结束时 |
| PreCompact | 上下文压缩前 |
| SubagentStop | 子代理结束时 |
| PermissionDenied | 权限被拒时 |
| UserPromptSubmit | 用户提交提示词前 |
5.2 Hook 配置 (settings.json)
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bun run security-check.sh"
}
]
}
]
}
}
5.3 设计精髓
- Hook 反馈被视为用户指令 — 会阻塞工具调用
- 大输出写磁盘 — >50KB 的输出写临时文件防爆 context
- 可以调整响应 — hook 拒绝了就改方案,不问用户
六、权限系统
6.1 三级权限模式
allow → 静默执行
ask → 弹窗让用户确认
deny → 直接拒绝
6.2 YOLO 分类器 (52KB)
yoloClassifier.ts 是自动模式的决策引擎:
- 分析 Bash 命令的风险等级
- 决定是否自动允许
- 包含网络/文件/进程操作的规则
6.3 权限规则范围
| 规则类型 | 说明 |
|---|---|
| alwaysAllowRules | 永久允许 |
| alwaysDenyRules | 永久拒绝 |
| alwaysAskRules | 永远询问 |
| toolPermissionContext | 当前会话上下文 |
七、Query 引擎的对话循环 (query.ts, 68KB)
核心流程
1. 构建系统提示词 (static prefix + dynamic suffix)
├── 前缀: 人格 + 准则 + 工具文档 (缓存用 global cache)
└── 后缀: 会话特定信息 (用户语言/设置/CLAUDEmd/记忆)
2. 发送给 Claude API (Anthropic SDK)
├── 携带工具定义 (JSON Schema)
└── 流式接收回复
3. 解析回复
├── 文本 → 直接输出给用户
├── tool_use → 进入权限流程
│ ├── 触发 PreToolUse hooks
│ ├── 权限检查 (allow/ask/deny)
│ └── 执行工具调用 + PostToolUse hooks
└── system reminders → 追加到上下文
4. 上下文压缩 (当 token 接近限制)
├── 自动触发 compact
└── 旧消息 → 摘要
5. 循环 — 直到用户 stop 或任务完成
压缩策略
autocompact 电路:
- 接近 context window → 自动压缩
- 3次连续失败 → 触发 circuit breaker → 报错提示
- 压缩保留: 重要决策/用户反馈/未完成任务
八、UI渲染系统
Ink 分支(非 npm 的 ink 包)
src/ink/ — 完整自研 React 终端渲染器
├── 自定义 Flexbox 布局 (src/native-ts/yoga-layout/)
├── 终端组件: Box/Text/Spinner/StatusBar
├── 权限弹窗
└── 进度条和 loading 动画
不用 npm 的 ink,而是自研分支:
- 完全控制样式
- 优化的性能
- 支持 Claude Code 特有的交互模式
九、关键技术细节
9.1 模型特征门控 (Feature Flags)
import { feature } from 'bun:bundle'
// 所有内部功能用 feature() 门控
// 泄露版中 shims/bun-bundle.ts 全部返回 false
// 意味着所有未发布功能被彻底禁用
if (feature('VERIFICATION_AGENT')) {
// 验证代理 (仅Ant内部)
}
9.2 CLAUDE.md 机制
src/utils/claudemd.ts — CLAUDE.md 加载器
功能:
- 自动读取项目的 CLAUDE.md / .claude/CLAUDE.md
- 支持 @path 引用其他文件
- 支持 frontmatter 的 paths: glob 模式
- 自动剥离 HTML 注释
- 父子目录合并优先级: 子 > 父
这就是为什么 Claude Code 能"理解项目"——它把 CLAUDE.md 注入系统提示词!
9.3 记忆系统 (MEMORY.md)
src/memdir/memdir.ts — 记忆文件加载
- 读取 MEMORY.md 并注入提示词
- 支持 markdown 的上下文引用
9.4 构建系统
// build.ts — 不是 webpack/vite,而是手写构建脚本
// 用 Bun.build() 打包
// MACRO.VERSION 硬编码为 "2.1.88"
// 输出: dist/cli.js (~23MB 单文件)
// 入口: src/entrypoints/cli.tsx
9.5 更新检测已被打补丁
// src/utils/autoUpdater.ts 第72行有 early return
// 禁用了远程版本检查
// 防止泄露版尝试连接 Anthropic 服务器
9.6 MCP 协议集成
@modelcontextprotocol/sdk — MCP 标准协议
- 支持本地和远程 MCP 服务器
- MCP工具自动注册,和内置工具一样使用
- MCP_CONNECTION_NONBLOCKING=true → 5秒超时
- _meta["anthropic/maxResultSizeChars"] → 最大500K字符
9.7 运营监控集成
OpenTelemetry (追踪/日志/指标)
├── OTLP HTTP/gRPC/Proto 三种导出器
├── Prometheus 指标导出
└── GrowthBook 功能开关 (A/B 测试)
十、架构精髓总结
🌟 10个设计精华
- 提示词就是产品 — prompts.ts 才是真正的产品逻辑,176条准则定义了一个"好AI助手"的一切
- 工具分层清晰 — 每个工具继承 Tool 基类,独立目录,description + inputSchema + call + prompt 四合一
- Hook 系统在工具之上 — 不是后加的,是核心架构的一部分,每个工具调用都被Hook包围
- 权限在工具之下 — 每次调用前都要过权限检查,分三级(allow/ask/deny),有52KB的自动决策引擎
- Context 管理是关键 — 自动压缩、claude.md机制、记忆文件、会话管理全部围绕"不丢上下文"
- UI 自研不是炫技 — 终端里的 React 渲染器有自己独特的需求(权限弹窗、进度、状态栏)
- 子代理是叉子不是线程 — Fork 模式让子代理不占主 context,异步执行
- 工具可以互相感知 — Bash 读过的文件 Edit 就知道,不需要重复 Read
- 所有内部功能都被门控 — Feature flags 让泄露代码安全可运行,同时保留完整架构供学习
- Bun 不是 Node.js — 用 Bun 的构建、Bun 的类型系统、Bun 的 API,比 Node.js 更快更现代
不适合学习的部分
- 27个 stub 文件(占位代码,不影响架构理解)
- Anthropic 内部工具(REPL/Tungsten/SuggestBackgroundPR)
- Computer Use(需要本机 Swift/Rust 二进制)
- 运营分析(GrowthBook/OpenTelemetry 配置)
最适合学习的部分
- 系统提示词设计 —
prompts.ts是 AI Agent 提示词工程的教科书 - 工具抽象 —
Tool.ts基类 + 45个工具,展示了如何构建Agent工具系统 - Hook 系统 — 155个文件的事件驱动架构
- 权限系统 — 三级权限 + 自动分类器
- Query 引擎 — 对话循环、token管理、上下文压缩
- CLAUDE.md 机制 — 如何让 AI 理解项目
分析时间: 2026-05-30
分析者: 小龙 (Xiao Long) 🐉