指南

各 AI 编程 agent 中的 hook:Claude Code、Cursor、Gemini CLI、GitHub Copilot、Kiro 和 Factory Droid(2026)

每个 AI 编程 agent 的 hook 放在哪里?hook 如何阻止命令?

Claude Code 读取 .claude/settings.json 中的 hooks 块,Gemini CLI 读取 .gemini/settings.json 中的 hooks 块,Cursor 读取 .cursor/hooks.json,Factory Droid 读取 .factory/hooks.json,GitHub Copilot 读取 .github/hooks/*.json,Kiro 读取 .kiro/hooks/ 中的任意 JSON 文件。它们都会通过 stdin 以 JSON 形式把事件发送给你的脚本。要阻止工具调用,在 Claude Code、Cursor、Gemini CLI、Factory Droid 和 Kiro CLI 中以退出码 2 退出,或以 JSON 输出 deny 决定(Copilot 使用 permissionDecision,Cursor 使用 permission)。

本文译自英文版指南。命令、配置键与代码均保持原样;如有出入,以英文版为准。 阅读英文原版 → · 其他语言: 日本語 · 한국어 · Español · Português (Brasil)

设置一变,第一时间知道

当这些工具的设置、参数或权限规则发生变化时,每周一封邮件通知你(英文),内容均对照官方文档核实。

快速答案:hook 文件位置

  • Claude Code:.claude/settings.json(项目)或 ~/.claude/settings.json(用户)中的 hooks 键。/hooks 显示已配置的内容。
  • Cursor:.cursor/hooks.json(项目)或 ~/.cursor/hooks.json(用户),需包含 "version": 1。企业和团队 hook 的优先级高于两者。
  • Gemini CLI:.gemini/settings.json(项目)、~/.gemini/settings.json(用户)或 /etc/gemini-cli/settings.json(系统)中的 hooks 键。
  • GitHub Copilot:.github/hooks/*.json 用于 cloud agent 和 Copilot CLI,另有 ~/.copilot/hooks/ 用于 CLI。"version": 1。
  • Kiro:.kiro/hooks/(工作区)或 ~/.kiro/hooks/(全局,CLI V3)中的任意 .json 文件,需包含 "version": "v1"。
  • Factory Droid:.factory/hooks.json(项目)或 ~/.factory/hooks.json(用户)。/hooks 打开 hook 管理器。

hook 如何阻止工具调用

  • Claude Code:以 2 退出的 PreToolUse hook 会阻止该操作,并将其 stderr 作为原因返回。
  • Cursor:以 2 退出,或输出 {"permission": "deny"}。其他非零退出码会放行(fail open),除非 hook 设置了 failClosed: true。
  • Gemini CLI:以 0 退出并输出 {"decision": "deny", "reason": "..."}(推荐方式),或以 2 退出并在 stderr 中给出原因。其他退出码只会发出警告。
  • GitHub Copilot:preToolUse hook 输出 {"permissionDecision": "deny", "permissionDecisionReason": "..."}。不做任何操作则允许调用。
  • Kiro:在 CLI 中,以 2 退出会阻止 PreToolUse。在 IDE 中,任何非零退出都会阻止 Pre Tool Use hook。
  • Factory Droid:在 PreToolUse 中以 2 退出会阻止工具调用。其他非零退出码会被记录,Droid 继续运行。

思路相同,事件名不同

  • 工具运行前:PreToolUse(Claude Code、Kiro、Factory Droid),preToolUse 和 beforeShellExecution(Cursor),BeforeTool(Gemini CLI),preToolUse(Copilot)。
  • 工具运行后:PostToolUse(Claude Code、Kiro、Factory Droid),postToolUse 和 afterFileEdit(Cursor),AfterTool(Gemini CLI),postToolUse(Copilot)。
  • 会话开始:SessionStart(Claude Code、Kiro、Factory Droid、Gemini CLI),sessionStart(Cursor、Copilot)。
  • Agent 完成:Stop(Kiro、Factory Droid),stop(Cursor),agentStop(Copilot)。
  • 提交 prompt:UserPromptSubmit(Kiro、Factory Droid),beforeSubmitPrompt(Cursor),userPromptSubmitted(Copilot)。

同一个 hook,四种语法

Claude Code:.claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

Cursor:.cursor/hooks.json

{
  "version": 1,
  "hooks": {
    "beforeShellExecution": [
      {
        "command": ".cursor/hooks/block-risky.sh",
        "matcher": "rm -rf|curl|wget"
      }
    ]
  }
}

Gemini CLI:.gemini/settings.json

{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          {
            "name": "security-check",
            "type": "command",
            "command": "$GEMINI_PROJECT_DIR/.gemini/hooks/security.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

Kiro:.kiro/hooks/guard-shell.json

{
  "version": "v1",
  "hooks": [
    {
      "name": "Guard shell commands",
      "trigger": "PreToolUse",
      "matcher": "shell",
      "action": {
        "type": "command",
        "command": "./scripts/guard.sh"
      }
    }
  ]
}

常见陷阱

  • Gemini CLI 的 stdout 只能包含最终的 JSON。无效 JSON 会被视为 allow。
  • 当项目 hook 的名称或命令发生变化时(例如 git pull 之后),Gemini CLI 会在运行前发出警告。
  • Copilot 以 JSON 字符串形式传递 toolArgs,因此需要解析两次。cloud agent 将 "ask" 决定视为 "deny",并且只从默认分支加载 hook。
  • Cursor 项目 hook 在项目根目录运行,用户 hook 在 ~/.cursor/ 运行,因此相对脚本路径不同。
  • Kiro 的 agent prompt 操作会启动新的 agent 循环并消耗 credits。Shell 命令操作不会。
  • Factory Droid 的 matcher 是区分大小写的正则表达式。用 commandRegex 按命令文本过滤 Execute 调用。

各 agent 的完整 hook 指南

来源

以下为本指南核对过的官方文档(英文)。 英文版核对日期: 2026-10-18

更多中文指南