Skip to content

Gemini CLI 钩子

钩子是 Gemini CLI 在代理循环的特定点执行的脚本或程序,允许你在不修改 CLI 源代码的情况下拦截和自定义行为。

参见编写钩子指南获取创建第一个钩子的教程和完整示例。

参见钩子参考获取 I/O 模式的技术规范。

参见最佳实践获取安全、性能和调试指南。

什么是钩子?

使用钩子,你可以:

  • 添加上下文: 在模型处理请求之前注入相关信息
  • 验证操作: 审查并阻止潜在危险的操作
  • 执行策略: 实施安全和合规要求
  • 记录交互: 跟踪工具使用和模型响应
  • 优化行为: 动态调整工具选择或模型参数

钩子作为代理循环的一部分同步运行——当钩子事件触发时,Gemini CLI 会等待所有匹配的钩子完成后再继续。

核心概念

钩子事件

钩子由 Gemini CLI 生命周期中的特定事件触发。下表列出了所有可用的钩子事件:

事件触发时机常见用例
SessionStart会话开始时初始化资源、加载上下文
SessionEnd会话结束时清理、保存状态
BeforeAgent用户提交提示后、规划前添加上下文、验证提示
AfterAgent代理循环结束时审查输出、强制继续
BeforeModel发送请求到 LLM 之前修改提示、添加指令
AfterModel收到 LLM 响应后过滤响应、记录交互
BeforeToolSelectionLLM 选择工具之前(在 BeforeModel 之后)过滤可用工具、优化选择
BeforeTool工具执行之前验证参数、阻止危险操作
AfterTool工具执行之后处理结果、运行测试
PreCompress上下文压缩之前保存状态、通知用户
Notification通知发生时(如权限请求)自动批准、记录决策

钩子类型

Gemini CLI 目前支持运行 shell 命令或脚本的命令钩子

json
{
  "type": "command",
  "command": "$GEMINI_PROJECT_DIR/.gemini/hooks/my-hook.sh",
  "timeout": 30000
}

注意: 插件钩子(npm 包)计划在未来版本中发布。

匹配器

对于工具相关事件(BeforeToolAfterTool),你可以过滤哪些工具触发钩子:

json
{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          /* 写操作的钩子 */
        ]
      }
    ]
  }
}

匹配器模式:

  • 精确匹配: "read_file" 只匹配 read_file
  • 正则表达式: "write_.*|replace" 匹配 write_filereplace
  • 通配符: "*""" 匹配所有工具

会话事件匹配器:

  • SessionStart: startupresumeclear
  • SessionEnd: exitclearlogoutprompt_input_exit
  • PreCompress: manualauto
  • Notification: ToolPermission

钩子输入/输出契约

命令钩子通信

钩子通过以下方式通信:

  • 输入: stdin 上的 JSON
  • 输出: 退出码 + stdout/stderr

退出码

  • 0: 成功 - stdout 显示给用户(或对某些事件注入为上下文)
  • 2: 阻塞错误 - stderr 显示给代理/用户,操作可能被阻止
  • 其他: 非阻塞警告 - 记录但继续执行

通用输入字段

每个钩子都会收到这些基本字段:

json
{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.jsonl",
  "cwd": "/path/to/project",
  "hook_event_name": "BeforeTool",
  "timestamp": "2025-12-01T10:30:00Z"
  // ... 事件特定字段
}

事件特定字段

BeforeTool

输入:

json
{
  "tool_name": "write_file",
  "tool_input": {
    "file_path": "/path/to/file.ts",
    "content": "..."
  }
}

输出(stdout 上的 JSON):

json
{
  "decision": "allow|deny|ask|block",
  "reason": "显示给代理的解释",
  "systemMessage": "显示给用户的消息"
}

或简单的退出码:

  • 退出 0 = 允许(stdout 显示给用户)
  • 退出 2 = 拒绝(stderr 显示给代理)

AfterTool

输入:

json
{
  "tool_name": "read_file",
  "tool_input": { "file_path": "..." },
  "tool_response": "文件内容..."
}

输出:

json
{
  "decision": "allow|deny",
  "hookSpecificOutput": {
    "hookEventName": "AfterTool",
    "additionalContext": "给代理的额外上下文"
  }
}

BeforeAgent

输入:

json
{
  "prompt": "修复认证 bug"
}

