Skip to content
工具箱

Hooks

Hooks(钩子)是事件驱动的自动化机制。Peri 可以读取 Claude 风格的 hook 配置,并在 Agent 生命周期的关键节点——比如开始一轮推理前、工具调用后、子代理(Subagent)启动时——执行脚本、发起 HTTP 请求或注入指令。具体事件、输入字段与退出语义仍需按当前版本验证。

和 CI/CD pipeline 的 hook 类似,但触发点是 Agent 的行为事件而非 git 事件。你可以用 hooks 来格式化代码、发送通知、校验工具参数,或强制注入项目规范——这些都是确定的自动化行为,不依赖 LLM 自行决策。

以下是当前文档覆盖的核心事件。插件或外部配置在迁移前应以运行时 Hooks 面板和最小测试确认,不要从这张表推导“所有上游事件均已实现”。

事件触发时机典型用途
UserPromptSubmit用户提交消息时,Agent 处理之前注入项目规范、修改 prompt
PreToolUse工具调用执行前校验参数、阻止危险操作
PostToolUse工具调用成功后格式化输出、记录日志
PostToolUseFailure工具调用失败后错误通知、重试判断
PostToolBatch一批并行工具调用全部完成后批量后处理
PermissionRequest权限弹窗出现时自动审批、录音提醒
StopAgent 本轮推理结束后通知用户、后续处理
StopFailure本轮因 API 错误结束时错误上报、降级策略
SubagentStart子代理启动时播放提示音、日志记录
SubagentStop子代理完成时通知、汇总结果
SessionStart会话开始或恢复时环境检查、加载配置
SessionEnd会话结束时清理临时文件、归档
PreCompact上下文压缩前备份关键信息
PostCompact上下文压缩后验证压缩结果
NotificationAgent 等待用户输入时桌面通知、IM 推送

事件的大致时序:SessionStart → UserPromptSubmit → (推理循环: PreToolUse → PostToolUse | PostToolUseFailure → PostToolBatch) → Stop | StopFailure → SessionEnd。

sequenceDiagram
    participant agent as ReAct 循环
    participant hook as HookMiddleware
    participant dispatcher as HookDispatcher
    participant cmd as Command Hook
    participant prompt as Prompt Hook

    agent ->> hook: before_agent()
    hook ->> dispatcher: fire(SessionStart)
    hook ->> dispatcher: fire(UserPromptSubmit)

    loop 工具调用阶段
        agent ->> hook: before_tool()
        hook ->> dispatcher: fire(PreToolUse)
        dispatcher-->>hook: Allow / Block / ModifyInput
        agent ->> hook: after_tool()
        hook ->> dispatcher: fire(PostToolUse)
        agent ->> hook: after_tools_batch()
        hook ->> dispatcher: fire(PostToolBatch)
    end

    agent ->> hook: after_agent()
    hook ->> dispatcher: fire(Stop)
    alt Block
        hook ->> agent: block_continue
    else Allow
        hook ->> dispatcher: fire(Notification)
    end

    dispatcher ->> cmd: Command → shell 脚本
    dispatcher ->> prompt: Prompt → LLM 评估
    cmd-->>dispatcher: Allow / Block / ModifyInput
    prompt-->>dispatcher: Allow / Block / ModifyInput

Hooks 可通过 .claude/settings.json(项目级)或 ~/.claude/settings.json(全局)中的 hooks 字段配置。Peri 支持相同的“事件 → matcher 组 → hook 列表”基本结构,但扩展类型和边界行为可能不同。

一个 hook 配置包含三个层级:事件名 → 匹配器组 → hook 列表。匹配器(matcher)用于按工具名或模式筛选触发条件,为空字符串表示匹配所有。

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Peri needs your attention\" with title \"Peri\"'"
}
]
}
]
}
}

Peri 按以下优先级加载 hooks,后加载的会追加到列表中:

  1. 插件 hooks:插件声明中自带的 hooks
  2. 全局 hooks:~/.claude/settings.json(只读此文件)
  3. 项目 hooks:<project>/.claude/settings.json
  4. 本地 hooks:<project>/.claude/settings.local.json

Peri 支持四种 hook 执行类型,对齐 Claude Code 的 HookType 定义。

最常用的类型。Peri 通过 stdin 传入 JSON 格式的事件上下文(session_id、cwd、tool_name 等),执行指定的 shell 命令。

{
"type": "command",
"command": "python3 ~/.claude/hooks/scripts/hooks.py",
"timeout": 5000
}

