08. 扩展 Matcha
钩子
钩子是 Matcha CLI 在生命周期节点运行的 **本地命令**:工具前、工具后、会话开始、一轮将要结束,等等。用来拦住危险命令、让一轮持续到测试通过,或记下发生了什么。
快速开始
mkdir -p ~/.matcha/hooks~/.matcha/hooks/session-start.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{ "type": "command", "command": "echo 'Matcha session started in '$(pwd)" }
]
}
]
}
}开始或重启会话。打开 /hooks,确认钩子列在 **Global** 下。
钩子从哪里加载
所有来源会合并:
| 范围 | 路径 | 受信任? |
|---|---|---|
| Global | ~/.matcha/hooks/*.json | 始终 |
| Project | <project>/.matcha/hooks/*.json | 需要文件夹信任 |
| Config | ~/.matcha/config.toml([[hooks.<Event>]]) | 始终 |
| Plugin | 已安装且 **受信任** 的插件内部 | 按插件 |
| Compat | ~/.claude/settings.json、~/.cursor/hooks.json,以及项目侧对应文件 | 同样的信任规则 |
在你信任该文件夹之前,项目钩子会被跳过。/hooks-trust(或启动时 --trust)写入 ~/.matcha/trusted_folders.toml。该授权同时覆盖 **钩子、MCP 和 LSP**,并向下级联到子目录。
/hooks-untrust 撤销它。~/.matcha/hooks/ 里的全局钩子从不需要条目。
Claude 风格的 matcher 名如 Bash 仍匹配 Matcha CLI 的 run_terminal_command。Cursor 的 camelCase 事件名映射到同一事件(preToolUse → PreToolUse)。
你会实际用到的事件
| 事件 | 时机 | 能拦截? |
|---|---|---|
SessionStart | 会话开始 | 不能 |
UserPromptSubmit | 你发出提示 | 不能 |
PreToolUse | 工具即将运行 | 能 — deny |
PostToolUse | 工具成功 | 不能 |
PostToolUseFailure | 工具失败 | 不能 |
Stop | 一轮将要结束 | 能 — 继续工作 |
SessionEnd | 会话结束 | 不能 |
PreToolUse 可以拒绝。Stop / SubagentStop 可以拦住结束,并把原因回传给助手(每轮最多续 8 次)。其他事件只观察。钩子失败时 **失败放行**:崩溃或超时不会拦住工具。只有明确的 {"decision":"deny","reason":"…"}(或 PreToolUse 退出码 2)才会拦住。
matcher 是对真实工具名的正则。MCP 工具显示为 server__tool(例如 linear__save_issue),不是内部的 use_tool 分发器。
拦截式 shell 守卫
~/.matcha/hooks/safe-shell.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "bin/safe-shell.sh", "timeout": 5 }
]
}
]
}
}bin/safe-shell.sh(与 JSON 同级,需可执行):
#!/bin/sh
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.toolInput.command // empty')
if echo "$CMD" | grep -qE '(rm -rf /|mkfs)'; then
echo '{"decision": "deny", "reason": "Blocked potentially destructive command"}'
exit 2
fi
echo '{"decision": "allow"}'事件以 JSON 经 stdin 到达。常见字段包括 hookEventName、sessionId、cwd、workspaceRoot、toolName 和 toolInput。
在 TUI 里管理
/hooks打开扩展模态框的 **Hooks** 标签页。分页器斜杠菜单 **不** 列出 /hooks-list、/hooks-add、/hooks-remove、/hooks-trust 或 /hooks-untrust;这些 shell 命令仍然可用,模态框覆盖同样的工作。
| 按键 | 作用 |
|---|---|
r | 从磁盘重新加载 |
a | 添加钩子文件或目录 |
x 再 y | 移除自定义来源 |
Space | 启用或停用一条钩子 |
f | 过滤 All / Enabled / Disabled |
从 shell 会话(或 ACP)也可以运行:
/hooks-list
/hooks-add ~/.matcha/hooks
/hooks-remove ~/.matcha/hooks
/hooks-trust
/hooks-untrust你应该看到
| 你运行了 | 结果 |
|---|---|
~/.matcha/hooks/ 里的文件 + /hooks | 钩子列在 Global 下 |
带 .matcha/hooks/ 的仓库里执行 /hooks-trust | 项目钩子开始运行 |
PreToolUse deny JSON | 工具被拦住;原因出现在回滚记录里 |
| HTTP 钩子 URL | 不是本篇要教的步骤 |