跳转到内容
EN

安装 hook:转换事件

Claude Code 在调用工具前运行 hook,使用的是 PreToolUse 事件。Gemini CLI 把同一时机称为 BeforeTool,Cursor 则称为 preToolUse。原样复制过去的 hook 永远不会触发。工具名称也不相同:Claude Code 的 shell 工具名为 Bash,Gemini CLI 的则是 run_shell_command。

  1. 读取。HarnessKit 从来源 agent 读取 hook 的事件、matcher 和命令,其他内容(例如超时)都不会带过去。
  2. 转换事件。在一张以 Claude Code 事件名为键的表中查找该事件。若目标没有对应的事件,安装失败。详情面板只提示「安装到 Hermes 失败」;具体原因(例如「Hook event ‘Stop’ is not supported by hermes」)只能在批量安装的汇总中看到。
  3. 追加。在目标的 hook 文件中,把命令添加到转换后的事件下。已有的命令不会重复添加。

表中的几组实际对应关系:

Claude Code 事件目标 agent目标中的名称
PreToolUseGemini CLIBeforeTool
PreToolUseCursorpreToolUse
PreToolUseHermespre_tool_call
UserPromptSubmitGemini CLIBeforeAgent
StopDevin Desktoppost_cascade_response
StopHermes没有,安装失败

HarnessKit 支持 10 个 agent 的 hook:Claude Code、Codex、Gemini CLI、Cursor、Copilot、Devin Desktop、Hermes、Kiro、Grok Build 和 Qoder CN。其中 Codex、Copilot、Kiro、Grok Build 和 Qoder CN 与 Claude Code 共有的事件,使用的就是 Claude Code 的名称。

Devin Desktop 有 12 个 hook 事件,HarnessKit 有意只映射了其中 2 个。Devin Desktop 把工具调用拆分为读代码、写代码、运行命令和 MCP 调用。若把其中任何一类对应到 PreToolUse,都会改变 hook 触发的频率,因此 HarnessKit 不映射这几类。

下面是一个检查 shell 命令的 Claude Code hook:

~/.claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "~/bin/check-command.sh" }]
}
]
}
}

安装到 Gemini CLI 后,Gemini CLI 的设置文件中会新增这一条:

~/.gemini/settings.json
{
"hooks": {
"BeforeTool": [
{
"hooks": [
{
"command": "~/bin/check-command.sh",
"type": "command"
}
],
"matcher": "Bash"
}
]
}
}

事件变为 BeforeTool。matcher 仍是 Bash,但 Gemini CLI 没有这个名称的工具。将其改为 run_shell_command 后,hook 才会触发。

Grok Build 有 disabled-hooks 文件,Kiro 的每个 hook 都有 enabled 标志,HarnessKit 直接使用这两种机制。在其他 agent 上,禁用会把 hook 从文件中删除,HarnessKit 在自己的数据库中保留一份快照(原样副本),与 MCP server 的做法相同。

  • crates/hk-core/src/adapter/hook_events.rs 存放事件对应表,以 Claude Code 的事件名为键。
  • crates/hk-core/src/service.rs 在安装时转换事件,此外不转换任何内容。
  • crates/hk-core/src/deployer.rs 每种 hook 格式一个写入器,并决定哪些格式保留 matcher。
  • crates/hk-core/src/manager.rs 负责启用和禁用 hook。
  • src/lib/agent-capabilities.ts 按是否支持 hook、是否支持该范围,把安装到智能体下的 agent 按钮置灰,不看事件。