命令通过 stdin JSON 获取事件上下文:

{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.json",
"cwd": "/path/to/project",
"permission_mode": "hitl",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": { "command": "rm -rf /" }
}
  • timeout:超时毫秒数,默认 5000
  • status_message:TUI 状态栏显示的执行中提示
  • once:整个会话生命周期内只触发一次
  • async + asyncRewake:异步执行,完成后可唤醒 Agent 继续推理

使用指定模型对上下文进行判断,常用于需要 LLM 决策的场景。模型在 hook 内评估条件并返回结构化决策。

{
"type": "prompt",
"prompt": "判断这个工具调用是否安全。如果不安全,返回 {\"decision\": \"block\", \"reason\": \"...\"}",
"model": "claude-sonnet-4-20250514",
"timeout": 10000
}

Prompt 类型 hook 返回的决策可以阻断工具调用(返回 "block" 或 "ask")或修改输入参数。

向指定 URL 发送 POST 请求,body 为事件上下文 JSON。适合对接外部服务,如企业微信通知、飞书机器人、Slack webhook。

{
"type": "http",
"url": "https://hooks.slack.com/services/xxx",
"headers": { "Content-Type": "application/json" },
"timeout": 5000
}
  • allowed_env_vars:白名单环境变量,用于 URL 中的密钥引用(如 $SLACK_WEBHOOK_URL),防止 SSRF 攻击暴露其他环境变量

启动一个完整的 Agent 循环(最多 50 轮)来执行 hook 逻辑。和 Subagent 类似,但由 hook 系统调度和管理。

{
"type": "agent",
"prompt": "检查本次工具调用的结果,如果发现安全问题,输出警告",
"timeout": 30000,
"once": true
}

matcher 字段支持正则表达式,用于按工具名筛选。Peri 会在触发 hook 前将事件上下文 JSON 序列化,然后与 matcher 进行 regex 匹配——典型用法是按 tool_name 过滤。

// 只匹配 Bash 和 Write 工具
{ "matcher": "Bash|Write" }
// 匹配所有 Edit 操作
{ "matcher": "Edit" }
// 空字符串表示匹配所有
{ "matcher": "" }

当 Agent 等待用户操作时发送 macOS 系统通知:

{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Peri 需要你的关注\" with title \"Peri\"'"
}
]
}
]
}
}

每次文件写入后自动运行 Prettier:

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "python3 -c \"import json,sys,os; d=json.load(sys.stdin); p=d.get('tool_input',{}).get('file_path',''); os.system(f'npx prettier --write {p}') if p else None\""
}
]
}
]
}
}

子代理完成时播放音频文件,提醒用户注意结果:

{
"hooks": {
"SubagentStop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "afplay ~/.claude/hooks/sounds/subagentstop/complete.wav"
}
]
}
]
}
}

在 Bash 和 Write 工具执行前进行安全校验:

{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|Write",
"hooks": [
{
"type": "prompt",
"prompt": "判断以下工具调用是否安全。`rm -rf`、`git push --force`、覆盖系统文件等操作应判定为危险。返回 JSON:{\"decision\": \"block\"|\"allow\", \"reason\": \"...\"}",
"timeout": 10000
}
]
}
]
}
}

在 Peri TUI 中输入 /hooks 打开 Hooks 面板。面板列出所有事件及其已配置的 hook 数量,选中事件可查看每个 hook 的详细信息(类型、匹配器、来源文件、命令)。

  • SSRF 防护:HTTP hook 的 allowed_env_vars 白名单机制限制 URL 中可引用的环境变量,防止密钥泄露
  • 权限门控:部分 hook(如 PreToolUse 中返回 block)会影响工具执行的权限门控(permission gate)
  • Stop block guard:Stop 和 StopFailure hook 的连续触发有保护机制,防止 hook 本身出错导致无限循环
  • 异步安全:async 类型 hook 完成后可选择是否唤醒 Agent(asyncRewake),避免意外打断推理流程

已有 Claude Code hook 配置可以作为迁移起点。请逐个验证事件输入、matcher、超时、退出码和敏感数据处理;Peri 还提供自己的扩展能力:

  • Agent 类型 hook:完整的子代理执行,不只限于 Claude Code 的 stop hook
  • Prompt 注入:Prompt 类型 hook 的决策结果可以注入到 Agent 的下一步推理中
  • 插件 hooks:插件可以在安装时声明 hooks,无需手动配置