游乐游手机版
首页/AI教程/文章详情

Claude Code架构深度拆解:本地Agent运行时全解析

时间:2026-06-16 19:17
ClaudeCode是分层本地智能体运行时,基于React+Ink构建终端UI。工具抽象含提示、执行、权限、UI等多层,调度分编排与执行两层,流式输出时启动。安全对Bash命令纵深校验,权限跨四层。上下文用截断、摘要等分层降级,提示词缓存控成本。Skills、插件与MCP统一为命令面。

不少开发者习惯把 Claude Code 当作一个终端下的 coding agent,但这次流传出来的源码揭示了更完整的面貌:它实际上是一套分层完整的本地 agent 运行时。

事情的起因并不复杂。Anthropic 在 npm 上发布的 @anthropic-ai/claude-code 包中,附带了一个将近 60MB 的 cli.js.map 文件。社区根据 source map 里的 sourcesContent,还原出了大约 1884 个 TypeScript 源文件。虽然这并非完整的内部仓库,但已经足以看清核心架构。

Claude Code 标题图Claude Code 标题图

综合这批材料,可以先确认两点:

  • Claude Code 的核心 agent loop 并不复杂
  • 复杂度主要分布在 loop 外围:终端 UI、工具运行时、权限系统、上下文治理、缓存以及远端 transport

npm 包里究竟泄露了什么

先看 npm 包本体。

Claude Code npm 包与 source map 截图Claude Code npm 包与 source map 截图

最具信息量的不仅是 cli.js.map,还包括包内其他文件:READMEbun.locksdk-tools.d.tsvendor/。这说明发布到 npm 的并非一个轻量包装器,而是一份承载完整产品逻辑的分发包。社区获得的也不只是压缩后的 CLI 二进制,而是足以拆解产品骨架的 npm 包。

再看还原后的 src/ 顶层目录结构。

Claude Code src 目录截图Claude Code src 目录截图

仅看目录名称,就能大致划分出架构:

  • entrypoints/:不同的启动入口
  • main.tsx:主运行时入口点
  • screens/components/context/:终端 UI 层
  • services/:工具服务、MCP、分析及其他运行时服务
  • skills/plugins/commands/:扩展模块
  • bridge/remote/:远端控制与远端会话
  • assistant/coordinator/:自主 agent 与多 agent 逻辑
  • buddy/voice/vim/:功能分支与实验特性

仅从这一层就能看出,Claude Code 绝非一个简单的命令行包装器。它更像一个以终端为首要界面的本地应用——前端是一套 TUI,后端则是完整的 agent 运行时。

终端 UI 为何采用 React + Ink

初次浏览这些文件时,你可能会产生疑问:为什么入口文件叫 main.tsx?为什么目录里有 context/?为什么一个命令行工具到处充斥着 React 组件?

答案在于它的终端 UI 使用的是 Ink——即 React 的终端渲染器。

一旦理解了这一点,许多代码便豁然开朗:

  • 权限确认框是一个组件
  • 工具调用展示是一个组件
  • Markdown 渲染是一个组件
  • REPL 本身也是一个前端界面,只不过运行在终端里

所以 main.tsx 并非命名习惯问题,它就是该产品的前端入口之一。代码中还能看到与滚动性能相关的处理:用户滚动时,后台工作会短暂暂停,定时器会执行 unref(),以避免阻止进程退出。这类处理更像桌面前端,而非普通 CLI。

换句话说,在 Anthropic 的实现中,终端并非“文本输出设备”,而是另一个前端容器。

主执行链路的结构

将主执行路径精简后,大致如下:

  1. entrypoints/cli.tsx 先处理快速路径
  2. main.tsx 完成完整初始化
  3. replLauncher.tsx 挂起 AppREPL
  4. REPL.tsx 组装消息状态、工具池、权限状态、MCP 状态
  5. 输入被传入 query(...)
  6. query.ts 执行 turn loop,处理流式输出、工具调用、上下文整理
  7. toolOrchestration.ts 负责编排调度
  8. toolExecution.ts 负责具体执行

这里容易产生误解:仓库中虽然已有 QueryEngine.ts,但 REPL 当前主路径仍然走 query()QueryEngine 更像是为 SDK / headless 场景及后续抽象预留的层次。

