Claude Code 初探 一
深入拆解 Anthropic 官方 CLI 智能体的架构设计
前言
Claude Code 是 Anthropic 推出的官方命令行 AI 编程助手。与普通的聊天式 AI 不同,它是一个真正的智能体(Agent)——能够自主规划、调用工具、读写文件、执行命令,并在终端中提供完整的交互式体验。
本文基于对 Claude Code 还原版源码的深度阅读,从运行机制、系统提示词、工具调用、文件操作、网络能力、认证体系、TUI 渲染等多个维度,拆解其核心架构。
一、整体架构:两层循环
Claude Code 的运行时架构可以概括为两层循环:
1 | ┌─────────────────────────────────────────────┐ |
外层 REPL
基于 React Hook 的事件驱动循环,代码位于 src/hooks/useQueueProcessor.ts:
1 | // 当没有活跃查询 + 队列有待处理命令时触发 |
它不是传统的 while(true),而是 React 的 useSyncExternalStore + useEffect 响应式模型——队列变化或查询状态变化时自动触发。
内层 queryLoop
真正的智能体循环,位于 src/query.ts 第 241 行:
1 | while (true) { |
关键点:模型不返回工具调用时循环才结束。一次用户提问可能触发数十轮工具调用。
二、系统提示词:智能体的”宪法”
系统提示词的构建位于 src/constants/prompts.ts,由多个部分拼接而成:
| 模块 | 内容 |
|---|---|
| 身份声明 | “你是 Claude,由 Anthropic 创建” |
| 工具使用规范 | 每个工具的使用场景和注意事项 |
| 安全边界 | 文件操作安全、命令执行限制 |
| 输出格式 | Markdown 格式、简洁风格要求 |
| 环境信息 | 操作系统、shell 类型、工作目录 |
| 动态上下文 | CLAUDE.md 内容、用户偏好 |
提示词中有一个重要的分界线 SYSTEM_PROMPT_DYNAMIC_BOUNDARY:
1 | [静态内容 - 可被 API 缓存] ← 节省 token 费用 |
这是一个精巧的成本优化设计——静态部分利用 Anthropic API 的 prompt caching 特性,避免重复计费。
三、工具调用:从文本到函数
这是 Claude Code 最核心的能力。整个流程如下:
3.1 工具注册
每个工具用 Zod Schema 定义输入参数,启动时通过 zodToJsonSchema() 转换为 JSON Schema,随 API 请求发送给模型:
1 | // src/utils/api.ts |
3.2 模型返回结构化调用
Claude 模型返回的不是纯文本,而是结构化的 JSON:
1 | { |
重要:这是 Anthropic 模型训练层面的能力,不是 prompt engineering 的结果。模型在预训练和 RLHF 阶段就学会了生成符合 JSON Schema 的结构化输出。这也是为什么 Claude Code 只支持 Claude 模型——其他厂商的模型不一定具备相同的工具调用协议。
3.3 客户端派发执行
src/services/tools/toolExecution.ts 负责将模型的结构化输出转为实际的函数调用:
1 | // 第 337 行 |
3.4 流式并发执行
StreamingToolExecutor 更进一步——在模型还在流式输出时就开始执行已解析完的工具:
1 | // src/services/tools/StreamingToolExecutor.ts |
四、文件操作:两条路径
Claude Code 操作文件有两种方式:
路径一:Node.js fs 模块(直接操作)
用于 Read、Write、Edit 等文件工具:
1 | FileWriteTool.call() |
原子写入设计保证了崩溃安全——即使写入过程中断电,原文件也不会损坏。
路径二:child_process.spawn(Shell 命令)
用于 Bash 工具,执行任意终端命令:
1 | // src/utils/Shell.ts |
spawn 创建的是独立子进程,直接调用操作系统的 shell(如 /bin/zsh),可以执行 git、npm、curl 等任何命令。
spawn和fs是完全不同的机制:fs是 Node.js 直接调用内核系统调用(如write(2)),而spawn是创建一个新的 shell 进程来执行命令。
五、网络能力
WebFetch(网页抓取)
使用 axios.get() 发送 HTTP 请求,并有域名黑名单机制:
1 | // 先检查域名是否被封禁 |
WebSearch(网页搜索)
这个并非本地实现,而是利用 Anthropic API 的服务端工具:
1 | // 发送给 API 的工具定义 |
搜索由 Anthropic 后端执行,结果通过 API 返回。客户端只负责展示。
六、认证与安全
认证方式
Claude Code 支持两种认证:
- OAuth 登录:通过
claude.ai网页授权,Token 存储在 macOS Keychain - API Key:直接配置
ANTHROPIC_API_KEY环境变量
优先级链(src/utils/auth.ts):
1 | 环境变量 ANTHROPIC_AUTH_TOKEN |
每次请求校验
认证信息不在本地校验——每次 API 请求都携带 Token/Key,由 Anthropic 后端验证:
1 | // src/services/api/client.ts |
后端负责:身份验证、速率限制、用量计费、安全审计、模型推理。
七、TUI 渲染:终端里的 React
Claude Code 的终端界面不是简单的 console.log,而是一个完整的 React 渲染引擎:
1 | React JSX 组件 |
关键实现
- 自定义 Ink 引擎(
src/ink/):fork 自开源 Ink,深度定制 - React Reconciler(
src/ink/reconciler.ts):将 JSX 桥接到自定义 DOM - Yoga 布局:Facebook 的 Flexbox 布局引擎,计算每个元素的终端位置
- Diff 渲染:维护两帧缓冲区,只重绘变化的字符,避免闪烁
- 16ms 渲染循环:约 60fps 的刷新率
组件体系:
1 | App (顶层容器) |
共 148 个组件文件,位于 src/components/。
八、上下文管理
跨任务上下文持久化
QueryEngine 维护一个 mutableMessages 数组,贯穿整个会话:
1 | // src/QueryEngine.ts |
任务 A 的对话历史对任务 B 完全可见。
上下文压缩
当消息接近上下文窗口限制时,自动触发压缩——用模型总结早期对话,替换原始消息,释放空间。
九、Skill 系统:可扩展的能力
Skill 本质上是预定义的提示词模板 + 工具权限集:
1 | // 技能执行流程 |
例如 simplify 技能会启动 3 个并行的子智能体进行代码审查;commit 技能会引导模型完成 git 提交流程。
总结
Claude Code 的架构可以用一句话概括:
一个以 Claude 模型为大脑、以结构化工具调用为手脚、以 React 终端引擎为面孔的自主智能体。
核心设计亮点:
| 特性 | 实现 |
|---|---|
| 自主决策 | queryLoop while(true) + 模型驱动的工具调用 |
| 安全写入 | 临时文件 + 原子重命名 |
| 流式执行 | StreamingToolExecutor 边接收边执行 |
| 高效渲染 | React + Yoga + Diff 的终端渲染管线 |
| 成本优化 | Prompt Caching 分界线设计 |
| 上下文连续 | mutableMessages 跨任务持久化 |
在下一篇中,我们将继续探索 MCP 协议实现、多智能体协调、以及 Claude Code 的插件扩展机制。
本文基于 Claude Code 还原版源码(版本 999.0.0-restored)的实际代码分析,非逆向工程。