尝试学习理解下Claude Code的实现原理和细节
结合Claude的回答我们来看下Claude Code的实现原理和细节
一、诞生故事:从「听歌小工具」到企业级产品
Claude Code 的想法源自一个命令行工具,最初只是用 Claude 来显示工程师在工作时听的音乐,但在获得文件系统访问权限后,它在 Anthropic 内部迅速传播开来。
时间线:
- 2024年9月: 第一个原型
- 2024年11月: 内部狗粮测试版本(第1天20%工程师使用,第5天50%使用)
- 2025年: 正式发布稳定版
这个发展路径很重要 → 它说明 Claude Code 不是为了炫技而做的产品,而是 Anthropic 工程师真实需求驱动的工具。
二、技术栈:「自举」的艺术
技术栈采用 TypeScript、React、Ink、Yoga 和 Bun,选择这些技术是为了”符合发行版”并发挥模型的优势。有趣的事实:Claude Code 中 90% 的代码是由它自己编写的!
核心组件:
1 | ┌─────────────────────────────────────┐ |
为什么用这些技术?
- TypeScript: 类型安全,适合复杂的状态管理
- React + Ink: 在终端中渲染 React 组件(是的,你没看错!)
- Yoga: Facebook 的布局引擎,用于终端 UI 布局
- Bun: 超快的 JavaScript 运行时
三、工作原理:AI 代理的「感知-决策-执行」循环
1. 基础流程
1 | 用户输入 → Claude分析 → 制定计划 → 调用工具 → 执行操作 → 反馈结果 |
2. 核心机制详解
A. 上下文理解系统
Claude Code 维护对整个项目结构的认知,可以从网上查找最新信息,并通过 MCP 可以从 Google Drive、Figma 和 Slack 等外部数据源提取信息
具体实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// 伪代码示例
class ContextManager {
// 1. 项目结构索引
buildProjectIndex() {
- 扫描文件树
- 识别语言和框架
- 构建依赖关系图
- 标记重要文件(配置、入口点等)
}
// 2. 智能搜索
agenticSearch(query) {
- 语义搜索相关文件
- 理解代码关系
- 定位依赖项
- 返回相关上下文
}
// 3. 上下文压缩
compactContext(preserveInstructions) {
- 保留核心信息
- 移除已完成的历史
- 压缩冗余内容
}
}
B. 工具调用系统
Claude Code 有一套标准化的工具接口:1
2
3
4
5
6
7
8
9
10// 核心工具类型
interface Tool {
read: 读取文件
write: 写入文件
bash: 执行Shell命令
grep: 代码搜索
diff: 查看差异
git: Git操作
mcp_*: MCP服务器提供的工具
}
工具调用流程:
- Claude 决策: “我需要查看 logging.py 文件”
- 权限检查: 询问用户或检查白名单
- 执行工具:
read_file("logging.py") - 返回结果: 文件内容 → Claude 的上下文
- 继续推理: 基于内容做下一步决策
四、子代理系统 (Subagents):分工协作的艺术
对于复杂问题应该强烈考虑使用子代理。让 Claude 使用子代理来验证细节或调查它可能有的特定问题,尤其是在对话或任务早期,往往能保留上下文可用性,而在效率损失方面几乎没有什么缺点
子代理架构
1 | 主 Claude (协调者) |
实现示例
1 | # .claude/subagents/code-reviewer.md |
使用方式:1
2
3
4
5
6
7
8# 让主 Claude 调用子代理
claude> "完成这个功能后,让代码审查员检查它"
# 自动委派
主 Claude: "我会让专门的审查员来检查这个..."
→ 启动 code-reviewer 子代理
→ 审查完成,报告返回给主 Claude
→ 主 Claude 根据反馈修改代码
五、MCP (Model Context Protocol):Claude Code 的「神经系统」
MCP(模型上下文协议)是一个开源标准,用于连接 AI 应用程序到外部系统。使用 MCP,像 Claude 或 ChatGPT 这样的 AI 应用程序可以连接到数据源(例如本地文件、数据库)、工具(例如搜索引擎、计算器)和工作流(例如专门的提示)
MCP 核心概念
把 MCP 想象成 “AI 的 USB-C 接口” → 标准化的连接方式1
2
3
4
5
6
7
8
9
10
11
12Claude Code (主机)
↓
MCP 客户端
↓
[MCP 协议] ← 标准化通信
↓
MCP 服务器们
├── GitHub MCP
├── Slack MCP
├── Google Drive MCP
├── Database MCP
└── 自定义 MCP
MCP 架构详解
1. 三种传输方式1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// A. Stdio (标准输入/输出) - 本地进程
{
"local-tool": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem"],
"env": { "LOG_LEVEL": "debug" }
}
}
// B. HTTP - 远程服务
{
"remote-api": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
// C. SSE (Server-Sent Events) - 已弃用,改用 HTTP
2. MCP 服务器能提供什么
Resources (资源): 可以 @ 引用的数据
1
2
3@github-issues
@notion-pages
@drive-documentsTools (工具): Claude 可以调用的功能
1
2
3
4
5
6
7// 工具命名格式
mcp__<服务器名>__<工具名>
// 示例
mcp__github__create_issue
mcp__slack__send_message
mcp__database__queryPrompts (提示): 预定义的工作流
1
2
3/analyze-pr
/generate-tests
/update-docs
3. 实际使用流程
1 | # 场景:让 Claude 分析 GitHub PR |
4. 开发自定义 MCP 服务器
1 | // 简化示例:数据库 MCP 服务器 |
六、安全机制:如何防止「失控」
Claude Code 通过一次性 API 调用 claude-3-5-haiku 来验证 bash 命令不是恶意的,并提取其前缀
安全层级
1 | ┌────────────────────────────────────┐ |
实际安全检查流程
1 | # 伪代码 |
七、性能优化:百万 Token 上下文管理
Anthropic 最近将 Sonnet 的上下文窗口增加到 100 万 tokens。这是整个莎士比亚作品集的大小,但这并不意味着你不应该仍然遵循这些技巧来保持 Claude 的专注
上下文管理策略
1. Context Compaction (上下文压缩)1
2# 使用 /compact 命令
claude> /compact 专注于保留我们当前的身份验证实现和数据库架构决策
工作原理:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15原始对话 (80,000 tokens)
↓
Claude 分析关键信息
↓
保留:
- 当前任务状态
- 重要的设计决策
- 未完成的 TODO
↓
移除:
- 已完成的历史操作
- 中间调试输出
- 冗余的讨论
↓
压缩后 (15,000 tokens)
2. 分层上下文策略1
2
3
4
5
6
7
8
9
10
11
12
13
14高优先级 (总是在上下文中)
├── 当前任务描述
├── 项目架构概览
└── 活跃文件内容
中优先级 (按需加载)
├── 相关代码文件
├── 测试文件
└── 配置文件
低优先级 (搜索时加载)
├── 历史讨论
├── 依赖文档
└── 相似代码模式
3. Think Budget (思考预算)
这些特定短语直接映射到系统中不断增加的思考预算级别:”think” < “think hard” < “think harder” < “ultrathink”1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 简单任务
claude> "think 修复这个 linting 错误"
↑ 快速思考,消耗少量 tokens
# 中等复杂度
claude> "think hard 重构这个认证系统"
↑ 深度分析,权衡多个方案
# 高复杂度
claude> "think harder 设计一个可扩展的微服务架构"
↑ 极深度推理,探索多种可能性
# 极限模式
claude> "ultrathink 为什么这个分布式系统会出现数据不一致?"
↑ 最大化思考能力,适合极难问题
八、实战工作流:TDD + 多实例并行
这是 Anthropic 最喜欢的工作流,适用于可以通过单元测试、集成测试或端到端测试轻松验证的更改。测试驱动开发(TDD)在代理编码中变得更加强大
完整 TDD 流程
1 | # 1. 生成规范文档 |
多实例并行工作
你可以在 IDE 的不同窗格中并行运行多个 Claude Code 实例,只要它们在代码库的不同部分工作1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19VS Code 布局:
┌─────────────────┬─────────────────┐
│ Claude #1 │ Claude #2 │
│ (前端功能) │ (后端 API) │
│ │ │
│ 任务: │ 任务: │
│ - 实现 UI 组件 │ - 创建 REST API │
│ - 写 React 测试 │ - 数据库迁移 │
│ - 更新样式 │ - API 文档 │
└─────────────────┴─────────────────┘
┌─────────────────┬─────────────────┐
│ Claude #3 │ Claude #4 │
│ (测试) │ (文档) │
│ │ │
│ 任务: │ 任务: │
│ - E2E 测试 │ - 更新 README │
│ - 集成测试 │ - API 文档 │
│ - 性能测试 │ - 变更日志 │
└─────────────────┴─────────────────┘
九、实际效果:数据说话
开发速度提升
团队以极快的速度工作,每位工程师每天大约发布 5 个版本。原型制作速度惊人地快:我们为一个新功能会完成 10 多个实际原型
具体案例:
- Builder.io 有一个 18,000 行的 React 组件。除了 Claude Code,没有任何 AI 代理能成功更新这个文件
- 第一个版本在一小时内完成。我又花了几个小时调整,现在它相当不错
应用场景
1 | ✅ 完美适合: |
十、核心技术优势总结
1. 上下文感知能力
- 代理式搜索,自动理解项目结构
- 100万 token 上下文窗口
- 智能压缩和管理
2. 工具生态系统
- 内置核心工具(文件、Shell、Git)
- MCP 开放标准,连接无限工具
- 可自定义扩展
3. 多代理协作
- 子代理专注不同任务
- 并行执行,提高效率
- 独立上下文,避免混淆
4. 安全与可靠
- 三层安全机制
- 命令验证和白名单
- 文件操作隔离
5. 开发者友好
- Unix 哲学:可组合、可脚本化
- 原生 IDE 集成
- 终端内完整工作流
十一、未来方向与思考
Claude Code 的核心理念:
“不是替代开发者,而是让开发者专注于创造性工作”
1 | 传统开发: |
关键要素:
- 人类保留控制权 - 设计、决策、审查
- AI 承担执行 - 编码、测试、文档
- 快速迭代 - 10+ 原型探索最佳方案
- 质量保证 - 自动测试 + 人工审查
代码层 继续看下的代码的主体架构
1 | ┌─────────────────────────────────────────────────┐ |
其中核心循环的实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62// 核心主循环 (nO)
class ClaudeCodeAgent {
private conversationHistory: Message[] = [];
private toolRegistry: ToolRegistry;
private h2aQueue: AsyncMessageQueue;
async run(userPrompt: string): Promise<void> {
// 1. 初始化对话
this.conversationHistory.push({
role: "user",
content: userPrompt
});
// 2. 主循环
while (true) {
// 3. 调用 Claude API
const response = await this.callClaude({
model: "claude-sonnet-4-5",
messages: this.conversationHistory,
tools: this.toolRegistry.getAllTools(),
system: this.buildSystemPrompt()
});
// 4. 检查是否有工具调用
const hasToolUse = response.content.some(
block => block.type === "tool_use"
);
if (!hasToolUse) {
// 没有工具调用 → 结束循环
this.displayResponse(response);
break;
}
// 5. 执行工具调用
const toolResults = await this.executeTools(
response.content.filter(b => b.type === "tool_use")
);
// 6. 将结果添加到对话历史
this.conversationHistory.push({
role: "assistant",
content: response.content
});
this.conversationHistory.push({
role: "user",
content: toolResults
});
// 7. 注入系统提醒(System Reminders)
this.injectSystemReminders();
// 8. 检查上下文窗口,必要时压缩
if (this.getContextUsage() > 0.92) {
await this.compressContext();
}
// 循环继续...
}
}
}
这就是核心调度层主要的一个伪代码示意,
工具层
工具接口
1 | // 工具基础接口 |
工具层的实现,比如文件操作工具
1 | // read_file 工具 |
Shell 执行工具 + Haiku 安全验证
这里用到了Claude家小模型,主要是又快又够用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96class BashTool implements Tool {
name = "bash";
private commandWhitelist: Set<string> = new Set();
async execute(params: {
command: string,
cwd?: string
}): Promise<ToolResult> {
// 1. 提取命令前缀
const prefix = this.extractCommandPrefix(params.command);
// 2. 检查白名单
if (this.commandWhitelist.has(prefix)) {
return await this.executeCommand(params);
}
// 3. 使用 Haiku 快速验证
const safety = await this.verifyCommandSafety(params.command);
if (safety.isDangerous) {
// 询问用户确认
const userApproved = await this.askUserPermission(
params.command,
safety.reason
);
if (!userApproved) {
return {
content: "Command execution denied by user",
is_error: true
};
}
}
// 4. 添加到白名单
if (safety.safePrefix) {
this.commandWhitelist.add(safety.safePrefix);
}
// 5. 执行命令
return await this.executeCommand(params);
}
// 🔥 关键:使用 Haiku 快速安全检查
private async verifyCommandSafety(
command: string
): Promise<CommandSafety> {
const response = await anthropic.messages.create({
model: "claude-3-5-haiku-20241022", // 快速且便宜!
max_tokens: 200,
messages: [{
role: "user",
content: `Analyze this bash command for safety:
Command: ${command}
Respond in JSON:
{
"isDangerous": boolean,
"reason": string,
"safePrefix": string | null // e.g., "npm", "git", "ls"
}
Dangerous commands:
- Delete/modify system files (rm -rf /, etc.)
- Network data exfiltration (curl to unknown hosts)
- Privilege escalation (sudo, chmod 777)
- Irreversible operations without confirmation`
}],
response_format: { type: "json_object" }
});
return JSON.parse(response.content[0].text);
}
private async executeCommand(params: {
command: string,
cwd?: string
}): Promise<ToolResult> {
const { stdout, stderr, exitCode } = await exec(
params.command,
{ cwd: params.cwd || process.cwd() }
);
return {
content: stdout + (stderr ? `\nstderr: ${stderr}` : ''),
is_error: exitCode !== 0,
system_instructions: `
Command executed. Remember to:
- Check exit codes
- Parse output carefully
- Handle errors gracefully
`
};
}
}
任务规划的核心:TODO 工具
1 | // TodoWrite 工具 |
子代理系统:Task 工具的实现
为了调度代理,Claude 使用 Task 工具,提供任务描述(用于在 UI 中标记任务)和提示(然后传递给子代理)。子代理接收的用户提示正是输入的内容。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60// Task 工具(内部称为 I2A/dispatch_agent)
class TaskTool implements Tool {
name = "Task";
private subagentDepth = 0;
private readonly MAX_DEPTH = 1; // 防止递归爆炸!
async execute(params: {
description: string; // UI 显示标签
prompt: string; // 子代理的提示
}): Promise<ToolResult> {
// 1. 深度检查:子代理不能生成子代理
if (this.subagentDepth >= this.MAX_DEPTH) {
return {
content: "Max subagent depth reached",
is_error: true
};
}
// 2. 创建新的代理实例
const subagent = new ClaudeCodeAgent({
parentAgent: this,
depth: this.subagentDepth + 1
});
// 3. UI 显示
this.ui.showSubagentStart(params.description);
// 4. 运行子代理(完全独立的上下文!)
const result = await subagent.run(params.prompt);
// 5. 返回结果给主代理
this.ui.showSubagentComplete(params.description);
return {
content: `Subagent completed: ${params.description}\n\n${result}`,
is_error: false,
system_instructions: `
Subagent task "${params.description}" has completed.
Review the results and continue with your main task.
`
};
}
}
// 使用示例
// Claude 决定:"这个任务太复杂,需要深入调查"
{
"name": "Task",
"input": {
"description": "Investigate authentication bug in login system",
"prompt": "Thoroughly analyze the login.js file and related authentication middleware. Identify the root cause of the session timeout bug reported by users. Check: session configuration, token validation, and database queries."
}
}
// 子代理执行:
// - 独立的上下文窗口
// - 完整的工具访问权限
// - 自己的 TODO 列表
// - 不知道自己是子代理
// - 结果作为普通工具输出返回
h2A 异步消息队列:实时控制
主要是用于和主循环引擎的协同1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73// h2A 异步消息队列
class H2AQueue {
private queue: AsyncQueue<AgentMessage> = new AsyncQueue();
private handlers: Map<MessageType, Handler[]> = new Map();
// 处理各种异步事件
async processMessages() {
while (true) {
const message = await this.queue.dequeue();
switch (message.type) {
case "user_interrupt":
// 用户按 Ctrl+C
this.handleUserInterrupt();
break;
case "context_alert":
// 上下文接近极限
this.triggerContextCompression();
break;
case "tool_permission_needed":
// 工具需要用户许可
await this.askUserPermission(message.data);
break;
case "stream_chunk":
// Claude 流式输出
this.displayStreamChunk(message.data);
break;
case "notification":
// 系统通知
this.showNotification(message.data);
break;
}
}
}
// 注入消息到队列(非阻塞)
enqueue(message: AgentMessage) {
this.queue.enqueue(message);
}
}
// 主循环与 h2A 的协作
class ClaudeCodeAgent {
private h2a: H2AQueue = new H2AQueue();
async run(prompt: string) {
// 启动异步消息处理
this.h2a.start();
while (true) {
// 检查中断信号
if (this.h2a.hasInterrupt()) {
console.log("Operation cancelled by user");
break;
}
// 主循环逻辑...
const response = await this.callClaude(...);
// 流式输出通过 h2A
this.h2a.enqueue({
type: "stream_chunk",
data: response
});
// ...
}
}
}
这样就实现了Claude Code的主题逻辑,看着不太复杂,但是要把这一套都实现好,并且是要结合大模型的逻辑细节都能闭环,还是比较复杂的工程