也就是说,Claude Code 并非“一开始就将所有统一为同一套引擎”,而是先稳定 REPL 路径,再将共享能力逐步抽象出来。

Tool 在这里并非普通函数

在这批源码中,Tool 抽象占据了很大比重。

许多人在自行编写 agent 时,工具通常只是:一个 schema、一个 handler、一个返回值。但 Claude Code 中的工具尺度完全不同。Tool.ts 里一个工具对象除了 nameinputSchemacall() 之外,还必须包含许多额外内容:

  • prompt():如何向模型描述自身
  • checkPermissions():权限判断逻辑
  • isReadOnly():是否只读
  • isConcurrencySafe():能否并发执行
  • isDestructive():是否具有破坏性
  • renderToolUseMessage():调用时的展示方式
  • renderToolResultMessage():结果展示方式
  • searchHint:如何被检索到
  • interruptBeha vior:中断时的处理行为

在 Claude Code 中,一个工具并非单纯函数,而是一个同时覆盖提示词层、执行层、权限层和 UI 层的运行时对象。

buildTool 的默认值也很直接。如果新工具未显式声明安全性,系统不会乐观假设:isConcurrencySafe 默认为 falseisReadOnly 默认为 false。这意味着默认将其视为“不可并发、可能写文件”的工具。权限层面同样保持保守方向,不会因为作者忘记声明就自动变为安全工具。

工具调度分为两层

从执行链路来看,Claude Code 的工具部分至少拆分为两层。

toolOrchestration.ts

这一层先进行工具编排,将同一轮模型输出中的工具调用分为两类:可以并发执行的,以及必须串行执行的。它不直接做权限判断,也不直接执行命令,主要负责“谁和谁一起跑,谁需要排队”。

toolExecution.ts

真正将一次调用落地的地方。它需要处理很多事项:输入校验、工具层面校验、权限检查、hook 决策、telemetry、MCP 特殊处理、执行结果回写。

这批泄露材料中还有一个关键细节:工具并非等到整段模型回复结束才开始执行,而是在流式输出期间就启动。

这样做有两个直接好处:第一个工具可以更早启动,可并发的工具也能提前完成。

但这带来了恢复问题:如果模型在流式过程中 fallback 到另一个模型,已经启动的工具怎么办?Claude Code 的处理方式是:在中间 fallback 时,将已经启动的工具停止,然后整轮重新开始。它牺牲了一部分实现简洁性,换取了整轮状态的一致性。

Bash 安全:纵深防御体系

这套源码中最像“线上事故沉淀”的部分,是 Bash 工具相关代码。

因为“让模型执行终端命令”本身就是整个系统中风险最高的能力之一,所以这里的设计并非简单黑名单,而是一条纵深校验链。