输出:

json
{
  "decision": "allow|deny",
  "hookSpecificOutput": {
    "hookEventName": "BeforeAgent",
    "additionalContext": "最近的项目决策:..."
  }
}

BeforeModel

输入:

json
{
  "llm_request": {
    "model": "gemini-2.0-flash-exp",
    "messages": [{ "role": "user", "content": "你好" }],
    "config": { "temperature": 0.7 },
    "toolConfig": {
      "functionCallingConfig": {
        "mode": "AUTO",
        "allowedFunctionNames": ["read_file", "write_file"]
      }
    }
  }
}

输出:

json
{
  "decision": "allow",
  "hookSpecificOutput": {
    "hookEventName": "BeforeModel",
    "llm_request": {
      "messages": [
        { "role": "system", "content": "额外指令..." },
        { "role": "user", "content": "你好" }
      ]
    }
  }
}

AfterModel

输入:

json
{
  "llm_request": {
    "model": "gemini-2.0-flash-exp",
    "messages": [
      /* ... */
    ],
    "config": {
      /* ... */
    },
    "toolConfig": {
      /* ... */
    }
  },
  "llm_response": {
    "text": "string",
    "candidates": [
      {
        "content": {
          "role": "model",
          "parts": ["内容部分数组"]
        },
        "finishReason": "STOP"
      }
    ]
  }
}

输出:

json
{
  "hookSpecificOutput": {
    "hookEventName": "AfterModel",
    "llm_response": {
      "candidate": {
        /* 修改后的响应 */
      }
    }
  }
}

BeforeToolSelection

输入:

json
{
  "llm_request": {
    "model": "gemini-2.0-flash-exp",
    "messages": [
      /* ... */
    ],
    "toolConfig": {
      "functionCallingConfig": {
        "mode": "AUTO",
        "allowedFunctionNames": [
          /* 100+ 工具 */
        ]
      }
    }
  }
}

输出:

json
{
  "hookSpecificOutput": {
    "hookEventName": "BeforeToolSelection",
    "toolConfig": {
      "functionCallingConfig": {
        "mode": "ANY",
        "allowedFunctionNames": ["read_file", "write_file", "replace"]
      }
    }
  }
}

或简单输出(逗号分隔的工具名称将模式设置为 ANY):

bash
echo "read_file,write_file,replace"

SessionStart

输入:

json
{
  "source": "startup|resume|clear"
}

输出:

json
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "已加载 5 个项目记忆"
  }
}

SessionEnd

输入:

json
{
  "reason": "exit|clear|logout|prompt_input_exit|other"
}

不期望结构化输出(但 stdout/stderr 会被记录)。

PreCompress

输入:

json
{
  "trigger": "manual|auto"
}

输出:

json
{
  "systemMessage": "压缩开始..."
}

Notification

输入:

json
{
  "notification_type": "ToolPermission",
  "message": "string",
  "details": {
    /* 通知详情 */
  }
}

输出:

json
{
  "systemMessage": "通知已记录"
}

配置

钩子定义在 settings.json 文件中使用 hooks 对象配置。配置可以在多个级别指定,具有定义的优先级规则。

配置层级

钩子配置按以下执行顺序应用(数字越小越先运行):

  1. 项目设置: 项目目录中的 .gemini/settings.json(最高优先级)
  2. 用户设置: ~/.gemini/settings.json
  3. 系统设置: /etc/gemini-cli/settings.json
  4. 扩展: 已安装扩展定义的内部钩子(最低优先级)

去重和覆盖

如果在不同配置层级发现具有相同名称命令的多个钩子,Gemini CLI 会对它们进行去重。来自更高优先级层级(如项目)的钩子将被保留,其他的将被忽略。

在每个级别内,钩子按配置中声明的顺序运行。

配置模式

json
{
  "hooks": {
    "EventName": [
      {
        "matcher": "pattern",
        "hooks": [
          {
            "name": "hook-identifier",
            "type": "command",
            "command": "./path/to/script.sh",
            "description": "这个钩子做什么",
            "timeout": 30000
          }
        ]
      }
    ]
  }
}

