Gemini CLI 钩子
Gemini CLI 钩子
Section titled “Gemini CLI 钩子”钩子是 Gemini CLI 在代理循环特定点执行的脚本或程序,使你能够在不修改 CLI 源代码的情况下截获和自定义行为。
有关创建你的第一个钩子以及综合性示例的教程,请参阅 编写钩子指南。
有关 I/O 架构的技术规范,请参阅 钩子参考。
有关安全性、性能和调试的指导原则,请参阅 最佳实践。
钩子是什么?
Section titled “钩子是什么?”使用钩子,你可以:
- 添加上下文: 在模型处理请求之前注入相关信息
- 验证操作: 审查并阻止潜在危险的操作
- 执行策略: 实施安全和合规要求
- 记录交互: 跟踪工具使用和模型响应
- 优化行为: 动态调整工具选择或模型参数
钩子作为代理循环的一部分同步运行——当钩子事件触发时,Gemini CLI 会等待所有匹配的钩子完成后再继续。
安全性和风险
Section titled “安全性和风险”[!WARNING] 钩子以你的用户权限执行任意代码。
通过配置钩子,你明确允许 Gemini CLI 在你的机器上运行 shell 命令。恶意或配置不当的钩子可能导致:
- 数据泄露: 读取敏感文件(如
.env,ssh 密钥)并将它们发送到远程服务器。 - 修改系统: 删除文件,安装恶意软件或更改系统设置。
- 消耗资源: 运行无限循环或使你的系统崩溃。
项目级钩子(在 .gemini/settings.json 中)和扩展钩子在打开来自不可信作者的第三方项目或扩展时特别危险。当 Gemini CLI 第一次检测到新的项目钩子(通过其名称和命令识别)时,它会警告你,但审查这些钩子(以及任何安装的扩展)并信任它们是你的责任。
[!NOTE] 插件钩子需要在进行插件安装或更新时,如果检测到钩子,则必须显示强制性的安全警告和同意流程。您必须明确批准包含钩子的任何插件的安装或更新。
请参阅安全考虑以获取详细的威胁模型和缓解策略。
钩子是由 Gemini CLI 生命周期中的特定事件触发的。下表列出了所有可用的钩子事件:
【翻译后文本】
| 事件 | 触发时机 | 常见用例 |
|---|---|---|
| 会话开始时 | 会话开始时 | 初始化资源,加载上下文 |
| 会话结束时 | 会话结束时 | 清理,保存状态 |
| 用户提交提示后,计划前 | 用户提交提示后,计划前 | 添加上下文,验证提示 |
| 代理循环结束时 | 代理循环结束时 | 审查输出,强制继续 |
| 发送请求到LLM前 | 发送请求到LLM前 | 修改提示,添加指令 |
| 接收到LLM响应后 | 接收到LLM响应后 | 过滤响应,记录交互 |
| LLM选择工具前(在BeforeModel之后) | LLM选择工具前(在BeforeModel之后) | 过滤可用工具,优化选择 |
| 工具执行前 | 工具执行前 | 验证参数,阻止危险操作 |
| 工具执行后 | 工具执行后 | 处理结果,运行测试 |
| 上下文压缩前 | 上下文压缩前 | 保存状态,通知用户 |
| 发生通知时(例如权限) | 发生通知时(例如权限) | 自动批准,记录决策 |
Gemini CLI目前支持命令钩子,运行shell命令或脚本:
{ "type": "command", "command": "$GEMINI_PROJECT_DIR/.gemini/hooks/my-hook.sh", "timeout": 30000}注意: 计划在未来的版本中支持插件钩子(npm包)。
对于与工具相关的事件(BeforeTool, AfterTool),您可以使用过滤器确定哪些工具触发钩子:
{ "hooks": { "BeforeTool": [ { "matcher": "write_file|replace", "hooks": [ /* hooks for write operations */ ] } ] }}匹配器模式:
精确匹配: "read_file" 只匹配 read_file
- 正则表达式:
"write_.*|replace"匹配write_file,replace - 通配符:
"*"或""匹配所有工具
会话事件匹配器:
- 会话开始:
startup,resume,clear - 会话结束:
exit,clear,logout,prompt_input_exit - 预压缩:
manual,auto - 通知:
ToolPermission
钩子输入/输出合约
Section titled “钩子输入/输出合约”命令钩子通信
Section titled “命令钩子通信”钩子通过以下方式通信:
- 输入: 标准输入上的 JSON
- 输出: 退出码 + 标准输出/错误输出
- 0: 成功 - 标准输出显示给用户(或某些事件中作为上下文注入)
- 2: 阻塞错误 - 错误输出显示给代理/用户,操作可能被阻止
- 其他: 非阻塞警告 - 记录但执行继续
公共输入字段
Section titled “公共输入字段”每个钩子接收以下基础字段:
{ "session_id": "abc123", "transcript_path": "/path/to/transcript.jsonl", "cwd": "/path/to/project", "hook_event_name": "BeforeTool", "timestamp": "2025-12-01T10:30:00Z" // ... event-specific fields}事件特定字段
Section titled “事件特定字段”BeforeTool
Section titled “BeforeTool”输入:
{ "tool_name": "write_file", "tool_input": { "file_path": "/path/to/file.ts", "content": "..." }}输出(标准输出上的 JSON):
{ "decision": "allow|deny|ask|block", "reason": "Explanation shown to agent", "systemMessage": "Message shown to user"}或简单的退出码:
- 退出 0 = 允许(标准输出显示给用户)
- 退出 2 = 拒绝(错误输出显示给代理)
AfterTool
Section titled “AfterTool”输入:
{ "tool_name": "read_file", "tool_input": { "file_path": "..." }, "tool_response": "file contents..."}输出:
{ "decision": "allow|deny", "hookSpecificOutput": { "hookEventName": "AfterTool", "additionalContext": "Extra context for agent" }}BeforeAgent
Section titled “BeforeAgent”输入:
{ "prompt": "Fix the authentication bug"}输出:
{ "decision": "allow|deny", "hookSpecificOutput": { "hookEventName": "BeforeAgent", "additionalContext": "Recent project decisions: ..." }}BeforeModel
Section titled “BeforeModel”输入:
{ "llm_request": { "model": "gemini-2.0-flash-exp", "messages": [{ "role": "user", "content": "Hello" }], "config": { "temperature": 0.7 }, "toolConfig": { "functionCallingConfig": { "mode": "AUTO", "allowedFunctionNames": ["read_file", "write_file"] } } }}输出:
{ "decision": "allow", "hookSpecificOutput": { "hookEventName": "BeforeModel", "llm_request": { "messages": [ { "role": "system", "content": "Additional instructions..." }, { "role": "user", "content": "Hello" } ] } }}AfterModel
Section titled “AfterModel”输入:
{ "llm_request": { "model": "gemini-2.0-flash-exp", "messages": [ /* ... */ ], "config": { /* ... */ }, "toolConfig": { /* ... */ } }, "llm_response": { "text": "string", "candidates": [ { "content": { "role": "model", "parts": ["array of content parts"] }, "finishReason": "STOP" } ] }}输出:
{ "hookSpecificOutput": { "hookEventName": "AfterModel", "llm_response": { "candidate": { /* modified response */ } } }}BeforeToolSelection
Section titled “BeforeToolSelection”输入:
{ "llm_request": { "model": "gemini-2.0-flash-exp", "messages": [ /* ... */ ], "toolConfig": { "functionCallingConfig": { "mode": "AUTO", "allowedFunctionNames": [ /* 100+ tools */ ] } } }}输出:
{ "hookSpecificOutput": { "hookEventName": "BeforeToolSelection", "toolConfig": { "functionCallingConfig": { "mode": "ANY", "allowedFunctionNames": ["read_file", "write_file", "replace"] } } }}或简单的输出(逗号分隔的工具名称集将模式设置为 ANY):
echo "read_file,write_file,replace"SessionStart
Section titled “SessionStart”输入:
{ "source": "startup|resume|clear"}输出:
{ "hookSpecificOutput": { "hookEventName": "SessionStart", "additionalContext": "Loaded 5 project memories" }}SessionEnd
Section titled “SessionEnd”输入:
{ "reason": "exit|clear|logout|prompt_input_exit|other"}不期望有结构的输出(但标准输出/错误输出被记录)。
PreCompress
Section titled “PreCompress”输入:
{ "trigger": "manual|auto"}输出:
{ "systemMessage": "Compression starting..."}Notification
Section titled “Notification”输入:
{ "notification_type": "ToolPermission", "message": "string", "details": { /* notification details */ }}输出:
{ "systemMessage": "Notification logged"}输入:
{ "notification_type": "ToolPermission", "message": "string", "details": { /* notification details */ }}输出:
{ "systemMessage": "Notification logged"}钩子定义在 settings.json 文件中通过 hooks 对象进行配置。配置可以在多个级别上指定,并有定义的优先级规则。
钩子配置按照以下执行顺序应用(数字越小,优先级越高):
- 项目设置: 在项目目录中的
.gemini/settings.json(最高优先级) - 用户设置:
~/.gemini/settings.json - 系统设置:
/etc/gemini-cli/settings.json - 扩展: 由已安装扩展定义的内部钩子(最低优先级)。有关扩展如何定义和配置钩子的详细信息,请参阅扩展文档。
如果在不同的配置层中发现了具有相同 名称 和 命令 的多个钩子,Gemini CLI 会将它们去重。来自更高优先级层(例如,项目层)的钩子将被保留,其他钩子将被忽略。
在每个级别内,钩子按照它们在配置中声明的顺序运行。
{ "hooks": { "EventName": [ { "matcher": "pattern", "hooks": [ { "name": "hook-identifier", "type": "command", "command": "./path/to/script.sh", "description": "What this hook does", "timeout": 30000 } ] } ] }}配置属性:
name(字符串,推荐):在/hooks enable/disable命令中使用的钩子的唯一标识符。如果省略,则使用command路径作为标识符。type(字符串,必填):钩子类型 - 目前只支持"command"command(字符串,必填):要执行的脚本或命令的路径description(字符串,可选):在/hooks panel中显示的人类可读描述timeout(数字,可选):超时时间(毫秒)(默认:60000)matcher(字符串,可选):钩子运行时的事件匹配器筛选模式
钩子可以访问以下内容:
【译文】
- 项目根目录:
GEMINI_PROJECT_DIR - 当前会话ID:
GEMINI_SESSION_ID - Gemini API密钥(如果已配置):
GEMINI_API_KEY - 父进程中的所有其他环境变量
查看已注册的钩子
Section titled “查看已注册的钩子”使用 /hooks panel 命令查看所有已注册的钩子:
/hooks panel此命令显示:
- 按事件组织的所有活动钩子
- 钩子来源(用户、项目、系统)
- 钩子类型(命令或插件)
- 执行状态和最近输出
启用和禁用钩子
Section titled “启用和禁用钩子”您可以使用以下命令临时启用或禁用单个钩子:
/hooks enable hook-name/hooks disable hook-name这些命令允许您在不编辑配置文件的情况下控制钩子执行。钩子名称应与您钩子配置中的 name 字段相匹配。通过这些命令所做的更改将保存到您的全局用户设置(~/.gemini/settings.json)。
禁用钩子的配置
Section titled “禁用钩子的配置”要永久禁用钩子,请将它们添加到 hooks.disabled 数组中,在您的 settings.json 中:
{ "hooks": { "disabled": ["secret-scanner", "auto-test"] }}注意: hooks.disabled 数组使用联合合并策略。来自所有配置级别(用户、项目、系统)的禁用钩子会被合并并去重,意味着在任何级别禁用的钩子都会保持禁用。
从Claude Code迁移
Section titled “从Claude Code迁移”如果您已为Claude Code配置了钩子,您可以迁移它们:
gemini hooks migrate --from-claude此命令:
- 读取
.claude/settings.json - 转换事件名称(
PreToolUse→BeforeTool等) - 翻译工具名称(
Bash→run_shell_command,replace→replace) - 更新匹配器模式
- 写入到
.gemini/settings.json
事件名称映射
Section titled “事件名称映射”(以下部分未提供英文原文,故不进行翻译)
| Claude Code | GeminiCLI |
|---|---|
PreToolUse | BeforeTool |
PostToolUse | AfterTool |
UserPromptSubmit | BeforeAgent |
Stop | AfterAgent |
Notification | Notification |
SessionStart | SessionStart |
SessionEnd | SessionEnd |
PreCompact | PreCompress |
工具名称映射
Section titled “工具名称映射”| Claude Code | GeminiCLI |
|---|---|
Bash | run_shell_command |
Edit | replace |
Read | read_file |
Write | write_file |
Glob | glob |
Grep | search_file_content |
LS | list_directory |
工具和事件匹配器参考
Section titled “工具和事件匹配器参考”匹配器可用的工具名称
Section titled “匹配器可用的工具名称”以下内置工具可以在 BeforeTool 和 AfterTool 钩子匹配器中使用:
read_file- 读取单个文件read_many_files- 一次性读取多个文件write_file- 创建或覆盖文件replace- 使用查找/替换编辑文件内容
list_directory- 列出目录内容glob- 查找与模式匹配的文件search_file_content- 在文件内容中搜索
run_shell_command- 执行Shell命令
google_web_search- 带有定位的Google搜索web_fetch- 获取网页内容
write_todos- 管理TODO项目save_memory- 将信息保存到内存delegate_to_agent- 将任务委派给子代理
{ "matcher": "write_file|replace" // File editing tools}{ "matcher": "read_.*" // All read operations}{ "matcher": "run_shell_command" // Only shell commands}事件特定匹配器
Section titled “事件特定匹配器”会话开始事件匹配器
Section titled “会话开始事件匹配器”startup- 新的会话开始resume- 恢复上一个会话clear- 会话已清除
会话结束事件匹配器
Section titled “会话结束事件匹配器”exit- 正常退出clear- 会话已清除logout- 用户已登出prompt_input_exit- 从提示输入退出other- 其他原因
预压缩事件匹配器
Section titled “预压缩事件匹配器”manual- 手动触发的压缩auto- 自动触发的压缩
通知事件匹配器
Section titled “通知事件匹配器”ToolPermission- 工具权限通知