bashSecurity.ts 这类逻辑中包含许多独立检查器,分别针对不同攻击面:空命令、heredoc 与命令替换、shell 元字符、危险变量、重定向、Unicode 空白字符、回车注入、$IFS 注入、/proc/*/environ 访问、大括号展开、注释和引号不同步。

其中有两类问题尤为典型。

1. Unicode 空白字符

某些字符看起来像空格,但 shell 并不将其视为普通分隔符。人眼看到的是正常命令,而解析器理解的是另一回事。

2. 回车注入

\r 能让终端后续内容覆盖前面的显示。屏幕上显示的是安全命令,实际执行的可能是另一条。

再往下看,还有一层针对 Zsh 的特殊治理。因为 macOS 默认 shell 为 Zsh,而 Zsh 拥有不少 Bash 所不具备的内建能力,可能绕过普通二进制检查。Claude Code 对这些路径单独做了限制,防范的不是一般误操作,而是有意绕过的行为。

权限系统横跨四层

Claude Code 的权限并非一个简单的弹窗函数,而是一套公共层次。

从代码分布来看,至少有 4 层:

1. Tool.ts

这里定义权限上下文,不仅包含 allow/deny/ask,还包括:mode、additional working directories、bypass/auto mode、prompt beha vior flags。

2. permissionSetup.ts

这一层决定初始权限包络。CLI 传入的 allow/deny 规则、基础工具规则、当前模式,都会在这里先整理好。

3. useCanUseTool.tsx

这是运行时与 UI 的接口层。它要决定的不仅是“能不能用”,还包括:直接放行、直接拒绝、弹出权限框、转给协调器、转给 worker、在某些路径下走自动分类或自动拒绝。

4. toolExecution.ts

真正执行前,还会再次读取当前 app state、hook 决策和权限状态。

这套分布看似较重,但逻辑上是连贯的:权限并非某个工具独有的事务,而是所有工具、本地模式、远端模式、后台 worker 以及 UI 都需要共享的语义。

泄露材料中有一句话清晰概括了后台 agent 的约束:无法向用户弹框确认的后台 agent,遇到需要审批的能力就直接拒绝。拿不到确认,就不执行。这与此套权限系统的整体取向完全一致。

上下文窗口治理:不止一次摘要

Claude Code 在处理上下文窗口时的做法,与许多人写 agent 时的第一反应不同。

很多自制 agent 的做法是:快超限时,做一次压缩或 summarize。

Claude Code 更像一条固定的降级链:

  1. 先截断工具结果
  2. 再裁掉旧消息
  3. 再按消息组做摘要
  4. 如果还不够,再单独发起一次模型调用,对整段会话做更重的压缩

这 4 步并非处理同一个问题:工具输出过长、普通对话历史过长、历史结构尚在但体积过大、整体上下文已必须压缩。

这也是为什么许多简易 agent 在短任务中表现良好,但长任务时开始偏离——它们做了“摘要”,却没有分层降级。

Prompt cache 与成本控制直接融入架构

这次泄露中还有一块非常实在的内容,即 prompt cache 相关逻辑。

Claude Code 的系统提示很长。如果每轮都原样重发,成本会很高,因此代码中专门设置了一条动态边界,将系统提示分为两部分:前半部分是稳定内容,后半部分是工作目录、模型名、MCP 配置等动态内容。这样,stable prefix 更容易命中缓存。

更精细的一点是,与请求头相关的某些状态会被做成“锁存器”。一旦某个模式打开,对应 header 就不再来回切换,因为这种切换会破坏 prompt cache。

会话在 API 调用前就持久化为 transcript,也属于同一思路。表面上看是为了 --resume 恢复,实际上也减少了进程意外中断后整段对话重发的成本。

Skills、Plugins、MCP 最终被收入统一命令面

如果仅看 README,很多人会将 skills、plugins、MCP 视为三种并排的功能。

但从 commands.tsloadSkillsDir.ts 可以看出,它们最终都被收入同一张命令注册表:

  • filesystem skills
  • plugin skills
  • bundled skills
  • built-in plugin skills
  • plugin commands
  • workflow commands

也就是说,Claude Code 并非在主程序边上挂几个扩展点,而是将这些来源统一成一个命令面。

loadSkillsDir.ts 还表明 skills 的来源非常多样:managed policy 目录、用户设置目录、项目目录、--add-dir、legacy commands-as-skills。而且技能可以根据文件路径动态激活。MCP 这边也不是 sidecar 式接入,客户端会直接将 MCP server 暴露的工具和资源收入运行时。

这一层设计决定了 Claude Code 后续的可扩展能力为何能持续增长,因为底座并非一次性写死的。

bridge/remote/ 表明它已不仅限于本地 REPL

源码中至少能看出两套不同的远端栈:

bridge/

这是将本地机器变为远端控制 worker 的层次。包含:feature gating、entitlement/OAuth/policy 检查、基于环境变量或无需环境变量的路径选择、v1/v2 transport 适配、worker 生命周期管理。

remote/

这是让本地客户端连接并显示远端 session 的层次。可以看到:websocket 订阅、HTTP message send、permission request/response handling、远端权限请求到本地 UI 的桥接。

因此,这两套栈并非一回事:bridge/ 是“本地机器被远端控制”,remote/ 是“本地客户端连接远端 session”。而它们最终仍需回到同一套工具语义和权限语义上。这也说明了为什么 Claude Code 的产品边界早已不限于单一本地 REPL。

多 agent 与未发布能力,指向同一条产品延长线

本次泄露中最具传播性的,仍是这些名字:KAIROSAuto-DreamULTRAPLANSPECULATIONBUDDY

其中确实有轻松的元素,例如 BUDDY。源码中呈现了一整套 ASCII 宠物系统,物种、帽子、眼睛、稀有度、名字、性格均已完成,随机方式甚至按用户 ID 做确定性生成。

但这些名字更重要的价值,并非“Claude Code 里藏着什么彩蛋”,而是它们几乎都建立在现有底座之上:KAIROS 指向跨 session 常驻 agent,Auto-Dream 指向空闲时自动整理记忆,SPECULATION 指向预测下一步输入并提前执行,ULTRAPLAN 指向更重的远端规划和多 agent 探索。

而多 agent 层次,在泄露材料中说得非常直白:sub-agent 本质上就是同一个 turn engine,只是换一组参数再运行一遍:换模型、换工具集合、换权限上下文,必要时换 git worktree。

这说明“多 agent”未必意味着重造一套全新系统。很多时候,只要先把 turn engine、权限语义、工具语义和工作区隔离做稳,后面的 worker/coordinator 只是对同一系统的参数化复用。

这批源码中可以直接观察到的工程取向

将这次流出的源码材料从头到尾梳理一遍,最终留下的并非某个神秘 loop,而是这些工程取向:

  • 终端 UI 被视为前端来编写
  • 工具被设计为完整的运行时对象
  • 工具调度支持流式期间启动和整轮重启
  • Bash 风险使用纵深防御处理
  • 权限系统横跨 setup、runtime、UI、remote 4 层
  • 上下文窗口治理是一条分层降级链
  • Prompt cache 与成本控制直接写入架构
  • Skills、plugins、MCP 被收入统一的扩展平面
  • Bridge 与 remote 证明它早已不是单一表面产品

Claude Code 这次最值得关注的,并非“它能不能调用工具”,而是它已经将终端 UI、工具、安全、缓存、权限、扩展和远端 transport 整合成了一套完整产品。

来源:https://cloud.tencent.com.cn/developer/article/2689446
上一篇ClawTeam高效平台让Claude Code、Codex和OpenClaw团队协同作战告别单打独斗 下一篇AI大模型下本体论实践再思考抛弃传统思路
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CapCut AI Docker 一键部署:镜像拉取、端口映射与数据目录配置教程
AI教程 · 2026-06-30

CapCut AI Docker 一键部署:镜像拉取、端口映射与数据目录配置教程

CapCutAI容器化部署需先确认镜像来源与授权范围,再完成环境准备、镜像拉取、端口映射、数据目录挂载和启动验证,适合本地试用、团队内网演示与轻量化AI剪辑服务管理。

CapCut AI Windows本地安装配置2026最新版含下载与环境要求
AI教程 · 2026-06-30

CapCut AI Windows本地安装配置2026最新版含下载与环境要求

CapCutAI与剪映AI在Windows端适合短视频、口播、课程和营销素材剪辑,安装前需确认系统、显卡、存储与网络条件,优先选择官方渠道下载,并完成账号、素材目录、硬件加速和导出参数配置。

Veo新手保姆级安装教程:从下载到首次运行
AI教程 · 2026-06-30

Veo新手保姆级安装教程:从下载到首次运行

Veo适合用文字生成短视频,新手应先确认官方入口、准备账号与设备环境,再按网页或应用方式完成启用。首次运行重点在提示词、参数、素材合规与结果保存,避免使用非官方安装包。

Veo本地模型运行下载路径设置与性能优化指南
AI教程 · 2026-06-30

Veo本地模型运行下载路径设置与性能优化指南

Veo本地模型部署需先确认模型来源与硬件条件,再完成下载校验、目录规划、路径配置和推理参数优化。重点关注显存占用、依赖版本、缓存位置、授权范围与常见报错处理。

Veo安装失败解决指南:常见报错与日志排查及升级回滚方案
AI教程 · 2026-06-30

Veo安装失败解决指南:常见报错与日志排查及升级回滚方案

Veo安装失败通常与系统环境、依赖版本、网络源、权限和缓存有关。排查时应先确认版本要求,再查看安装日志,按报错类型处理,并提前备份项目,确保升级与回滚可控。