突发!Claude Code 源码遭泄露,我让 AI 连夜扒出了一套“造轮子”秘籍
从 Claude Code 源码学习开发 Coding Agent 的系统化路径
核心心智模型
Coding Agent 的本质是一个循环:
用户输入 → LLM 思考 → 调用工具 → 观察结果 → 继续思考或结束
第一阶段:理解核心概念 — “Agent 到底是什么?”
入口文件:src/query.ts 中的 queryLoop(),整个系统的心脏。
理解要点:
-
• 每一轮循环做了什么(调 API → 提取 tool_use → 执行工具 → 决定继续还是停止) -
• 什么条件下循环终止(没有更多工具调用、达到 token 预算、stop hook 阻断) -
• 如何处理流式输出
学习产出: 自己写一个最简单的 agent loop — 50 行代码,能调 Claude API,解析 tool_use,执行一个工具,把结果喂回去。
第二阶段:工具系统 — Agent 的”手和脚”
2.1 工具的抽象定义 — src/Tool.ts
核心接口:
-
• call()— 执行逻辑 -
• checkPermissions()— 权限控制 -
• validateInput()— 输入校验 -
• prompt()— 告诉 LLM 这个工具怎么用(系统提示词注入) -
• isConcurrencySafe()/isReadOnly()— 并发控制标记
2.2 工具的注册与组装 — src/tools.ts
-
• getAllBaseTools()→getTools()→assembleToolPool()的流水线 -
• 如何合并内建工具 + MCP 外部工具 -
• 如何根据权限过滤工具
2.3 典型工具深入学习
|
|
|
src/tools/FileReadTool/ |
|
src/tools/FileEditTool/ |
|
src/tools/BashTool/ |
|
src/tools/AgentTool/ |
|
学习产出: 给你的 mini agent 加 3 个工具:读文件、写文件、执行 shell。用 buildTool() 模式定义它们。
第三阶段:工具编排 — 不只是”一个一个执行”
3.1 并发编排 — src/services/tools/toolOrchestration.ts
-
• 并发分批:多个只读工具可以并行执行,写操作必须串行 -
• partitionToolCalls()的分区逻辑 -
• 这是性能的关键 — Claude 一次可能返回多个 tool_use
3.2 执行生命周期 — src/services/tools/toolExecution.ts
-
• 单个工具的完整生命周期: 校验 → 权限 → pre-hook → 执行 → post-hook → 序列化 -
• 错误处理和中止(abort)机制
学习产出: 让你的 agent 支持并行工具执行。
第四阶段:权限与安全 — 让 Agent 不失控
这是生产级 agent 和玩具 agent 的分水岭。
4.1 权限模型 — src/hooks/useCanUseTool.tsx
-
• 三级权限: allow(自动通过)→ask(询问用户)→deny(拒绝) -
• 工具的 isDestructive()标记影响默认权限级别
4.2 安全机制 — src/tools/BashTool/
-
• 命令的 AST 解析(不是简单的字符串匹配) -
• 沙箱执行 -
• 危险操作检测
关键设计理念: 读操作默认允许,写操作需要确认,危险操作默认拒绝。这个梯度设计是 UX 和安全的平衡点。
学习产出: 给你的 agent 加权限层 — 至少区分”自动允许”和”需要确认”两级。
第五阶段:上下文管理 — Agent 的”记忆”
长对话场景下,context window 会耗尽。
5.1 压缩策略 — src/query.ts
-
• Auto-compact — 接近上下文极限时自动压缩历史对话 -
• Reactive compact — context window 溢出时的紧急处理
5.2 Token 预算 — src/query/tokenBudget.ts
-
• BudgetTracker管理 500K token 预算的自动续写功能
5.3 上下文注入 — src/context.ts
-
• getUserContext()— 注入 git 状态、系统信息等上下文 -
• 系统提示词是如何组装的(每个工具贡献自己的 prompt 片段)
学习产出: 实现一个简单的上下文压缩策略 — 当消息超过阈值时,用 LLM 总结早期对话。
第六阶段:子 Agent 与任务系统 — 从单体到多体
6.1 递归 Agent — src/tools/AgentTool/runAgent.ts
-
• 子 agent 本质上是递归调用 query(),但用受限的工具集 -
• 子 agent 有自己的上下文,不会污染主对话 -
• 通过 onProgress回调向父 agent 报告进展
6.2 任务管理 — src/tasks/ 和 src/Task.ts
-
• 前台 vs 后台任务 -
• 任务状态机: pending → running → completed/failed/killed -
• 多种任务类型: local_agent、remote_agent、in_process_teammate
学习产出: 让你的 agent 能通过一个 “Agent” 工具派生子 agent,子 agent 完成后把结果返回给父 agent。
第七阶段:用户界面 — 让 Agent 可交互
Claude Code 用了深度定制的 Ink(React for Terminal)框架:
-
• src/ink/— 自定义 React reconciler,Yoga 布局引擎,帧 diff 优化 -
• src/screens/REPL.tsx— 主交互界面(~2000+ 行) -
• src/components/Markdown.tsx— 流式 Markdown 渲染
关键交互模式:
-
• 流式输出(token 到达时即渲染) -
• 工具执行时的进度展示 -
• 权限请求的交互式对话框
学习产出: 不需要复刻 Ink。但至少实现流式输出 + 工具执行的实时状态展示。
第八阶段:可扩展性 — Skills、Hooks、MCP
让 agent 从”固定功能”变成”平台”的关键:
|
|
|
|
| Skills | src/skills/ |
|
| Hooks |
|
|
| MCP | src/tools/MCPTool/ |
|
Skill 的定义模式(src/skills/bundledSkills.ts):
-
• 一个 skill 本质上是 名字 + 描述 + 提示词生成函数 + 可选的工具/模型限制
关键数据流
CLI entry (cli.tsx / main.tsx) → Init (auth, GrowthBook, MCP, plugins, skills) → launchRepl() → <App><REPL /></App> via Ink OR → print() → QueryEngine.submitMessage()User input → REPL.tsx → query(params) [query.ts] → queryLoop() iterates: 1. Claude API call (streaming) → assistant message 2. Extract tool_use blocks 3. runTools() [toolOrchestration.ts] → partitionToolCalls() → concurrent or serial batches → runToolUse() [toolExecution.ts] → validateInput → checkPermissions (canUseTool) → pre-tool hooks → tool.call() → post-tool hooks → tool result message 4. handleStopHooks() [stopHooks.ts] 5. Decide: continue (more tool calls) or terminate → Stream events → Ink re-renders UI
推荐学习顺序
1. query.ts → 理解 agent loop2. Tool.ts + tools.ts → 理解工具抽象3. FileReadTool → 写第一个工具4. toolOrchestration → 理解并发执行5. useCanUseTool → 加权限控制6. tokenBudget.ts → 上下文管理7. AgentTool → 子 agent 递归8. skills/ → 可扩展性
每个阶段都先读源码理解设计,再动手实现一个最小版本。最终目标是从零构建一个能读写文件、执行命令、自动规划的 mini coding agent。Claude Code 的源码不是用来照搬的,而是用来理解”为什么这样设计” — 每个看似复杂的模块背后都是踩过坑后的解法。
夜雨聆风