# 工具系统详解 本文件说明:详细介绍 Claude Code 的工具系统,包括所有内置工具的功能、输入 schema、权限模型和核心逻辑。 ## 1. 工具系统架构 ### 1.1 工具注册表 所有内置工具在 `tools.ts` 中注册: ```typescript export function getAllBaseTools(): Tools { return [ AgentTool, TaskOutputTool, BashTool, GlobTool, GrepTool, ExitPlanModeV2Tool, FileReadTool, FileEditTool, FileWriteTool, NotebookEditTool, WebFetchTool, TodoWriteTool, WebSearchTool, TaskStopTool, AskUserQuestionTool, SkillTool, EnterPlanModeTool, // ... 更多工具 ] } ``` ### 1.2 工具调用流程 ``` 用户输入/模型决策 │ ▼ checkPermissions() ────► 权限检查 │ ▼ validateInput() ────► 输入验证 │ ▼ call() ───────────► 工具执行 │ ▼ renderToolResultMessage() ────► 结果渲染 ``` ### 1.3 工具基类接口 所有工具都实现以下核心方法: | 方法 | 描述 | |------|------| | `call(args, context, canUseTool, parentMessage)` | 工具执行入口 | | `description(input, options)` | 获取工具描述 | | `inputSchema` | 输入参数 Zod Schema | | `checkPermissions(input, context)` | 权限检查 | | `validateInput(input, context)` | 输入验证 | | `renderToolUseMessage(input, options)` | 渲染工具调用消息 | | `renderToolResultMessage(content, options)` | 渲染工具结果 | ## 2. BashTool - Shell 命令执行 ### 2.1 功能描述 BashTool 是 Claude Code 最核心的工具之一,负责在用户授权下执行 Shell 命令。 ### 2.2 输入 Schema ```typescript const inputSchema = z.object({ command: z.string().describe('要执行的命令'), cwd: z.string().optional().describe('工作目录'), timeout: z.number().optional().describe('超时时间(毫秒)'), }) ``` ### 2.3 权限模型 **权限检查规则**: 1. 检查命令是否匹配 `alwaysAllowRules` 2. 检查命令是否匹配 `alwaysDenyRules` 3. 检查命令是否属于危险命令(如 `rm -rf`) 4. 用户确认后执行 **危险命令警告**: - `rm -rf` 类删除命令 - 格式化命令(如 `mkfs`) - 覆盖系统文件 ### 2.4 核心逻辑 ```typescript async call({ command, cwd, timeout }, context) { // 1. 展开路径 const fullCommand = expandPath(command) // 2. 权限检查 const decision = await checkBashPermission(fullCommand, context) // 3. 决定是否使用沙箱 const shouldSandbox = await shouldUseSandbox(fullCommand) // 4. 执行命令 if (shouldSandbox) { return executeInSandbox(fullCommand, cwd, timeout) } else { return executeDirect(fullCommand, cwd, timeout) } // 5. 追踪文件变更 if (result.modifiedFiles) { for (const file of result.modifiedFiles) { updateFileHistory(file, 'modified') } } } ``` ### 2.5 沙箱执行 Claude Code 支持使用沙箱执行危险命令: ```typescript async function shouldUseSandbox(command: string): Promise { // 检测命令是否危险 const isDangerous = detectDangerousCommand(command) // 检查用户是否设置了沙箱偏好 const sandboxPreference = getSandboxPreference() return isDangerous || sandboxPreference === 'always' } ``` ## 3. FileReadTool - 文件读取 ### 3.1 功能描述 FileReadTool 用于读取文件内容,支持多种文件类型: - 纯文本文件 - 图片文件(PNG, JPG, GIF, WebP) - PDF 文档 - Jupyter Notebooks ### 3.2 输入 Schema ```typescript const inputSchema = z.object({ file_path: z.string().describe('要读取的文件绝对路径'), offset: z.number().int().nonnegative().optional().describe('起始行号'), limit: z.number().int().positive().optional().describe('读取行数'), pages: z.string().optional().describe('PDF 页码范围(如 "1-5")'), }) ``` ### 3.3 权限模型 - 检查文件路径是否在允许目录下 - 检查是否匹配 deny rules - 检查是否为会话相关文件(特殊处理) ### 3.4 核心逻辑 ```typescript async call({ file_path, offset = 1, limit, pages }, context) { const ext = path.extname(file_path).toLowerCase() // 根据文件类型处理 if (ext === '.ipynb') { return readNotebook(file_path) } else if (IMAGE_EXTENSIONS.has(ext)) { return readImage(file_path) } else if (ext === '.pdf') { return readPDF(file_path, pages) } else { return readTextFile(file_path, offset, limit) } } ``` ### 3.5 特殊处理 **Deduplication(去重)**: - 如果文件未修改且读取范围相同,返回 `file_unchanged` stub - 避免重复发送相同内容浪费 Token **内存新鲜度提示**: ```typescript function memoryFileFreshnessNote(mtimeMs: number): string { const age = Date.now() - mtimeMs if (age < 60000) return '(updated seconds ago)' if (age < 3600000) return `(updated ${Math.floor(age/60000)}m ago)` // ... } ``` ## 4. FileWriteTool - 文件写入 ### 4.1 功能描述 FileWriteTool 用于创建或覆盖文件内容。 ### 4.2 输入 Schema ```typescript const inputSchema = z.object({ file_path: z.string().describe('文件路径'), content: z.string().describe('文件内容'), }) ``` ### 4.3 权限模型 - 写入权限检查 - 目录创建权限 - 危险路径保护(如 `/etc`、`/System`) ### 4.4 核心逻辑 ```typescript async call({ file_path, content }, context) { // 1. 验证路径 const fullPath = expandPath(file_path) // 2. 安全检查 if (isDangerousPath(fullPath)) { throw new Error('Cannot write to protected path') } // 3. 确保目录存在 const dir = path.dirname(fullPath) await ensureDirExists(dir) // 4. 写入文件 await writeFile(fullPath, content) // 5. 更新文件状态缓存 context.readFileState.set(fullPath, { content, timestamp: Date.now(), }) return { success: true, path: fullPath } } ``` ## 5. FileEditTool - 文件编辑 ### 5.1 功能描述 FileEditTool 支持两种编辑模式: 1. **Search/Replace 模式**:通过 old_string 和 new_string 进行替换 2. **Edit 模式**:直接编辑文件内容 ### 5.2 输入 Schema ```typescript const inputSchema = z.object({ file_path: z.string().describe('文件路径'), old_string: z.string().optional().describe('要替换的文本(精确匹配)'), new_string: z.string().optional().describe('替换后的文本'), // 或者使用 partial_diff partial_diff: z.object({ replacements: z.array(z.object({ old_string: z.string(), new_string: z.string(), })) }).optional() }) ``` ### 5.3 权限模型 - 需要有效的 old_string(防止意外覆盖) - 不能用于删除整个文件 - 禁止编辑二进制文件 ### 5.4 核心逻辑 ```typescript async call({ file_path, old_string, new_string, partial_diff }, context) { // 1. 读取当前文件内容 const content = await readFile(file_path) // 2. 执行替换 let newContent: string if (partial_diff) { // 批量替换 newContent = content for (const { old_string, new_string } of partial_diff.replacements) { newContent = applyReplacement(newContent, old_string, new_string) } } else { // 单次替换 newContent = applyReplacement(content, old_string, new_string) } // 3. 验证 old_string 存在且唯一 const occurrences = countOccurrences(content, old_string) if (occurrences === 0) { throw new Error('old_string not found in file') } if (occurrences > 1) { throw new Error('old_string appears multiple times, be more specific') } // 4. 写入文件 await writeFile(file_path, newContent) // 5. 更新缓存 context.readFileState.set(file_path, { content: newContent, timestamp: Date.now(), }) } ``` ## 6. GlobTool - 文件模式匹配 ### 6.1 功能描述 使用 glob 模式查找文件。 ### 6.2 输入 Schema ```typescript const inputSchema = z.object({ pattern: z.string().describe('Glob 模式(如 "**/*.ts")'), cwd: z.string().optional().describe('搜索根目录'), }) ``` ### 6.3 核心逻辑 ```typescript async call({ pattern, cwd }, context) { // 使用 ripgrep 的 glob 功能实现高性能搜索 const results = await execFile('rg', [ '--files-with-matches', '--glob', pattern, cwd || process.cwd() ]) return { files: results.split('\n').filter(Boolean) } } ``` ## 7. GrepTool - 代码搜索 ### 7.1 功能描述 在代码库中搜索匹配文本。 ### 7.2 输入 Schema ```typescript const inputSchema = z.object({ pattern: z.string().describe('搜索模式(支持正则)'), cwd: z.string().optional().describe('搜索目录'), context: z.number().optional().describe('上下文行数'), file_pattern: z.string().optional().describe('文件过滤模式'), }) ``` ### 7.3 核心逻辑 ```typescript async call({ pattern, cwd, context = 3, file_pattern }, context) { const args = [ '--json', '-C', context.toString(), pattern, ] if (file_pattern) { args.push('--glob', file_pattern) } args.push(cwd || '.') const results = await execFile('rg', args) // 解析 JSON 输出 const matches = JSON.parse(results) return { matches: matches.map(parseMatch), count: matches.length } } ``` ## 8. WebFetchTool - 网页获取 ### 8.1 功能描述 获取网页内容。 ### 8.2 输入 Schema ```typescript const inputSchema = z.object({ url: z.string().url().describe('网页 URL'), }) ``` ### 8.3 权限模型 **预批准域名列表**: - anthropic.com - claude.ai - github.com - 主要新闻和文档站点 ### 8.4 核心逻辑 ```typescript async call({ url }, context) { // 1. URL 安全检查 if (!isPreapprovedUrl(url)) { const decision = await context.requestPrompt('web_fetch', url) if (!decision.approved) { throw new Error('URL not approved') } } // 2. 获取网页 const response = await fetch(url) // 3. 解析 HTML const text = await extractText(response) // 4. 清理和格式化 return { content: cleanHtml(text), title: extractTitle(response), url, } } ``` ## 9. WebSearchTool - 网络搜索 ### 9.1 功能描述 执行网络搜索。 ### 9.2 输入 Schema ```typescript const inputSchema = z.object({ query: z.string().describe('搜索查询'), }) ``` ### 9.3 核心逻辑 ```typescript async call({ query }, context) { // 使用搜索引擎 API const results = await searchEngine.query(query) return { results: results.map(r => ({ title: r.title, url: r.url, snippet: r.snippet, })), total: results.length, } } ``` ## 10. AgentTool - 子 Agent ### 10.1 功能描述 AgentTool 允许 Claude 创建和管理子 Agent 来并行执行任务。 ### 10.2 输入 Schema ```typescript const inputSchema = z.object({ agent: z.enum(['general', 'plan', 'explore', ...]).describe('Agent 类型'), prompt: z.string().describe('给 Agent 的指令'), agentId: z.string().optional().describe('现有 Agent ID(用于恢复)'), maxTurns: z.number().optional().describe('最大轮次'), }) ``` ### 10.3 Agent 类型 | 类型 | 描述 | |------|------| | `general` | 通用任务执行 | | `plan` | 计划制定 | | `explore` | 代码探索 | | `verification` | 验证检查 | ### 10.4 核心逻辑 ```typescript async call({ agent, prompt, maxTurns }, context) { // 1. 创建或恢复 Agent const agentId = await createSubAgent({ type: agent, prompt, maxTurns, }) // 2. 执行 Agent const result = await runAgent(agentId, context) // 3. 返回结果 return { output: result.output, agentId, turns: result.turns, } } ``` ## 11. SkillTool - 技能执行 ### 11.1 功能描述 SkillTool 用于执行用户定义的技能(Skills),这些技能以 Markdown 文件形式保存在本地目录中。 ### 11.2 输入 Schema ```typescript const inputSchema = z.object({ name: z.string().describe('技能名称'), args: z.string().optional().describe('传递给技能的参数'), }) ``` ### 11.3 技能定义格式 技能目录结构: ``` ~/.claude/skills/my-skill/ └── skill.md ``` skill.md 格式: ```markdown --- name: my-skill description: 这个技能做什么 --- # My Skill 这个技能用于执行特定任务... ## 使用方法 执行时会运行以下脚本... ``` ### 11.4 核心逻辑 ```typescript async call({ name, args }, context) { // 1. 查找技能定义 const skill = await findSkill(name) if (!skill) { throw new Error(`Skill not found: ${name}`) } // 2. 解析技能定义 const { prompt, script } = parseSkillDefinition(skill) // 3. 执行脚本 const output = await executeScript(script, { args }) return { output, skillName: name, } } ``` ## 12. MCPTool - Model Context Protocol ### 12.1 功能描述 MCPTool 是 MCP(Model Context Protocol)协议的工具包装器,允许调用 MCP 服务器提供的工具。 ### 12.2 输入 Schema ```typescript const inputSchema = z.object({ server: z.string().describe('MCP 服务器名称'), tool: z.string().describe('工具名称'), arguments: z.record(z.string(), z.unknown()).optional().describe('工具参数'), }) ``` ### 12.3 核心逻辑 ```typescript async call({ server, tool, arguments }, context) { // 1. 获取 MCP 客户端 const client = context.mcpClients.find(c => c.name === server) if (!client) { throw new Error(`MCP server not found: ${server}`) } // 2. 发送工具调用请求 const result = await client.callTool(tool, arguments) // 3. 返回结果 return result } ``` ## 13. LSPTool - 语言服务器协议 ### 13.1 功能描述 LSPTool 提供对 Language Server Protocol 的访问,用于代码导航、诊断等。 ### 13.2 核心功能 - 跳转到定义 (Go to Definition) - 查找引用 (Find References) - 代码补全 (Completions) - 诊断信息 (Diagnostics) ## 14. NotebookEditTool - Jupyter Notebook 编辑 ### 14.1 功能描述 NotebookEditTool 专门用于编辑 Jupyter Notebook 文件。 ### 14.2 输入 Schema ```typescript const inputSchema = z.object({ file_path: z.string().describe('Notebook 文件路径'), cell_id: z.string().optional().describe('要编辑的单元格 ID'), new_source: z.string().optional().describe('新单元格内容'), action: z.enum(['insert', 'delete', 'move']).optional().describe('操作类型'), }) ``` ## 15. Task 系列工具 ### 15.1 概述 Task 系列工具提供完整的任务管理功能: | 工具 | 描述 | |------|------| | `TaskCreateTool` | 创建新任务 | | `TaskGetTool` | 获取任务详情 | | `TaskUpdateTool` | 更新任务状态 | | `TaskListTool` | 列出任务 | | `TaskStopTool` | 停止任务 | | `TaskOutputTool` | 获取任务输出 | ### 15.2 TaskCreateTool 输入 Schema ```typescript const inputSchema = z.object({ description: z.string().describe('任务描述'), status: z.enum(['pending', 'in_progress', 'completed']).optional(), priority: z.enum(['low', 'medium', 'high']).optional(), }) ``` ### 15.3 任务状态流转 ``` pending ──► in_progress ──► completed │ │ └──────► failed ``` ## 16. SendMessageTool - 团队消息 ### 16.1 功能描述 SendMessageTool 用于向团队成员发送消息。 ### 16.2 输入 Schema ```typescript const inputSchema = z.object({ recipient: z.string().describe('收件人标识'), message: z.string().describe('消息内容'), }) ``` ## 17. TeamCreateTool - 创建团队 ### 17.1 功能描述 TeamCreateTool 创建一个 Agent 团队,团队成员可以协作完成任务。 ### 17.2 输入 Schema ```typescript const inputSchema = z.object({ name: z.string().describe('团队名称'), members: z.array(z.object({ name: z.string(), role: z.enum(['coordinator', 'worker', 'reviewer']), agentType: z.string().optional(), })).describe('团队成员'), }) ``` ### 17.3 团队角色 | 角色 | 描述 | |------|------| | `coordinator` | 协调者,负责分配任务 | | `worker` | 执行者,负责完成任务 | | `reviewer` | 审核者,负责检查结果 | ## 18. EnterPlanModeTool / ExitPlanModeTool ### 18.1 功能描述 计划模式允许 Claude 在执行前先制定计划,用户确认后再执行。 ### 18.2 输入 Schema ```typescript // EnterPlanModeTool const inputSchema = z.object({ prompt: z.string().optional().describe('计划提示'), }) // ExitPlanModeTool // 无需参数 ``` ## 19. EnterWorktreeTool / ExitWorktreeTool ### 19.1 功能描述 用于创建和切换 Git Worktree,便于在多个分支上同时工作。 ### 19.2 输入 Schema ```typescript // EnterWorktreeTool const inputSchema = z.object({ branch: z.string().describe('分支名'), path: z.string().optional().describe('Worktree 路径'), }) // ExitWorktreeTool const inputSchema = z.object({ path: z.string().optional().describe('要删除的 Worktree 路径'), }) ``` ## 20. ToolSearchTool - 工具搜索 ### 20.1 功能描述 ToolSearchTool 允许模型在运行时搜索可用工具,当工具过多时会延迟加载。 ### 20.2 输入 Schema ```typescript const inputSchema = z.object({ query: z.string().describe('搜索查询'), }) ``` ### 20.3 延迟加载机制 ```typescript // 当工具数量超过阈值时启用延迟加载 const TOOL_SEARCH_THRESHOLD = 50 if (totalTools > TOOL_SEARCH_THRESHOLD) { // 工具标记为 shouldDefer: true // 首次调用时需要通过 ToolSearchTool 激活 } ``` ## 21. CronCreateTool - 定时任务 ### 21.1 功能描述 CronCreateTool 创建定时执行的任务。 ### 21.2 输入 Schema ```typescript const inputSchema = z.object({ schedule: z.string().describe('Cron 表达式'), command: z.string().describe('要执行的命令'), name: z.string().optional().describe('任务名称'), }) ``` ## 22. RemoteTriggerTool - 远程触发 ### 22.1 功能描述 RemoteTriggerTool 允许从远程触发任务执行。 ### 22.2 输入 Schema ```typescript const inputSchema = z.object({ trigger_id: z.string().describe('触发器 ID'), payload: z.record(z.string(), z.unknown()).optional().describe('传递的数据'), }) ``` ## 23. SleepTool - 延迟执行 ### 23.1 功能描述 SleepTool 用于在任务执行中引入延迟。 ### 23.2 输入 Schema ```typescript const inputSchema = z.object({ duration: z.number().describe('延迟时间(秒)'), }) ``` ## 24. SyntheticOutputTool - 结构化输出 ### 24.1 功能描述 SyntheticOutputTool 用于提供符合 JSON Schema 的结构化输出。 ### 24.2 输入 Schema ```typescript const inputSchema = z.object({ schema: z.record(z.string(), z.unknown()).describe('JSON Schema'), data: z.record(z.string(), z.unknown()).describe('输出数据'), }) ``` ### 24.3 验证机制 ```typescript async call({ schema, data }, context) { // 使用 Zod 验证数据 const validator = z.object(schema) const result = validator.safeParse(data) if (!result.success) { throw new Error(`Invalid output: ${result.error.message}`) } return { validated: result.data } } ``` ## 25. 工具权限系统总结 ### 25.1 权限模式 | 模式 | 描述 | 行为 | |------|------|------| | `default` | 默认模式 | 询问危险操作 | | `auto` | 自动模式 | 基于规则自动决定 | | `bypass` | 绕过模式 | 允许所有操作 | | `plan` | 计划模式 | 强制计划模式 | ### 25.2 权限检查流程 ``` 1. validateInput() - 验证输入有效性 │ ▼ 2. checkPermissions() - 检查权限规则 │ ├──► alwaysAllow → 返回允许 │ ├──► alwaysDeny → 返回拒绝 │ └──► 需要询问 → 等待用户确认 ``` ### 25.3 权限规则匹配 ```typescript // 权限规则支持通配符模式 const rules = { 'Bash(rm *)': 'deny', // 拒绝所有 rm 命令 'Bash(git *)': 'allow', // 允许所有 git 命令 'Read(/home/user/src/*)': 'allow', // 允许读取特定目录 } ``` ## 26. 工具渲染系统 ### 26.1 渲染方法 | 方法 | 用途 | |------|------| | `renderToolUseMessage` | 渲染工具调用消息 | | `renderToolUseTag` | 渲染工具标签(如超时标记) | | `renderToolUseProgressMessage` | 渲染进度消息 | | `renderToolResultMessage` | 渲染工具结果 | | `renderToolUseErrorMessage` | 渲染错误消息 | | `renderToolUseRejectedMessage` | 渲染拒绝消息 | ### 26.2 渲染选项 ```typescript interface RenderOptions { style?: 'condensed' | 'full' theme?: ThemeName verbose?: boolean isTranscriptMode?: boolean terminalSize?: { columns: number; rows: number } } ``` ## 27. 总结 Claude Code 的工具系统设计遵循以下原则: 1. **一致性**:所有工具实现统一的 Tool 接口 2. **安全性**:细粒度的权限控制和验证 3. **可扩展性**:支持 MCP、插件、技能等多种扩展机制 4. **用户控制**:用户可精确控制每个工具的使用权限 5. **高性能**:支持流式执行、缓存、去重等优化