Claude Code 源码泄漏深度解析:终端 AI 编程助手的核心原理

深度剖析 Anthropic 官方 Claude Code CLI 的源码架构 从入口层到基础设施层,逐层解读 60+ 工具的编排机制
开篇:为什么要拆解 Claude Code?
Claude Code 是 Anthropic 官方的命令行 AI 编程助手,它将强大的 Claude 模型集成到终端中,让开发者能够通过自然的对话来完成代码编写、调试、文件操作等开发任务。
但作为一个开发者,你可能和我一样好奇:
- • 它是如何实现流式对话和工具调用的?
- • 60+ 个工具是如何编排和管理的?
- • 权限系统(plan/auto/manual 模式)是如何实现的?
- • 单文件打包后达到 25MB,核心架构是怎样的?
本文将通过逆向还原的源码(CCB 项目),逐层剖析 Claude Code 的核心原理,让你不仅能理解它的工作机制,还能从中学习到构建复杂 AI 应用的工程化经验。
一、核心架构:六层设计图
Claude Code 采用清晰的分层架构,从底层到上层分为 6 层:
┌─────────────────────────────────────────┐
│ 入口层 │
│ cli.tsx - 运行时 Polyfill 注入 │
│ main.tsx - Commander.js CLI 定义 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 核心层 │
│ QueryEngine.ts (1300+ 行) │
│ query.ts (1700+ 行) │
│ Tool.ts - 工具系统定义 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ API 层 │
│ services/api/claude.ts (3400+ 行) │
│ 支持多 Provider: │
│ Anthropic, Bedrock, Vertex, Azure │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 工具层 │
│ 60+ 工具 (Bash, FileRead, FileEdit) │
│ 工具编排 - 并发/串行执行,权限检查 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ UI 层 (Ink React CLI) │
│ REPL.tsx (5000+ 行) - 主交互界面 │
│ Messages.tsx - 消息渲染 │
│ permissions/ - 权限提示 UI │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 基础设施层 │
│ 权限系统 (plan/auto/manual) │
│ Feature Flags (30 个) │
│ Hook 系统 (pre/post tool use) │
│ 会话记忆 / 压缩 │
│ MCP 集成 │
└─────────────────────────────────────────┘
关键设计原则
- • 关注点分离:每层职责明确,UI 层不关心 API 细节
- • 可扩展性:工具系统采用统一接口,新增工具只需实现 Tool 类型
- • 多 Provider 支持:API 层抽象了 4 种不同的云服务提供商
- • 流式处理:从 API 响应到 UI 渲染全程采用流式设计,低延迟
二、工具调用循环:核心机制
Claude Code 最核心的功能是工具调用循环,它实现了 AI 与系统的交互:
用户输入 → Claude API → 工具调用 → 执行工具 → 反馈结果 → Claude 分析 → 继续或结束
↑
└─ 循环 ─┘
流程详解
1. 用户输入消息
用户输入: "帮我重构 src/utils/ 目录,优化函数组织"
2. QueryEngine.query() – 构建上下文
┌─────────────────────────────────────────┐
│ 构建上下文: │
│ ├─ CLAUDE.md 内容 │
│ ├─ 当前 git 分支和状态 │
│ ├─ 最近提交历史 │
│ └─ 内存中的对话历史 │
└─────────────────────────────────────────┘
3. 调用 Claude API(流式)
const stream = await client.messages.create({
messages: normalizeMessagesForAPI(messages),
system: systemPrompt.text,
tools: tools.map(tool => toolToAPISchema(tool)),
stream: true
})
for await (const event of stream) {
switch (event.type) {
case 'content_block_delta':
buffer += event.delta.text
break
case 'tool_use':
toolUseBlocks.push(event.toolUse)
break
}
}
4. 工具编排 – 并发 vs 串行
const batches = partitionToolCalls(toolUseBlocks, context)
// 批次 1(并发):grep, ls, FileReadTool 同时执行
// 批次 2(串行):FileEditTool 单独执行
5. 单个工具执行流程
async function* runToolUse(toolUse, context) {
const validation = await tool.validateInput(toolUse.input, context)
const permission = await checkPermissions(toolUse, context)
const result = await tool.call(
toolUse.input,
context,
canUseTool,
onProgress
)
return createToolResultMessage(toolUse, result.data)
}
循环终止条件
- • ✅ Claude 返回完整消息(不再调用工具)
- • ✅ 用户手动中断(Ctrl+C)
- • ✅ 达到最大轮数限制(防止无限循环)
- • ❌ 权限被拒绝(用户拒绝工具调用)
- • ❌ 工具执行失败(严重的 API 错误)
三、权限系统:三种模式
Claude Code 支持三种权限模式,平衡安全性和效率:
1. Default 模式(默认)
用户请求: "删除 node_modules 目录"
↓
Claude: 我需要执行: rm -rf node_modules
↓
权限提示:
┌─────────────────────────────────────────┐
│ BashTool: rm -rf node_modules │
│ 推理: 清理依赖缓存 │
│ 风险: ⚠️ 高风险 │
│ [Accept] [Deny] [Always Allow] │
└─────────────────────────────────────────┘
2. Plan 模式(计划)
用户请求: "重构 src/ 目录"
↓
Claude 生成计划:
┌─────────────────────────────────────────┐
│ 重构 src/ 目录 │
│ Step 1: 分析现有代码结构 │
│ Step 2: 创建新目录 src/utils/ │
│ Step 3:移动辅助函数 │
│ Step 4:更新导入路径 │
│ Step 5:运行测试验证 │
│ [Approve] [Cancel] │
└─────────────────────────────────────────┘
3. Auto 模式(自动)
YOLO 分类器自动判断:
工具调用: BashTool → ls -la /tmp
分类器判断: ✅ 只读命令 → 自动执行
工具调用: BashTool → rm -rf /
分类器判断: ❌ 危险命令 → 提示用户
权限系统对比
| 模式 | 安全性 | 效率 | 适用场景 |
|---|---|---|---|
| Default | ⭐⭐⭐⭐⭐ | ⭐⭐ | 新手、未知项目 |
| Plan | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 复杂重构、大规模任务 |
| Auto | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 信任项目、快速开发 |
四、工具系统:60+ 工具的统一接口
Tool 接口定义
export type Tool<Input, Output> = {
name: string
inputSchema: Input
description: (input) => Promise<string>
call(args, context, canUseTool, onProgress): Promise<ToolResult<Output>>
isEnabled: () => boolean
isConcurrencySafe: (input) => boolean
isReadOnly: (input) => boolean
isDestructive: (input) => boolean
checkPermissions: (input, context) => Promise<PermissionResult>
renderToolUseMessage: (input, options) => React.ReactNode
renderToolResultMessage: (output, options) => React.ReactNode
}
示例:BashTool 实现
const BashTool = buildTool({
name: 'bash',
inputSchema: z.object({
command: z.string(),
timeout: z.number().optional(),
}),
async call(args, context) {
const permission = await this.checkPermissions(args, context)
if (permission.behavior === 'deny') {
throw new Error('Permission denied')
}
const result = await execa(args.command, {
timeout: args.timeout || 30000,
cwd: context.options.cwd,
reject: false,
})
return {
data: {
output: result.stdout,
error: result.stderr,
exitCode: result.exitCode,
},
}
},
isConcurrencySafe: (input) => false,
isReadOnly: (input) => {
const readOnlyCommands = ['ls', 'grep', 'find', 'cat']
return readOnlyCommands.some(cmd => input.command.startsWith(cmd))
},
})
五、UI 层:Ink React CLI
export function REPL() {
const [messages, setMessages] = useState<Message[]>([])
const [input, setInput] = useState('')
useInput((input, key) => {
if (key.ctrl && input === 'c') {
abortCurrentToolExecution()
} else if (key.return) {
sendMessage(input)
setInput('')
}
})
return (
<Box flexDirection="column">
<Header />
<VirtualScrollList messages={messages} />
<PromptInput value={input} onChange={setInput} />
</Box>
)
}
自定义 Ink 特性
- • 虚拟列表:只渲染可见区域的消息
- • 自定义 hooks:useInput, useTerminalSize, useScroll
- • React Compiler:自动优化,减少重新渲染
六、基础设施层
Feature Flags(30 个,全部关闭)
globalThis.feature = (name: string): boolean => {
return false
}
会话压缩
async function compactMessages(messages: Message[]): Promise<Message[]> {
const currentTokens = await countTokens(messages)
if (currentTokens > 200000) {
const summary = await generateSummary(earlyMessages)
return [createCompactBoundaryMessage(summary), ...recentMessages]
}
}
七、关键技术总结
架构设计亮点
- 1. 清晰的分层架构:6 层设计,职责明确
- 2. 统一的工具接口:60+ 工具实现同一接口
- 3. 多 Provider 支持:统一接口支持 4 种云服务
- 4. 流式处理:全流程流式,低延迟
- 5. 智能工具编排:自动并发/串行判断
- 6. 灵活的权限系统:3 种模式 + YOLO 分类器
- 7. 会话状态管理:QueryEngine 管理完整生命周期
- 8. 自动压缩:3 种策略控制 token 使用
工程化经验
- 1. Monorepo 管理:Bun workspaces
- 2. TypeScript 全覆盖:类型安全
- 3. 单文件打包:25MB,易于分发
- 4. 性能监控:OpenTelemetry 追踪
- 5. 错误处理:完善的分类和重试机制
八、构建与运行
bun install
bun run dev
bun run build # 输出 dist/cli.js (~25MB)
九、未来展望
Claude Code 是一个优秀的 AI 应用工程实践案例,展示了如何:
- • 将大语言模型集成到工具链中
- • 设计灵活的工具系统
- • 实现流式协作
- • 管理会话状态
- • 处理权限和安全
- • 优化性能和成本
这些都是构建 AI 应用的通用原则,值得学习和借鉴。
📚 资源链接:
- • CCB GitHub:https://github.com/claude-code-best/claude-code
- • Claude Code 官方文档:https://docs.anthropic.com/en/docs/claude-code
- • Anthropic API 文档:https://docs.anthropic.com/
夜雨聆风