配置属性:

  • name(字符串,推荐):钩子的唯一标识符,用于 /hooks enable/disable 命令。如果省略,将使用 command 路径作为标识符。
  • type(字符串,必需):钩子类型 - 目前只支持 "command"
  • command(字符串,必需):要执行的脚本或命令的路径
  • description(字符串,可选):在 /hooks panel 中显示的人类可读描述
  • timeout(数字,可选):超时时间(毫秒)(默认:60000)
  • matcher(字符串,可选):过滤钩子何时运行的模式(仅事件匹配器)

环境变量

钩子可以访问:

  • GEMINI_PROJECT_DIR:项目根目录
  • GEMINI_SESSION_ID:当前会话 ID
  • GEMINI_API_KEY:Gemini API 密钥(如果已配置)
  • 父进程的所有其他环境变量

管理钩子

查看已注册的钩子

使用 /hooks panel 命令查看所有已注册的钩子:

bash
/hooks panel

此命令显示:

  • 按事件组织的所有活动钩子
  • 钩子来源(用户、项目、系统)
  • 钩子类型(命令或插件)
  • 执行状态和最近输出

启用和禁用钩子

你可以使用命令临时启用或禁用单个钩子:

bash
/hooks enable hook-name
/hooks disable hook-name

这些命令允许你在不编辑配置文件的情况下控制钩子执行。钩子名称应与钩子配置中的 name 字段匹配。通过这些命令所做的更改会持久化到你的全局用户设置(~/.gemini/settings.json)。

禁用钩子配置

要永久禁用钩子,将它们添加到 settings.json 中的 hooks.disabled 数组:

json
{
  "hooks": {
    "disabled": ["secret-scanner", "auto-test"]
  }
}

注意: hooks.disabled 数组使用 UNION 合并策略。来自所有配置级别(用户、项目、系统)的禁用钩子会被合并和去重,这意味着在任何级别禁用的钩子都会保持禁用状态。

从 Claude Code 迁移

如果你有为 Claude Code 配置的钩子,可以迁移它们:

bash
gemini hooks migrate --from-claude

此命令:

  • 读取 .claude/settings.json
  • 转换事件名称(PreToolUseBeforeTool 等)
  • 翻译工具名称(Bashrun_shell_commandreplacereplace
  • 更新匹配器模式
  • 写入 .gemini/settings.json

事件名称映射

Claude CodeGemini CLI
PreToolUseBeforeTool
PostToolUseAfterTool
UserPromptSubmitBeforeAgent
StopAfterAgent
NotificationNotification
SessionStartSessionStart
SessionEndSessionEnd
PreCompactPreCompress

工具名称映射

Claude CodeGemini CLI
Bashrun_shell_command
Editreplace
Readread_file
Writewrite_file
Globglob
Grepsearch_file_content
LSlist_directory

工具和事件匹配器参考

匹配器可用的工具名称

以下内置工具可用于 BeforeToolAfterTool 钩子匹配器:

文件操作

  • read_file - 读取单个文件
  • read_many_files - 一次读取多个文件
  • write_file - 创建或覆盖文件
  • replace - 使用查找/替换编辑文件内容

文件系统

  • list_directory - 列出目录内容
  • glob - 查找匹配模式的文件
  • search_file_content - 在文件内容中搜索

执行

  • run_shell_command - 执行 shell 命令

Web 和外部

  • google_web_search - 带 grounding 的 Google 搜索
  • web_fetch - 获取网页内容

代理功能

  • write_todos - 管理 TODO 项目
  • save_memory - 将信息保存到记忆
  • delegate_to_agent - 将任务委托给子代理

示例匹配器

json
{
  "matcher": "write_file|replace" // 文件编辑工具
}
json
{
  "matcher": "read_.*" // 所有读取操作
}
json
{
  "matcher": "run_shell_command" // 仅 shell 命令
}
json
{
  "matcher": "*" // 所有工具
}

事件特定匹配器

SessionStart 事件匹配器

  • startup - 全新会话启动
  • resume - 恢复之前的会话
  • clear - 会话已清除

SessionEnd 事件匹配器

  • exit - 正常退出
  • clear - 会话已清除
  • logout - 用户已登出
  • prompt_input_exit - 从提示输入退出
  • other - 其他原因

PreCompress 事件匹配器

  • manual - 手动触发的压缩
  • auto - 自动触发的压缩

Notification 事件匹配器

  • ToolPermission - 工具权限通知

了解更多

aicodex 文档网站