概述
Hook(钩子)允许您在 CodeBuddy Code 的会话生命周期内插入自定义脚本或命令,实现自动化校验、环境初始化、合规检查等高级能力。
版本要求:本文档针对 CodeBuddy Code v1.16.0 及以上版本中提供的 Hooks 实现。
功能状态:Hook 功能当前处于 Beta 阶段,接口和行为可能在未来版本中调整。
功能概览
完整支持 Hook 事件家族(27+ 种),覆盖工具生命周期(
PreToolUse / PostToolUse / PostToolUseFailure)、会话与子代理(SessionStart / SessionEnd / Stop / SubagentStart / SubagentStop / StopFailure)、用户交互(UserPromptSubmit / Notification / PermissionRequest / PermissionDenied / Elicitation / ElicitationResult)、上下文(PreCompact / PostCompact / InstructionsLoaded / ConfigChange)、任务与团队(TaskCreated / TaskCompleted / TeammateIdle)、文件与环境(FileChanged / CwdChanged / WorktreeCreate / WorktreeRemove)以及启动/维护(Setup)。完整事件清单见插件参考的事件表。在自定义 Agent / Skill 的 frontmatter 里直接声明 hooks,scope 与 subagent 生命周期绑定(详见本文末尾章节)。
支持基于正则表达式的 matcher,可按工具名称或事件上下文筛选执行。
自动注入
session_id、会话转录文件、当前工作目录等上下文信息。支持退出码与 JSON 输出双模式,提供清晰的决策语义。
支持 CLI
/hooks 面板进行图形化配置,所有外部修改需在面板审核后生效,保障安全。钩子脚本在 60 秒超时后自动终止,不影响其他 hook 执行。
配置
CodeBuddy Code hooks 存储在您的设置文件中:
作用域 | 文件路径 | 说明 |
用户级 | ~/.codebuddy/settings.json | 适用于所有项目 |
项目级 | <项目根>/.codebuddy/settings.json | 对项目成员共享的配置 |
项目本地 | <项目根>/.codebuddy/settings.local.json | 本地未提交配置 |
企业策略 | 集成发布的策略文件 | 受企业统一管理 |
配置合并规则:来自不同作用域的 hooks 会合并而非覆盖。同一事件的所有匹配 hooks 都会并行执行。
结构
Hooks 按匹配器组织,每个匹配器可以有多个 hooks:
{"hooks": {"EventName": [{"matcher": "ToolPattern","hooks": [{"type": "command","command": "your-command-here"}]}]}}
关键字段:
matcher:用于匹配工具名称的正则表达式模式,区分大小写(仅适用于 PreToolUse 和 PostToolUse)
简单字符串匹配:
Write 会匹配任何包含 "Write" 的工具名(如 Write、NotebookWrite)精确匹配:使用
^Write$ 仅匹配 Write 工具多工具匹配:
Edit|Write 或 Web.*匹配所有工具:以下三种方式等效
使用
* 字符使用空字符串
""省略 matcher 字段
hooks:当模式匹配时执行的 hooks 数组
type: Hook 执行类型 -
"command" 用于 shell 命令,或 "prompt" 用于基于 LLM 的评估command: (对于 type:
"command")要执行的 shell 命令(可以使用 $CODEBUDDY_PROJECT_DIR 环境变量)。在 macOS/Linux 上使用用户默认 shell($SHELL)执行,在 Windows 上强制使用 Git Bash 执行(不支持 cmd.exe 或 PowerShell),因此命令需兼容 bash 语法prompt: (对于 type:
"prompt")发送给 LLM 进行评估的提示词(仅支持 Stop、UserPromptSubmit、PreToolUse 事件)timeout: (可选)hook 运行多长时间(以秒为单位)后取消该特定 hook
对于不使用匹配器的事件(如 UserPromptSubmit、Stop 和 SubagentStop),您可以省略 matcher 字段:
{"hooks": {"UserPromptSubmit": [{"hooks": [{"type": "command","command": "python3 /path/to/prompt-validator.py"}]}]}}
项目特定的 Hook 脚本
您可以使用环境变量
CODEBUDDY_PROJECT_DIR(仅在 CodeBuddy Code 生成 hook 命令时可用)来引用存储在项目中的脚本:{"hooks": {"PostToolUse": [{"matcher": "Write|Edit","hooks": [{"type": "command","command": "\\"$CODEBUDDY_PROJECT_DIR\\"/.codebuddy/hooks/check-style.sh"}]}]}}
说明:
如果您的 hook 脚本是 Python 文件,请显式使用
python3 来调用,而不是直接执行 .py 文件。因为在 Windows 上即使脚本包含 shebang 行(#!/usr/bin/env python3),Git Bash 也不一定能正确识别:"command": "python3 \\"$CODEBUDDY_PROJECT_DIR\\"/.codebuddy/hooks/my_hook.py"
插件 Hooks
插件可以提供与用户和项目 hooks 无缝集成的 hooks。启用插件时,插件 hooks 会自动与您的配置合并。
插件 hooks 的工作方式:
插件 hooks 在插件的
hooks/hooks.json 文件中定义,或在 hooks 字段提供的自定义路径的文件中定义当插件启用时,其 hooks 会与用户和项目 hooks 合并
来自不同来源的多个 hooks 可以响应同一事件
插件 hooks 使用
${CODEBUDDY_PLUGIN_ROOT} 环境变量来引用插件文件插件 hook 配置示例:
{"description": "Automatic code formatting","hooks": {"PostToolUse": [{"matcher": "Write|Edit","hooks": [{"type": "command","command": "${CODEBUDDY_PLUGIN_ROOT}/scripts/format.sh","timeout": 30}]}]}}
基于提示词的 Hooks
除了 bash 命令 hooks(
type: "command"),CodeBuddy Code 还支持基于提示词的 hooks(type: "prompt"),使用 LLM 来评估是否允许或阻止某个操作。支持的事件:目前仅支持
Stop、UserPromptSubmit 和 PreToolUse 三种事件。会话级捷径:内置斜杠命令
/goal 是 prompt-based Stop hook 的开箱即用封装——直接输入 /goal <condition> 即可让 CodeBuddy 持续工作直到条件满足,无需手写 hook 配置。如果您的判定逻辑可以靠条件文本表达,优先用 /goal;只有需要更复杂的 prompt 编排或跨多事件协作时才回到本节自己写 prompt hook。基于提示词的 hooks 如何工作
基于提示词的 hooks 不是执行 bash 命令,而是:
1. 将 hook 输入和您的提示词发送给快速小模型(绑定到
lite 槽位的小模型,按 model provider 分别映射)2. LLM 使用包含决策的结构化 JSON 响应
3. CodeBuddy Code 自动处理决策
支持的事件
事件 | 用途 |
Stop | 智能决定 CodeBuddy 是否应继续工作 |
UserPromptSubmit | 使用 LLM 协助验证用户提示 |
PreToolUse | 做出上下文感知的权限决策 |
与 Command Hook 的比较
特性 | Command Hooks | Prompt Hooks |
执行方式 | 运行 bash 脚本 | 查询 LLM |
决策逻辑 | 您在代码中实现 | LLM 评估上下文 |
设置复杂性 | 需要脚本文件 | 只需配置提示词 |
上下文感知 | 受脚本逻辑限制 | 自然语言理解 |
性能 | 快速(本地执行) | 较慢(API 调用) |
适用场景 | 确定性规则 | 上下文感知决策 |
配置
{"hooks": {"Stop": [{"hooks": [{"type": "prompt","prompt": "Evaluate if CodeBuddy should stop: $ARGUMENTS. Check if all tasks are complete."}]}]}}
字段:
type:必须为
"prompt"prompt:发送给 LLM 的提示词文本
使用
$ARGUMENTS 作为 hook 输入 JSON 的占位符,会被直接替换如果不存在
$ARGUMENTS,输入 JSON 会以 \\n\\nARGUMENTS:\\n{JSON} 格式追加到提示词末尾timeout: (可选) 超时时间(秒)(默认: 30 秒)
continueOnBlock: (可选)当 prompt hook 返回
ok: false 时,是否让 Agent 继续工作而不是停止。设为 true 时行为类似 /goal:reason 会注入对话历史,Agent 继续循环直到条件满足。仅对 Stop/SubagentStop 事件有意义。默认为 false(Agent 停止)响应模式
LLM 必须使用包含以下内容的 JSON 响应:
{"ok": true | false,"reason": "Explanation for the decision", // 当 ok 为 false 时必需"impossible": false // 可选,仅 Stop 事件下生效}
响应字段:
ok:true 允许操作,false 阻止操作reason:当 ok 为 false 时必需,显示给 CodeBuddy 的解释impossible:可选布尔值,仅 Stop hook 下有意义。{ok: false, impossible: true} 表示评估器判断"在当前会话里这个目标根本不可能完成"(条件自相矛盾、依赖资源不可用、模型已穷尽合理尝试)。CodeBuddy 不再继续循环,UI 显示"无法达成"终态。普通 {ok: false} 仍按"未达成、继续工作"处理。reason 注入 history 的语义:
Stop hook 返回 {ok: false} 时,reason 文本不是简单地"显示给 CodeBuddy",它会以 isMeta=true 的内部 user message 形式注入到对话 history 中,让主模型在下一轮看到评估器的视角,从而精准补做欠缺的部分。这是 prompt-based Stop hook 能驱动多轮迭代收敛的核心机制(/goal 命令底层就是依赖这条链路)。示例:智能 Stop Hook
{"hooks": {"Stop": [{"hooks": [{"type": "prompt","prompt": "You are evaluating whether CodeBuddy should stop working. Context: $ARGUMENTS\\n\\nAnalyze the conversation and determine if:\\n1. All user-requested tasks are complete\\n2. Any errors need to be addressed\\n3. Follow-up work is needed\\n\\nRespond with JSON: {\\"ok\\": true} to allow stopping, or {\\"ok\\": false, \\"reason\\": \\"your explanation\\"} to continue working.","timeout": 30}]}]}}
示例:持续工作的 Stop Hook(continueOnBlock)
通过设置
continueOnBlock: true,prompt Stop hook 可以在条件不满足时驱动 Agent 继续工作,类似 /goal 的效果:{"hooks": {"Stop": [{"hooks": [{"type": "prompt","prompt": "Check if all tests pass and code is properly formatted. Context: $ARGUMENTS\\n\\nIf tests pass and code is clean, return {\\"ok\\": true}.\\nIf not, return {\\"ok\\": false, \\"reason\\": \\"describe what still needs to be fixed\\"}.","continueOnBlock": true,"timeout": 30}]}]}}
当
continueOnBlock 为 true 时:ok: true → Agent 正常停止ok: false → reason 注入对话历史,Agent 继续工作直到条件满足ok: false, impossible: true → Agent 停止,显示"目标不可达成"当
continueOnBlock 为 false(默认)时:ok: false → Agent 停止,不会继续循环示例:UserPromptSubmit 验证
{"hooks": {"UserPromptSubmit": [{"hooks": [{"type": "prompt","prompt": "Evaluate if this user prompt is safe and appropriate. Input: $ARGUMENTS\\n\\nCheck if:\\n- The prompt contains sensitive information (passwords, secrets)\\n- The request is clear and actionable\\n- Any security concerns exist\\n\\nReturn: {\\"ok\\": true} to allow, or {\\"ok\\": false, \\"reason\\": \\"explanation\\"} to block."}]}]}}
示例:PreToolUse 权限决策
{"hooks": {"PreToolUse": [{"matcher": "Bash","hooks": [{"type": "prompt","prompt": "Evaluate if this bash command should be allowed. Input: $ARGUMENTS\\n\\nCheck if:\\n- The command is safe and non-destructive\\n- It doesn't access sensitive files or directories\\n- It aligns with the user's stated goals\\n\\nReturn: {\\"ok\\": true} to allow, or {\\"ok\\": false, \\"reason\\": \\"explanation\\"} to deny."}]}]}}
使用技巧
在提示词中具体说明:清楚描述您希望 LLM 评估的内容
包含决策标准:列出 LLM 应考虑的因素
测试您的提示词:验证 LLM 为您的用例做出正确的决策
设置适当的超时:默认为 30 秒,如果需要可调整
用于复杂决策:Command hooks 更适合简单的、确定性的规则
Hook 事件
事件类型
事件 | 触发时机 | matcher 字段 | 典型场景 |
PreToolUse | 工具执行前 | 支持(工具名) | 校验命令、二次审批、日志记录 |
PostToolUse | 工具成功执行后 | 支持 | 自动格式化、补充上下文、压缩/替换工具结果 |
Notification | 权限请求或 60 秒无输入提醒 | 部分支持 | 桌面提示、IM 通知 |
UserPromptSubmit | 用户提交消息时<br/>注:不包括内部命令 | 不支持 | 内容审查、上下文注入 |
Stop | 主代理响应结束时 | 不支持 | 要求继续执行、追加提醒 |
SubagentStop | 子代理(TaskTool)结束时 | 不支持 | 子任务继续执行或补充说明 |
PreCompact | 执行上下文压缩前 | 支持( manual/auto) | 保留关键信息、防止压缩 |
SessionStart | 会话创建或恢复时 | 支持( startup/resume/clear/compact) | 环境初始化、变量注入 |
SessionEnd | 会话结束时 | 支持( clear/logout/prompt_input_exit/other) | 清理资源、持久化日志 |
PreToolUse
在 CodeBuddy 创建工具参数之后、处理工具调用之前运行。
常见匹配器:
Task - 子代理任务Bash - Shell 命令Glob - 文件模式匹配Grep - 内容搜索Read - 文件读取Edit - 文件编辑Write - 文件写入WebFetch, WebSearch - Web 操作PostToolUse
在工具成功完成后立即运行。识别与 PreToolUse 相同的匹配器值。
Notification
在 CodeBuddy Code 发送通知时运行。支持匹配器以按通知类型过滤。
常见匹配器(部分支持):
permission_prompt - 来自 CodeBuddy Code 的权限请求idle_prompt - 当 CodeBuddy 等待用户输入时(空闲时间超过 60 秒后)auth_success - 身份验证成功通知elicitation_dialog - 当 CodeBuddy Code 需要 MCP 工具引导的输入时(暂未支持)示例:
{"hooks": {"Notification": [{"matcher": "permission_prompt","hooks": [{"type": "command","command": "/path/to/permission-alert.sh"}]},{"matcher": "idle_prompt","hooks": [{"type": "command","command": "/path/to/idle-notification.sh"}]}]}}
UserPromptSubmit
在用户提交提示词后、CodeBuddy 处理之前运行。这允许您根据提示词/对话添加额外的上下文、验证提示词或阻止某些类型的提示词。
Stop
在主 CodeBuddy Code 代理完成响应时运行。如果停止是由于用户中断而发生的,则不会运行。
会话级捷径:内置斜杠命令
/goal 是 session-scoped prompt-based Stop hook 的封装——/goal <condition> 一行即可注册一个让 CodeBuddy 持续工作到条件满足为止的 Stop hook,并自动处理三态评估(达成 / 未达成继续 / 不可达成)、turn 计数、token 统计、/resume 自动恢复等细节。需要会话级"持续工作直到 X"时优先考虑 /goal,不必手写 hook 配置。SubagentStop
在 CodeBuddy Code 子代理(Agent 工具调用)完成响应时运行。
PreCompact
在 CodeBuddy Code 即将运行压缩操作之前运行。
匹配器:
manual - 从 /compact 调用auto - 从自动压缩调用(由于上下文窗口已满)SessionStart
在 CodeBuddy Code 启动新会话或恢复现有会话时运行。
匹配器:
startup - 从启动调用resume - 从 --resume、--continue 或 /resume 调用clear - 从 /clear 调用compact - 从自动或手动压缩调用SessionEnd
在 CodeBuddy Code 会话结束时运行。用于清理任务、记录会话统计信息或保存会话状态。
reason 字段将是以下之一:
clear - 使用 /clear 命令清除会话logout - 用户注销prompt_input_exit - 用户在提示词输入可见时退出other - 其他退出原因(包括正常退出)Hook 输入
Hooks 通过 stdin 接收包含会话信息和事件特定数据的 JSON 数据:
{// 公共字段"session_id": "string","transcript_path": "string", // 对话 JSON 的路径"cwd": "string", // 调用 hook 时的当前工作目录"permission_mode": "string", // 当前权限模式: "default"、"plan"、"acceptEdits" 或 "bypassPermissions"// 事件特定字段"hook_event_name": "string"// ...}
PreToolUse 输入
{"session_id": "abc123","transcript_path": "/Users/.../.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","cwd": "/Users/...","permission_mode": "default","hook_event_name": "PreToolUse","tool_name": "Write","tool_input": {"file_path": "/path/to/file.txt","content": "file content"}}
PostToolUse 输入
{"session_id": "abc123","transcript_path": "/Users/.../.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","cwd": "/Users/...","permission_mode": "default","hook_event_name": "PostToolUse","tool_name": "Write","tool_input": {"file_path": "/path/to/file.txt","content": "file content"},"tool_response": {"filePath": "/path/to/file.txt","success": true}}
Notification 输入
{"session_id": "abc123","transcript_path": "/Users/.../.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","cwd": "/Users/...","permission_mode": "default","hook_event_name": "Notification","message": "CodeBuddy needs your permission to use Bash","notification_type": "permission_prompt"}
UserPromptSubmit 输入
{"session_id": "abc123","transcript_path": "/Users/.../.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","cwd": "/Users/...","permission_mode": "default","hook_event_name": "UserPromptSubmit","prompt": "Write a function to calculate the factorial of a number"}
Stop 和 SubagentStop 输入
当 CodeBuddy Code 已经由于 stop hook 的结果而继续时,
stop_hook_active 为 true。{"session_id": "abc123","transcript_path": "/Users/xxx/.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","permission_mode": "default","hook_event_name": "Stop","stop_hook_active": true}
PreCompact 输入
对于手动触发,
custom_instructions 来自用户传入 /compact 的内容。对于自动触发,custom_instructions 为空。{"session_id": "abc123","transcript_path": "/Users/xxx/.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","permission_mode": "default","hook_event_name": "PreCompact","trigger": "manual","custom_instructions": ""}
SessionStart 输入
{"session_id": "abc123","transcript_path": "/Users/xxx/.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","permission_mode": "default","hook_event_name": "SessionStart","source": "startup"}
SessionEnd 输入
{"session_id": "abc123","transcript_path": "/Users/xxx/.codebuddy/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl","cwd": "/Users/...","permission_mode": "default","hook_event_name": "SessionEnd","reason": "other"}
Hook 输出
Hooks 有两种方式将输出返回给 CodeBuddy Code。
简单方式: 退出代码
Hooks 通过退出代码、stdout 和 stderr 传达状态:
退出代码 0:成功。stdout 在 transcript 模式(CTRL-R)中显示给用户,但 UserPromptSubmit 和 SessionStart 除外,其中 stdout 会添加到上下文中。
退出代码 2:阻塞错误。消息来源优先级:stdout(JSON 的
reason/stopReason 字段或纯文本)> stderr。即 stderr 仅作为 fallback,只有当 stdout 没有输出任何内容时才会传递给 CodeBuddy。因此调试日志可以安全地写入 stderr,不会污染给 Agent 的反馈消息。其他退出代码:非阻塞错误。stderr 显示给用户,执行继续。
退出代码 2 的行为
注意:
下表中"显示消息"指的是按优先级从 stdout 或 stderr 获取的消息(参见上文 fallback 说明)。
Hook 事件 | 行为 |
PreToolUse | 阻止工具调用,向 CodeBuddy 显示消息 |
PostToolUse | 向 CodeBuddy 显示消息(工具已运行,用于补充上下文);可用 updatedToolOutput 替换工具结果 |
Notification | N/A,仅向用户显示消息 |
UserPromptSubmit | 阻止提示词处理,清除提示词,仅向用户显示消息 |
Stop | 阻止停止,向 CodeBuddy 显示消息并继续对话 |
SubagentStop | 阻止停止,向 CodeBuddy 子代理显示消息并继续执行 |
PreCompact | 阻止压缩操作,仅向用户显示消息 |
SessionStart | N/A,仅向用户显示消息 |
SessionEnd | N/A,仅向用户显示消息 |
高级方式: JSON 输出
Hooks 可以在 stdout 中返回结构化 JSON 以实现更复杂的控制。
公共 JSON 字段
所有 hook 类型都可以包含这些可选字段:
{"continue": true, // CodeBuddy 在 hook 执行后是否继续(默认: true)"stopReason": "string", // 当 continue 为 false 时显示给 CodeBuddy 的消息"reason": "string", // stopReason 的别名,两者等效"suppressOutput": true, // 在 transcript 模式中隐藏 stdout(默认: false)"systemMessage": "string" // 显示给用户的可选警告消息(不传给 Agent)}
消息字段说明:
stopReason / reason:传递给 CodeBuddy Agent 的消息,用于解释为什么阻止操作systemMessage:仅显示给用户的警告信息,不会传给 AgentPreToolUse 决策控制
PreToolUse hooks 可以控制工具调用是否继续。
{"hookSpecificOutput": {"hookEventName": "PreToolUse","permissionDecision": "allow" | "deny" | "ask","permissionDecisionReason": "显示在权限对话框中的原因说明","modifiedInput": {"field_to_modify": "new value"}}}
"allow" 绕过权限系统,直接执行工具"deny" 阻止工具调用执行,permissionDecisionReason 会传递给 Agent"ask" 要求用户在 UI 中确认工具调用,permissionDecisionReason 会显示在确认对话框中modifiedInput 允许您在执行前修改工具的输入参数(部分字段覆盖)PostToolUse 上下文注入与结果替换
PostToolUse 在工具执行完成后触发,无法阻止已执行的操作,但可以:
1. 向 Agent 追加额外上下文(
additionalContext);2. 替换将要发送给 Agent 的工具结果(
updatedToolOutput)。追加上下文(原始工具结果保留,在其后追加一段提示):
{"hookSpecificOutput": {"hookEventName": "PostToolUse","additionalContext": "补充给 CodeBuddy 的额外信息,如代码规范检查结果"}}
替换工具结果(用返回值整个替换原始工具输出后再发给 Agent):
{"hookSpecificOutput": {"hookEventName": "PostToolUse","updatedToolOutput": "精简后的工具输出"}}
updatedToolOutput 对所有工具生效(内置工具与 MCP 工具均可)。典型用途:压缩冗长的工具输出(如超大命令日志、超长文件内容)以节省上下文 token —— 这类"压缩型" hook 依赖的正是替换能力。
与
additionalContext 的区别:additionalContext 是追加(结果只会变长),updatedToolOutput 是替换(结果可以变短)。两者可同时返回:先用
updatedToolOutput 替换,再把 additionalContext 追加到替换后的内容上。对 MCP 工具,返回的
updatedToolOutput 若为数组则原样作为 MCP content 数组,否则包装为单个文本块。注意:
decision: "block" 字段已废弃。由于工具已执行完成,此时无法真正"阻止"操作。UserPromptSubmit 决策控制
{"continue": false, // 设为 false 阻止提示词处理"reason": "阻止原因(仅显示给用户)","hookSpecificOutput": {"hookEventName": "UserPromptSubmit","additionalContext": "注入给 CodeBuddy 的额外上下文"}}
注意:
decision: "block" 字段已废弃,请使用 continue: false。Stop/SubagentStop 决策控制
{"continue": false, // 设为 false 阻止停止,让 Agent 继续工作"reason": "告诉 Agent 为什么需要继续工作的原因"}
注意:
注意:
decision: "block" 字段已废弃,请使用 continue: false。SessionStart 决策控制
{"hookSpecificOutput": {"hookEventName": "SessionStart","additionalContext": "My additional context here"}}
使用 MCP 工具
CodeBuddy Code hooks 与模型上下文协议(MCP)工具无缝配合。
MCP 工具命名
MCP 工具遵循
mcp__<server>__<tool> 模式,例如:mcp__memory__create_entities - Memory 服务器的创建实体工具mcp__filesystem__read_file - Filesystem 服务器的读取文件工具mcp__github__search_repositories - GitHub 服务器的搜索工具为 MCP 工具配置 Hooks
您可以针对特定的 MCP 工具或整个 MCP 服务器:
{"hooks": {"PreToolUse": [{"matcher": "mcp__memory__.*","hooks": [{"type": "command","command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"}]},{"matcher": "mcp__.*__write.*","hooks": [{"type": "command","command": "python3 /home/user/scripts/validate-mcp-write.py"}]}]}}
安全注意事项
免责声明
使用风险自负: CodeBuddy Code hooks 会在您的系统上自动执行任意 shell 命令。通过使用 hooks,您承认:
您对所配置的命令负全部责任
Hooks 可以修改、删除或访问您的用户账户可以访问的任何文件
恶意或编写不当的 hooks 可能导致数据丢失或系统损坏
Tencent Cloud 不提供任何保证,并对因使用 hooks 而导致的任何损害不承担任何责任
您应该在安全环境中彻底测试 hooks,然后再在生产环境中使用
安全实践教程
1. 验证和清理输入 - 永远不要盲目信任输入数据
2. 始终引用 shell 变量 - 使用
"$VAR" 而不是 $VAR3. 阻止路径遍历 - 检查文件路径中的
..4. 使用绝对路径 - 为脚本指定完整路径(对项目路径使用
"$CODEBUDDY_PROJECT_DIR")5. 跳过敏感文件 - 避免
.env、.git/、密钥等配置安全
直接编辑设置文件中的 hooks 不会立即生效。CodeBuddy Code:
1. 在启动时捕获 hooks 的快照
2. 在整个会话期间使用此快照
3. 如果 hooks 在外部被修改,会发出警告
4. 需要在
/hooks 菜单中审查才能应用更改Hook 执行详情
超时:默认 60 秒执行限制,可按命令配置
并行化:所有匹配的 hooks 并行运行
去重:多个相同的 hook 命令会自动去重
执行 Shell:
macOS/Linux:使用用户默认 shell(
$SHELL 环境变量,通常为 bash 或 zsh),回退到 /bin/shWindows:强制使用 Git Bash(不支持 cmd.exe 或 PowerShell)。如果未找到 Git Bash,会报错提示安装 Git for Windows。可通过
CODEBUDDY_CODE_GIT_BASH_PATH 环境变量指定 bash.exe 路径可通过
CODEBUDDY_CODE_SHELL 环境变量覆盖默认 shell(仅支持 POSIX shell:bash、zsh、sh)环境:在当前目录中使用 CodeBuddy Code 的环境运行
CODEBUDDY_PROJECT_DIR 环境变量包含项目根目录的绝对路径输入:通过 stdin 的 JSON
输出:
PreToolUse/PostToolUse/Stop/SubagentStop:在 transcript 中显示进度(Ctrl-R)
Notification/SessionEnd:仅记录到调试(
--debug)UserPromptSubmit/SessionStart: stdout 作为上下文添加给 CodeBuddy
调试
基本故障排除
如果您的 hooks 不工作:
1. 检查配置 - 运行
/hooks 查看您的 hook 是否已注册2. 验证语法 - 确保您的 JSON 设置有效
3. 测试命令 - 首先手动运行 hook 命令
4. 检查权限 - 确保脚本可执行
5. 查看日志 - 使用
codebuddy --debug 查看 hook 执行详情常见问题:
引号未转义 - 在 JSON 字符串中使用
\\"错误的匹配器 - 检查工具名称是否完全匹配(区分大小写)
找不到命令 - 为脚本使用完整路径
高级调试
对于复杂的 hook 问题:
1. 检查 hook 执行 - 使用
codebuddy --debug 查看详细的 hook 执行2. 验证 JSON 模式 - 使用外部工具测试 hook 输入/输出
3. 检查环境变量 - 验证 CodeBuddy Code 的环境是否正确
4. 测试边缘情况 - 尝试使用不寻常的文件路径或输入的 hooks
5. 监控系统资源 - 检查 hook 执行期间的资源耗尽
6. 使用结构化日志 - 在您的 hook 脚本中实现日志记录
调试输出示例
注:该功能暂未支持。
使用
codebuddy --debug 查看 hook 执行详情:[DEBUG] Executing hooks for PostToolUse:Write[DEBUG] Getting matching hook commands for PostToolUse with query: Write[DEBUG] Found 1 hook matchers in settings[DEBUG] Matched 1 hooks for query "Write"[DEBUG] Found 1 hook commands to execute[DEBUG] Executing hook command: <Your command> with timeout 60000ms[DEBUG] Hook command completed with status 0: <Your stdout>
进度消息出现在 transcript 模式 (Ctrl-R) 中,显示:
正在运行哪个 hook
正在执行的命令
成功/失败状态
输出或错误消息
Agent / Skill Frontmatter Hooks
除了在
~/.codebuddy/settings.json 中全局配置 hooks 外,还可以直接在自定义 Agent 的 .md 文件或 Skill 的 SKILL.md 的 YAML frontmatter 里声明 hooks 字段。这种方式让 Hook 与 Agent / Skill 一起作为"原子单位"分发,scope 自动随 subagent 生命周期开闭,不污染主会话。字段格式
hooks 字段结构和 settings.json 完全一致——按事件名分组,每个事件下若干个 {matcher?, hooks[]} 配置;hook type 支持 command / prompt / agent / http 四种:---name: my-reviewerdescription: Code reviewer with pre-tool-use guardhooks:PreToolUse:- matcher: Bashhooks:- type: commandcommand: ./guard.shonce: trueSubagentStop:- hooks:- type: commandcommand: echo "reviewer finished"- type: httpurl: https://example.com/notifymethod: POST---
生命周期与作用域
范围限定:Skill 仅
context: fork 时支持 frontmatter hooks(注入路径无清晰生命周期边界,不接入);自定义 Agent 总是支持。自动注册/清理:subagent 启动时把 frontmatter hooks 注册到
ScopedHookRegistry,subagent 退出时自动注销。Hooks 仅对该 subagent 自身的工具调用 / 生命周期事件生效。Stop → SubagentStop 重写:在 frontmatter 中写 Stop 事件会被自动重写为 SubagentStop——subagent 完成时不会触发主会话的 Stop,写 Stop 是想表达"subagent 自己结束"的语义。与全局 hooks 合并:相同事件下,frontmatter hooks 与
settings.json / 插件 hooks/hooks.json 会叠加(不覆盖),全部并行触发。安全闸门(allowUntrustedFrontmatterHooks)
frontmatter hooks 可以静默触发 Shell 命令,因此来自非内置来源的 frontmatter hooks 默认不会被注册:
来源 | 默认是否注册 |
Product 内置 Agent / Skill | ✔ 自动放行 |
.codebuddy/agents/*.md(用户/项目本地 Agent) | ✖ 默认拒绝 |
.codebuddy/skills/SKILL.md(用户/项目本地 Skill) | ✖ 默认拒绝 |
插件市场分发的 Agent / Skill | ✖ 默认拒绝 |
插件 hooks/hooks.json(不是 frontmatter) | ✔ 不受闸门约束 |
需要启用时,在
~/.codebuddy/settings.json 设置:{"allowUntrustedFrontmatterHooks": true}
被闸门拦截时 CLI 会输出 warning:
[AgentTask] Frontmatter hooks from skill 'xxx' skipped(source not admin-trusted; enable `allowUntrustedFrontmatterHooks` in settings to allow)
容错与诊断
静默丢弃非法定义:单条 hook 不符合 schema 时只跳过该条,不影响整段 hooks 解析;warning 中包含
event 'YYY' invalid: <详细原因> 便于定位。未知事件名:会被 warning 跳过(
unknown event 'XXX'),不会让整个 frontmatter 报废。YAML 完全破损:日志会输出
Malformed YAML frontmatter in '<path>'。运行时调试:
CODEBUDDY_DEBUG=1 启动后可以看到 [ScopedHookRegistry] registered N hook config(s) for scope '<sessionId>' (...) 这样的注册日志,确认 hooks 是否就位。说明: