Claude Code 源码分析:Coding Agent 的最佳实践
整体架构图
🎯 核心论点
Claude Code 不是简单的 LLM CLI,而是一个精心设计的 AI Coding Harness:– 512,000+ 行 TypeScript,1,900+ 文件– 40+ 工具、50+ 命令、Bun + React + Ink 架构– Context Engineering:系统化的上下文管理– Harness Engineering:确定性的工具执行循环– 极致优化:并行预加载、懒加载、死代码消除
为什么在 coding 表现优异:1. 丰富的工具集:40+ 专门为编程设计的工具2. 智能上下文管理:自动收集项目上下文、git 状态、LSP 集成3. 确定性验证:每个工具调用都有明确的输入验证和权限检查4. 反馈循环:实时的工具执行结果反馈给 LLM5. 性能优化:快速启动、流式响应、缓存策略
🌳 Part 1: 架构总览
1.1 技术栈
|
|
|
|
|---|---|---|
| Runtime |
|
|
| Language |
|
|
| Terminal UI |
|
|
| CLI Parsing |
|
|
| Schema |
|
|
| Search |
|
|
| Protocols |
|
|
| Feature Flags |
|
|
| Telemetry |
|
|
1.2 目录结构(重点)
src/├── main.tsx # 入口(803KB!)├── QueryEngine.ts # 核心 LLM 引擎(46K 行)├── Tool.ts # 工具类型定义(29K 行)├── tools.ts # 工具注册(25K 行)├── context.ts # 上下文收集│├── tools/ # 40+ 工具实现│ ├── BashTool/ # Shell 执行│ ├── FileEditTool/ # 文件编辑│ ├── AgentTool/ # 子 agent│ ├── SkillTool/ # 技能执行│ ├── LSPTool/ # LSP 集成│ ├── GlobTool/ # 文件搜索│ ├── GrepTool/ # 内容搜索│ └── ...│├── commands/ # 50+ slash 命令│ ├── commit/ # Git commit│ ├── review/ # Code review│ ├── compact/ # 上下文压缩│ └── ...│├── services/ # 核心服务│ ├── api/ # Anthropic API│ ├── mcp/ # MCP 协议│ ├── lsp/ # LSP 管理│ ├── compact/ # 上下文压缩│ └── analytics/ # 遥测│├── bridge/ # IDE 桥接│ ├── bridgeMain.ts # 主循环│ ├── bridgeMessaging.ts # 消息协议│ └── jwtUtils.ts # JWT 认证│├── components/ # 140+ UI 组件├── hooks/ # React hooks├── state/ # 状态管理└── utils/ # 工具函数(331 文件!)
🌿 Part 2: 核心设计模式
2.1 QueryEngine:LLM 查询引擎
定义:管理整个对话生命周期和会话状态的核心类
关键职责:1. 对话状态管理:维护 mutableMessages、totalUsage、abortController2. 工具调用循环:处理 LLM 的 tool call,执行工具,返回结果3. 上下文管理:自动注入系统上下文、git 状态、用户上下文4. 权限控制:每个工具调用前检查权限5. 流式响应:实时返回 LLM 输出
核心流程:
class QueryEngine { private config: QueryEngineConfig private mutableMessages: Message[] private abortController: AbortController private permissionDenials: SDKPermissionDenial[] private totalUsage: NonNullableUsage async submitMessage(userMessage: Message) { // 1. 添加用户消息 this.mutableMessages.push(userMessage) // 2. 调用 LLM API const stream = await query({ messages: this.mutableMessages, tools: this.config.tools, systemPrompt: await this.buildSystemPrompt(), }) // 3. 处理流式响应 for await (const event of stream) { if (event.type === 'tool_use') { // 4. 执行工具 const result = await this.executeTool(event.tool) // 5. 添加工具结果到消息 this.mutableMessages.push(result) // 6. 继续查询 LLM // (递归调用 query) } } }}
Harness 亮点:– 确定性循环:工具执行 → 结果 → LLM → 工具执行– 状态持久化:跨多个 submitMessage 调用保持状态– 可中断:通过 abortController 支持取消操作
2.2 Tool 系统:40+ 专门化工具
设计原则:– 每个工具是自包含模块– 定义输入 schema、权限模型、执行逻辑– 支持渐进式权限(default → plan → bypassPermissions)
工具分类:
A. 文件操作(5 个)
FileReadTool // 读取文件(支持图片、PDF、notebook)FileWriteTool // 创建/覆盖文件FileEditTool // 部分修改(字符串替换)GlobTool // 文件模式匹配GrepTool // ripgrep 内容搜索
FileEditTool 亮点:
export const FileEditTool = buildTool({ name: 'edit_file', strict: true, // 严格模式 async validateInput(input) { // 1. 路径扩展(处理 ~、相对路径) const fullPath = expandPath(input.file_path) // 2. 安全检查(防止编辑敏感文件) const secretError = checkTeamMemSecrets(fullPath, input.new_string) if (secretError) return { result: false, message: secretError } // 3. 幂等性检查 if (input.old_string === input.new_string) { return { result: false, message: "No changes" } } // 4. 文件大小限制(1 GiB) if (fileSize > MAX_EDIT_FILE_SIZE) { return { result: false, message: "File too large" } } }, async checkPermissions(input, context) { // 调用权限检查器 return checkWritePermissionForTool(input, context) }, async execute(input, context) { // 1. 读取文件 const content = await readFile(input.file_path) // 2. 查找 old_string const actualString = findActualString(content, input.old_string) // 3. 替换 const newContent = content.replace(actualString, input.new_string) // 4. 写入 await writeFile(input.file_path, newContent) // 5. 返回 diff return { diff: getPatchForEdit(actualString, input.new_string) } },})
为什么 FileEditTool 比直接 shell 命令更好:– ✅ 输入验证:自动检查路径、字符串匹配– ✅ 权限控制:可配置允许/拒绝规则– ✅ 差异反馈:返回 diff 给 LLM– ✅ 幂等性:old_string 不匹配时报错– ✅ 文件历史:可选的文件快照(用于回滚)
B. Shell 执行(1 个)
BashTool // Shell 命令执行
BashTool 亮点:– 沙箱执行:支持配置允许/拒绝的命令– 超时控制:防止长时间运行的命令– 输出捕获:stdout/stderr 分离– 工作目录:可指定执行目录– 环境变量:可传递环境变量
C. 搜索工具(3 个)
GlobTool // 文件模式搜索(类似 find)GrepTool // 内容搜索(ripgrep)ToolSearchTool // 延迟工具发现
ToolSearchTool 亮点:
Deferred tool discovery — 不预加载所有工具,按需加载
为什么需要:– 工具数量多时,预加载会占用大量 token– 按需加载减少初始 context window 消耗– LLM 通过搜索找到需要的工具
D. Agent 系统(5 个)
AgentTool // 子 agent 生成TeamCreateTool // 创建 agent 团队TeamDeleteTool // 删除团队SendMessageTool // agent 间消息传递TaskOutputTool // 任务输出查询
AgentTool 亮点:
export const AgentTool = buildTool({ name: 'agent', async execute(input) { // 1. 创建子 agent const subAgent = await createSubagent({ prompt: input.prompt, tools: filterTools(input.tools), maxTurns: input.max_turns, }) // 2. 运行子 agent const result = await subAgent.run() // 3. 返回结果给父 agent return { result: result.output } },})
为什么需要子 agent:– 并行工作:多个 agent 同时处理不同任务– 专业化:每个 agent 专注特定领域– 隔离:子 agent 的错误不影响父 agent– 上下文隔离:子 agent 有独立的 context window
E. LSP 集成(1 个)
LSPTool // Language Server Protocol 集成
LSPTool 能力:– 定义跳转:Go to definition– 引用查找:Find references– 重命名:Rename symbol– 诊断:获取错误/警告
为什么 LSP 重要:– LLM 不需要猜测,可以直接查询精确信息– 减少幻觉(LSP 提供确定性答案)– 理解代码库结构
F. 技能系统(1 个)
SkillTool // 执行预定义的技能
SkillTool 亮点:– 用户可自定义技能(YAML/Markdown)– 可分享和复用– 自动激活条件(基于文件路径)
G. 其他工具(15+ 个)
WebFetchTool // 获取 URL 内容WebSearchTool // Web 搜索ConfigTool // 配置管理EnterPlanModeTool // 进入规划模式ExitPlanModeTool // 退出规划模式EnterWorktreeTool // Git worktree 隔离ExitWorktreeToolTodoWriteTool // Todo 管理AskUserQuestionTool // 询问用户...
2.3 Context Engineering:智能上下文管理
context.ts 的核心职责:– 收集系统上下文(git 状态、环境信息)– 收集用户上下文(当前目录、项目信息)– 自动注入到每个查询
getGitStatus 亮点:
export const getGitStatus = memoize(async () => { // 1. 并行获取多个 git 信息 const [branch, mainBranch, status, log, userName] = await Promise.all([ getBranch(), getDefaultBranch(), execFile(gitExe, ['status', '--short']), execFile(gitExe, ['log', '--oneline', '-n', '5']), execFile(gitExe, ['config', 'user.name']), ]) // 2. 截断过长的输出 const truncatedStatus = status.length > 2000 ? status.substring(0, 2000) + '\n... (truncated)' : status // 3. 组装上下文 return `Current branch: ${branch}Main branch: ${mainBranch}Git user: ${userName}Status:${truncatedStatus}Recent commits:${log} `.trim()})
为什么 git 状态重要:– LLM 知道当前在哪个分支– 了解未提交的修改– 知道最近的提交(用于 context)
上下文截断策略:– 2000 字符限制:防止 context window 过大– 提示用户:”If you need more information, run git status”
getSystemContext:
export const getSystemContext = memoize(async () => { const gitStatus = await getGitStatus() return { ...(gitStatus && { gitStatus }), }})
memoize 的作用:– 缓存结果,避免重复计算– 整个对话期间只计算一次
2.4 权限系统:细粒度控制
权限模式:
type PermissionMode = | 'default' // 默认:交互式确认 | 'plan' // 规划模式:只读操作 | 'bypassPermissions' // 绕过权限(内部) | 'auto' // 自动批准(基于规则)
权限检查流程:
async checkPermissions(input, context) { const appState = context.getAppState() // 1. 检查 alwaysAllowRules if (matchRule(input, appState.alwaysAllowRules)) { return 'allow' } // 2. 检查 alwaysDenyRules if (matchRule(input, appState.alwaysDenyRules)) { return 'deny' } // 3. 交互式确认 if (context.mode === 'default') { return await promptUser(input) } // 4. Plan 模式:只读操作 if (context.mode === 'plan' && !isReadOnly(input)) { return 'deny' } return 'ask'}
Harness 亮点:– 三层规则:allow → deny → ask– 支持通配符:*.ts, src/**– 可配置:通过配置文件或 CLI 参数
🍃 Part 3: 为什么 Coding 表现优异
3.1 丰富的工具集
对比其他 CLI:
|
|
|
|
|---|---|---|
| 文件操作 |
|
|
| 搜索 |
|
|
| LSP |
|
|
| Agent |
|
|
| Skills |
|
|
为什么多工具比少工具好:– 精确控制:每个工具职责单一– 清晰反馈:每个工具有专门的输出格式– 权限分离:不同工具有不同权限级别
3.2 智能上下文管理
自动收集的上下文:1. Git 状态:当前分支、未提交修改、最近提交2. 项目结构:通过 glob 了解文件布局3. LSP 信息:定义、引用、诊断4. 环境信息:操作系统、工作目录
为什么自动上下文重要:– 减少用户输入:不需要手动描述项目– 提高准确性:基于实际状态,而非猜测– 上下文相关性:只注入相关的上下文
3.3 确定性验证
每个工具调用的验证流程:
LLM 输出 tool call ↓validateInput(验证输入) ↓checkPermissions(权限检查) ↓execute(执行) ↓返回结构化结果给 LLM
FileEditTool 的验证:
async validateInput(input) { // 1. 路径规范化 const fullPath = expandPath(input.file_path) // 2. 安全检查(防止注入) const secretError = checkTeamMemSecrets(fullPath, input.new_string) // 3. 幂等性检查 if (input.old_string === input.new_string) { return { result: false, message: "No changes" } } // 4. 文件存在性检查 if (!exists(fullPath)) { return { result: false, message: "File not found" } } // 5. 字符串匹配检查 const content = await readFile(fullPath) if (!content.includes(input.old_string)) { const suggestion = findSimilarString(content, input.old_string) return { result: false, message: `String not found. Did you mean: ${suggestion}?` } } return { result: true }}
为什么验证重要:– 防止错误:在执行前发现问题– 有用反馈:告诉 LLM 具体哪里错了– 安全性:防止恶意输入
3.4 反馈循环
完整的工具调用循环:
1. LLM 输出 tool_call { "name": "edit_file", "input": { "file_path": "src/main.ts", "old_string": "...", "new_string": "..." } }2. Claude Code 执行工具3. 返回结构化结果 { "success": true, "diff": "- old\n+ new", "lines_changed": 5 }4. LLM 看到结果,继续推理5. 循环直到任务完成
为什么这个循环强大:– 迭代改进:LLM 可以根据结果调整– 错误恢复:失败后可以重试– 透明性:用户可以看到每一步
3.5 性能优化
优化 1:并行预加载
// main.tsx — 启动时并行执行startMdmRawRead() // 读取 MDM 设置startKeychainPrefetch() // 预取 keychainapiPreconnect() // 预连接 API
效果:– 启动时间从 3-5 秒降至 1-2 秒– 用户感知更快
优化 2:懒加载
// 重模块延迟加载const openTelemetry = await import('open-telemetry')const analytics = await import('./services/analytics')
效果:– 减少初始加载时间– 只在需要时加载
优化 3:死代码消除
import { feature } from 'bun:bundle'// 特性标志控制的代码在编译时完全移除const voiceCommand = feature('VOICE_MODE') ? require('./commands/voice/index.js').default : null
特性标志:– PROACTIVE:主动模式– KAIROS:新架构– BRIDGE_MODE:IDE 桥接– VOICE_MODE:语音输入– AGENT_TRIGGERS:触发器
效果:– 减少包体积– 加载更快
优化 4:Memoization
export const getGitStatus = memoize(async () => { // 复杂计算...})export const getSystemContext = memoize(async () => { // 复杂计算...})
效果:– 避免重复计算– 对话期间只计算一次
优化 5:流式响应
for await (const event of stream) { if (event.type === 'content_block_delta') { // 实时输出 process.stdout.write(event.delta.text) }}
效果:– 用户看到即时反馈– 不需要等待完整响应
💡 Part 4: Harness 亮点总结
亮点 1:确定性工具执行
传统方式:
LLM → 生成代码 → 执行 → 可能成功,可能失败
Claude Code 方式:
LLM → tool call → validateInput → checkPermissions → execute → 结构化结果 ↑_______________________________________________| 反馈循环
对比:
|
|
|
|
|---|---|---|
| 可验证性 |
|
|
| 错误反馈 |
|
|
| 可恢复性 |
|
|
亮点 2:丰富的上下文
自动注入的上下文:1. Git 状态(分支、修改、提交)2. 项目结构(通过 glob)3. LSP 信息(定义、引用)4. 环境信息
对比其他 CLI:
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
亮点 3:专业化工具
为什么专业化工具好:
对比:通用 Bash vs 专用 FileEditTool
# Bash 方式(通用但危险)sed -i 's/old/new/g' file.txt# ❌ 无验证# ❌ 无权限控制# ❌ 错误反馈差# ❌ 幂等性差
// FileEditTool 方式(专业化){ "name": "edit_file", "input": { "file_path": "file.txt", "old_string": "old", "new_string": "new" }}// ✅ 输入验证// ✅ 权限检查// ✅ 精确反馈(diff)// ✅ 幂等性保证
亮点 4:渐进式权限
权限层级:
default → plan → bypassPermissions → auto ↓ ↓ ↓ ↓交互式 只读操作 绕过权限 规则自动
为什么需要:– default:日常使用,安全– plan:规划阶段,只读– bypassPermissions:CI/CD,无人值守– auto:基于规则,减少交互
亮点 5:Agent 协作
子 Agent 能力:
// 创建团队await TeamCreateTool.execute({ name: "refactoring-team", agents: [ { role: "planner", prompt: "Plan refactoring" }, { role: "coder", prompt: "Implement changes" }, { role: "reviewer", prompt: "Review code" }, ]})// Agent 间通信await SendMessageTool.execute({ to: "coder", message: "Here's the plan..."})
为什么强大:– 并行化:多个 agent 同时工作– 专业化:每个 agent 专注一件事– 可扩展:可添加更多 agent
🚀 Part 5: 关键洞察
洞察 1:工具 > 自由文本
Claude Code 的哲学:
Don’t let LLM generate free-form codeLet LLM call structured tools
原因:– 可验证:工具输入有 schema– 可控制:每个工具独立权限– 可恢复:失败后精确反馈
洞察 2:上下文工程是关键
上下文质量 = 代码生成质量
Claude Code 的上下文策略:1. 自动收集:git、项目结构、LSP2. 智能截断:防止 context window 溢出3. 按需加载:ToolSearchTool 延迟发现4. 缓存:memoize 避免重复计算
洞察 3:确定性验证 + 随机生成
公式:
高质量代码 = 确定性验证 + 随机生成 + 迭代优化 (validateInput) (LLM) (feedback loop)
类比:– LLM = 创造力:生成想法– 工具 = 约束:验证和执行– 循环 = 迭代:持续改进
洞察 4:专业化 > 通用化
Claude Code 的选择:– 40+ 专业化工具 > 1 个通用 Bash– 5 个文件工具 > 1 个通用的文件操作– 3 个搜索工具 > 1 个通用的搜索
原因:– 更好的验证:每个工具有专门的 schema– 更好的反馈:每个工具有专门的输出格式– 更好的权限:每个工具有独立的权限规则
洞察 5:性能 = 用户体验
Claude Code 的优化:1. 并行预加载:启动时并发执行2. 懒加载:延迟加载重模块3. 死代码消除:编译时移除未使用代码4. Memoization:缓存计算结果5. 流式响应:实时输出
结果:– 启动时间:1-2 秒– 响应时间:实时流式– 内存占用:优化后更小
🎯 Part 6: 实践建议
对于 AI Agent 开发者
1. 采用工具优先设计:– 不要让 LLM 生成自由代码– 设计结构化的工具接口– 每个工具有明确的输入/输出
2. 实现确定性验证:
interface Tool { validateInput(input): ValidationResult checkPermissions(input, context): PermissionDecision execute(input, context): ToolResult}
3. 建立反馈循环:– 工具结果 → LLM → 工具调用 → 结果 → …– 让 LLM 根据结果调整
4. 智能上下文管理:– 自动收集相关上下文– 智能截断– 缓存策略
5. 性能优化:– 并行预加载– 懒加载– 死代码消除
对于使用者
1. 利用专业化工具:– 用 edit_file 而非 sed– 用 grep tool 而非 shell grep– 用 LSPTool 而非猜测
2. 理解权限模式:– default:日常使用– plan:规划阶段– auto:CI/CD
3. 使用 skills:– 定义常用工作流– 分享给团队
4. 监控 token 使用:– 使用 /cost 查看消耗– 定期 /compact 压缩上下文
📚 扩展资源
源码
-
泄露源码: https://github.com/instructkr/claude-code -
官方仓库: https://github.com/anthropics/claude-code
协议与框架
-
MCP 协议: https://modelcontextprotocol.io/ -
Bun Runtime: https://bun.sh/ -
Ink (Terminal UI): https://github.com/vadimdemedes/ink
Harness Engineering
-
The Bitter Lesson: http://www.incompleteideas.net/IncIdeas/BitterLesson.html -
Harness Engineering Guide: https://www.nxcode.io/resources/news/what-is-harness-engineering-complete-guide-2026
夜雨聆风
