命令、工具与任务
slash 表、工具表以 2.1.233 制品为准。能力分三层:slash 是用户控制面,Tool 是模型行动面,Task 是长生命周期执行容器。
1. 三层边界:Command、Tool、Task#
能做事的能力分三层:
| 层级 | 面向谁 | 典型入口 | 适合承载 |
|---|---|---|---|
| Command | 用户显式输入 | /mcp、/config、/compact | 配置、查看、管理、导出、模式切换、prompt 展开 |
| Tool | 模型调用 | Read、Bash、Edit、Agent、mcp__... | 文件、Shell、Web、MCP、Agent、Plan、Task 等模型能力 |
| Task | 运行时生命周期 | LocalShellTask、LocalAgentTask | 长任务、后台任务、远程 agent、输出落盘、kill/foreground |
这三层边界很清楚:slash 命令是用户控制面,Tool 是模型行动面,Task 是长生命周期执行容器。
2. 命令系统:src/commands.ts#
src/commands.ts 是 slash 命令总注册表。它不是静态数组,而是多来源汇聚:
bundled skills
+ builtin plugin skills
+ skill dir commands
+ workflow commands
+ plugin commands
+ plugin skills
+ built-in commands
+ dynamic skills
核心函数与机制:
COMMANDS():memoized 的内建命令列表,避免模块初始化时读 config。getSkills(cwd):并行加载 skill dir commands 与 plugin skills,并合并 bundled/builtin plugin skills。loadAllCommands(cwd):并行加载 skills、plugin commands、workflow commands。getCommands(cwd):每次都会重新跑 availability 与isEnabled(),因此/login这类 auth 变化能即时影响命令可见性。clearCommandsCache():清理 command、plugin、skill 多层缓存。getSkillToolCommands():筛出可被SkillTool暴露给模型的 prompt 型命令。getMcpSkillCommands():从AppState.mcp.commands中筛出 MCP 提供的 skills。
命令还带有明确的安全/场景过滤:
REMOTE_SAFE_COMMANDS:--remoteviewer 中允许的本地 TUI 命令,例如/session、/exit、/theme。BRIDGE_SAFE_COMMANDS:从 Remote Control bridge 收到时允许执行的 local 命令,例如/compact、/clear。local-jsx默认禁止。meetsAvailabilityRequirement():按claude-ai、console等 provider/auth 条件过滤。
很多命令通过 feature('...') 或 USER_TYPE 条件引入,例如 assistant、bridge、voice、workflows、ultraplan、buddy、peers、fork、subscribe-pr。同一套源码服务多种发行/实验形态。
2.1 2.1.233 的 slash 表#
制品 slash-commands.txt 从 bundle 扫出 112 个 /name。菜单里不是每一条都开着:不少带 isEnabled / feature / workspace 门。
相对 2.1.88,独立 slash 已经不在表里的包括:
| 旧名 | 2.1.233 怎么走 |
|---|---|
/loop | 表里是 /loops。这条 local-jsx 注册目前 isEnabled 恒 false;循环调度走 CronCreate / CronList / CronDelete 和 .claude/scheduled_tasks.json |
/cost、/stats | /usage |
/vim | /config → Editor mode。Vim 输入子系统还在 |
/output-style | /config。样式在会话开始固定 |
/schedule | 没有独立 slash;调度看 Cron 三件套 |
/files、/debug | 已从 slash 表拿掉 |
/commit、/commit-push-pr | 不在 slash 表;skill 名里还留着 |
扫表扫不到、bundle 里仍注册的:/code-review(alias review,ultra 走 /ultrareview)。
表里新增、值得点名的:/workflows(看 feature)、/auto-mode-setup(要 workspace,且满足 auto 条件)、/artifacts、/background、/pause-memory、/reload-skills、/recap、/memory(编辑 CLAUDE.md 和 memory 设置)。
3. Tool 协议:src/Tool.ts#
Tool 不是简单的 name + inputSchema + call()。它是模型 schema、运行时执行、权限安全、UI 展示、进度、结果映射的完整协议。
一个 Tool 主要包含:
- 模型侧:
name、aliases、inputSchema、inputJSONSchema、prompt()、description()、searchHint、shouldDefer、alwaysLoad。 - 执行侧:
call()、validateInput()、isEnabled()、isConcurrencySafe()、isReadOnly()、isDestructive()、interruptBehavior()。 - 权限侧:
checkPermissions()、preparePermissionMatcher()、toAutoClassifierInput()、isOpenWorld()、requiresUserInteraction()。 - 路径/结果侧:
getPath()、maxResultSizeChars、mapToolResultToToolResultBlockParam()、backfillObservableInput()。 - UI 侧:
renderToolUseMessage()、renderToolResultMessage()、renderToolUseProgressMessage()、renderToolUseRejectedMessage()、renderGroupedToolUse()、extractSearchText()。
ToolUseContext 也很重,里面有 commands、tools、MCP clients/resources、agent definitions、permission context、AppState getter/setter、tool JSX setter、notification、OS notification、memory attachment 状态、query tracking、file reading limits、content replacement state 等。
这意味着 Tool 在系统里既是“模型能看见的能力”,也是“UI 能展示的交互单元”,还是“权限系统能判断的动作对象”。
buildTool() 的意义
Tool.ts 末尾的 buildTool() 给常用字段填安全默认值:
isEnabled默认true;isConcurrencySafe默认false,保守地不并发;isReadOnly默认false,保守地认为可能写;isDestructive默认false;checkPermissions默认 allow,但安全相关工具应覆盖;toAutoClassifierInput默认空字符串,安全相关工具必须覆盖;userFacingName默认工具名。
这降低了每个工具实现的样板代码,同时让调用方总能面对完整 Tool 对象。
4. 工具注册表:src/tools.ts#
getAllBaseTools() 是工具集合的 source of truth。默认和条件工具包括:
| 工具族 | 代表工具 | 作用 |
|---|---|---|
| 文件 | FileReadTool、FileEditTool、FileWriteTool、NotebookEditTool | 读写编辑文件和 Notebook |
| Shell | BashTool、PowerShellTool | PowerShell:Windows 没 Git Bash 默认开,有则看 tengu_cobalt_ridge |
| 检索 | GlobTool、GrepTool、WebSearchTool、WebFetchTool | 本地与 Web 检索 |
| Agent | AgentTool、SendMessageTool | 子代理、多代理。TeamCreate/TeamDelete 已在 2.1.178 移除 |
| Plan | EnterPlanModeTool、ExitPlanModeV2Tool、AskUserQuestionTool | 计划模式、退出计划、澄清问题 |
| 任务清单 | TaskCreate / Get / Update / List、TodoWrite | v2 默认 Task 四件套,v1 为 TodoWrite。2.1.233 新模型两套都不给,见 Todo 门控 |
| 后台任务 | TaskOutput、TaskStop | 读/停后台 agent 或 shell |
| MCP | ListMcpResources、ReadMcpResource、动态 MCP tools | 2.1.233 没有单独的 McpAuth |
| 记忆 / 编排 | memory_list / read / write、Workflow、Monitor | 2.1.233 工具表里的一等公民 |
| Worktree/技能 | EnterWorktreeTool、ExitWorktreeTool、SkillTool | 工作树、技能调用。2.1.233 没有 Config 工具 |
| 实验/内部 | REPL 等 | Tungsten / WebBrowser / TerminalCapture / Snip 不在 2.1.233 工具表 |
tools.ts 还提供几个关键过滤:
getToolsForDefaultPreset():列出 default preset 中启用的工具。- blanket deny 过滤:如果 permission context 对某个工具有整工具 deny rule,就在模型看见之前移除。
- MCP server-level deny:例如
mcp__server可以在暴露前过滤该 server 的工具。 - ToolSearch 相关:部分工具可延迟加载,让模型先用
ToolSearchTool找工具。
5. 工具执行编排:services/tools/*#
真正执行 Tool 的逻辑不在 query.ts 里,而在 src/services/tools。
toolOrchestration.ts
runTools() 会根据 tool.isConcurrencySafe(input) 分批:
- 连续 concurrency-safe 工具批量并发执行;
- 非 concurrency-safe 工具单独串行执行;
- 默认最大并发来自
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY,默认 10; - 并发批的 contextModifier 会排队,在批结束后按 tool_use 顺序应用。
这保证读/搜类操作可以并行,写/改状态类操作不会互相踩。
toolExecution.ts
runToolUse() 是单个 tool use 的执行状态机。它负责:
- 按 name/alias 找工具,不存在则返回 tool_result error;
- input schema 校验;
validateInput();- 权限与
canUseTool(); - PreToolUse / PostToolUse / PermissionRequest hooks;
- progress message;
- telemetry 与 tracing;
- MCP auth/session error 包装;
- tool result 大小处理与落盘;
- UI/模型所需的 tool_result message 生成。
StreamingToolExecutor.ts
当 streamingToolExecution gate 开启时,模型流式输出 tool_use block 后,工具可提前开始执行,而不是等整条 assistant message 完成。
它的策略是:
- concurrency-safe 工具可并行;
- 非 concurrency-safe 工具独占;
- progress 立即 yield;
- 结果按工具出现顺序缓冲输出;
- streaming fallback 时 discard 已启动工具,避免旧 tool_use_id 的结果污染新响应;
- Bash 失败会中止 sibling tools,因为 shell 命令常有隐式依赖链;Read/WebFetch 等失败不会取消其他工具;
- 支持
interruptBehavior(),用户新输入时某些工具可取消,某些工具必须阻塞等待。
6. 权限决策链路#
权限入口在 hooks/useCanUseTool.tsx,核心规则在 utils/permissions/permissions.ts。简化后的决策顺序:
- 整工具 deny rule。
- 整工具 ask rule。
- 工具自己的
checkPermissions(),例如 Bash 子命令规则、文件路径安全检查。 - 工具明确 deny。
requiresUserInteraction()的工具即使在 bypass 相关场景也不能静默执行。- 内容级 ask rule 和 safetyCheck 会优先于 bypass。
bypassPermissions或 plan+原本 bypass 可直接 allow。- 整工具 allow rule。
- passthrough 转 ask。
dontAsk把 ask 转 deny。auto模式走 classifier / fast path / deny tracking。- headless 或 async agent 不能弹窗时,先跑 PermissionRequest hooks,再自动 deny。
- interactive 模式进入权限 UI,也可能同时 race bridge/channel callbacks、hooks、classifier。
Auto mode 不是简单“自动同意”。它会:
- 对某些安全检查保持不可自动批准;
- 对 acceptEdits 下会允许的安全编辑走 fast path;
- 对白名单工具跳过 classifier;
- 其余走分类器(默认两阶段 XML;HARD 外泄翻不过,SOFT 才允许点名放行);
- PowerShell 工具如果在,跟 Bash 一样走预检 / 白名单 / 分类器;
- 分类器不可用时 fail-closed;
- 连续/总 deny 超限后,交互退回人工,headless 中止。
细节见 Auto Mode 深度解析。
7. BashTool 为什么很重#
tools/BashTool 是最复杂的工具族之一,因为它既要执行命令,又要理解命令。相关能力包括:
BashTool.tsx:执行、输出截断/落盘、进度、后台任务、UI、sandbox、文件历史、图片输出处理。bashPermissions.ts:命令权限、前缀建议、compound command、heredoc、classifier、sandbox 规则。utils/bash/treeSitterAnalysis.ts:基于 tree-sitter AST 的 quote、compound、pipeline、subshell、heredoc、command substitution 等分析。readOnlyValidation.ts、pathValidation.ts、sedValidation.ts:只读约束、路径约束、sed 编辑约束。commandSemantics.ts:解释命令语义,用于展示和安全判断。
这里的重点不是“能跑 shell”,而是尽量在复杂 shell 语法里保守判断风险。例如:
- compound command 数量过多会直接 fallback 到 ask,避免解析/校验导致 REPL 卡死;
- heredoc 和多行命令不会轻易建议精确 allow rule,而会尽量提取稳定前缀;
- shell wrapper、
sudo、env、xargs等危险前缀不会被自动建议成宽泛规则; - tree-sitter 用来区别真实操作符和被转义/引用的字符,避免只靠正则误判。
8. AgentTool 与多代理#
tools/AgentTool/AgentTool.tsx 说明系统已经把“代理调用代理”当作主路径。它支持:
subagent_type:按 agent definition 选择专用 agent;modeloverride;run_in_background;name:注册到agentNameRegistry,供SendMessage按名路由;name:拉队友。team_name仍接受但已忽略(2.1.178 起隐式成团);isolation: worktree:创建临时 git worktree;- 内部构建可有
isolation: remote,将任务发到 CCR remote 环境; - fork subagent、in-process teammate、async agent、remote agent 等多条路径。
AgentTool 与 Task 系统关系紧密:同步子代理可以直接返回结果;后台/远程子代理会注册 task,输出写文件,UI/模型再通过 task tools 查看状态。
9. 任务系统:src/Task.ts、src/tasks.ts#
Task.ts 定义任务协议:
TaskType:local_bash、local_agent、remote_agent、in_process_teammate、local_workflow、monitor_mcp、dream。TaskStatus:pending、running、completed、failed、killed。isTerminalTaskStatus():终态判断。TaskStateBase:id、type、status、description、start/end、outputFile、outputOffset、notified 等。generateTaskId():按类型前缀 + 8 位 base36 随机串,例如b...、a...、r...。注释明确提到要抵抗 symlink brute-force。getTaskOutputPath(id):任务输出落盘,支持 offset 增量读取。
tasks.ts 是注册表:默认有 LocalShellTask、LocalAgentTask、RemoteAgentTask、DreamTask,按 feature 可追加 LocalWorkflowTask 与 MonitorMcpTask。
10. 阅读建议#
- 想看
/xxx怎么工作:从commands.ts找命令,再看commands/<name>。 - 想看模型为什么能用某能力:从
tools.ts找 Tool,再看tools/<ToolName>。 - 想看一次 tool use 如何执行:读
services/tools/toolExecution.ts与toolOrchestration.ts。 - 想看权限:读
useCanUseTool.tsx、utils/permissions/permissions.ts、具体 Tool 的checkPermissions()。 - 想看后台与多代理:读
Task.ts、tasks.ts、tasks/*、AgentTool。