Lifecycle hooks

在 Bob 会话的关键节点自动运行 Shell 命令,用于记录活动、注入上下文,或根据自定义逻辑阻止操作。

Lifecycle hooks 让你在 Bob 会话的特定时间点执行 Shell 命令。可用于记录活动、向模型注入上下文、允许或阻止操作,或启动后续自动化流程——无需修改 Bob 本身。

支持的 hooks

Hook触发时机是否阻塞stdout 行为
SessionStart会话开始时执行一次注入为上下文
UserPromptSubmit每次提交 prompt 时是(exit 2注入为上下文
PreToolUse匹配工具运行之前是(exit 2忽略
PostToolUse匹配工具完成之后忽略
StopAgent 停止时忽略

配置

Hooks 在 settings.jsonhooks 键下定义。Bob 会从两个位置合并 hooks:

范围文件
全局(所有 workspace)~/.bob/settings/settings.json
Workspace(当前项目).bob/settings.json

全局 hooks 始终运行。Workspace hooks 在全局 hooks 之上合并,仅适用于当前项目。

Hook 结构示例

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^write_file$",
        "hooks": [
          {
            "type": "command",
            "command": "sh .bob/hooks/check.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

配置字段

字段类型默认值说明
type"command"(无)必填。仅支持 command
commandstring(无)必填。要执行的 Shell 命令。在 macOS/Linux 上通过 sh -c 运行,在 Windows 上通过 cmd /c 运行。
matcherstring(无)可选。与工具名匹配的正则表达式(仅 PreToolUsePostToolUse)。省略则匹配所有工具。
timeoutnumber10Hook 被停止前的秒数。设为 0 可禁用超时。

Hook 参考

在新会话开始时,第一轮之前执行一次。

stdin 结构

{
  "event": "string",
  "session_id": "string"
}

示例 payload

{
  "event": "SessionStart",
  "session_id": "ses_01abc123"
}

Stdout:作为额外会话信息写入模型上下文。

阻塞:不支持 exit 代码 2,会话始终启动。其他非零退出会被记录并忽略。

每次提交 prompt 时,在发送给模型之前执行。

stdin 结构

{
  "event": "string",
  "session_id": "string",
  "prompt": "string"
}

示例 payload

{
  "event": "UserPromptSubmit",
  "session_id": "ses_01abc123",
  "prompt": "Refactor the auth module"
}

Stdout:与 prompt 一起写入模型上下文。

阻塞:exit 代码 2 会阻止 prompt 发送,Bob 显示错误且 prompt 不会提交。

在匹配的工具运行之前执行,让你有机会检查或阻止该操作。

stdin 结构

{
  "event": "string",
  "session_id": "string",
  "tool": "string",
  "input": "object"
}

示例 payload

{
  "event": "PreToolUse",
  "session_id": "ses_01abc123",
  "tool": "write_file",
  "input": {
    "path": "src/index.ts",
    "content": "..."
  }
}

Stdout:忽略。

阻塞:exit 代码 2 会阻止工具运行,Bob 将该工具报告为已阻止并继续会话。

在匹配的工具完成之后执行,无论是否成功。

stdin 结构

{
  "event": "string",
  "session_id": "string",
  "tool": "string",
  "input": "object",
  "output": "string"
}

示例 payload

{
  "event": "PostToolUse",
  "session_id": "ses_01abc123",
  "tool": "write_file",
  "input": {
    "path": "src/index.ts",
    "content": "..."
  },
  "output": "File written successfully"
}

Stdout:忽略。

阻塞:exit 代码 2 无效,工具已经运行完成。

当 agent 停止时,在最后一轮完成后执行。

stdin 结构

{
  "event": "string",
  "session_id": "string"
}

示例 payload

{
  "event": "Stop",
  "session_id": "ses_01abc123"
}

Stdout:忽略。

阻塞:exit 代码 2 无效,会话已经结束。

Exit 代码与阻塞

Exit 代码行为适用范围
0成功:hook 正常执行所有 hooks
2阻止:停止当前操作UserPromptSubmitPreToolUse
其他非零值非阻塞失败:记录并忽略所有 hooks
注意:

UserPromptSubmitPreToolUse 支持阻塞。来自 SessionStartPostToolUseStop 的 exit 代码 2 被视为非阻塞失败。

命令详情

  • 工作目录:命令从任务工作目录(Bob 正在操作的文件夹)运行。
  • 默认超时:10 秒。可通过 timeout 字段为每个 hook 单独覆盖。将 timeout 设为 0 可完全禁用超时。
  • Stderr:写入 Bob 的日志,但不影响 hook 结果。
  • Shell:命令在 macOS 和 Linux 上通过 sh -c 运行,在 Windows 上通过 cmd /c 运行。

快速开始

打开或创建全局设置文件,路径为 ~/.bob/settings/settings.json

添加 hooks 键以及你要使用的 hook。以下示例在每次 write_file 调用之前运行一个脚本:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^write_file$",
        "hooks": [
          {
            "type": "command",
            "command": "sh ~/.bob/hooks/log-write.sh"
          }
        ]
      }
    ]
  }
}

创建脚本文件。以下最简脚本会记录收到的 JSON payload:

#!/bin/sh
# ~/.bob/hooks/log-write.sh
cat >> ~/.bob/hooks/write-log.txt

启动 Bob 会话并使用匹配的工具。检查 ~/.bob/hooks/write-log.txt,确认 hook 已运行且 payload 已写入。

示例

记录所有 hook 输入

将每个 hook 的 stdin 写入文件用于调试:

#!/bin/sh
# 带时间戳追加收到的 JSON payload
echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> ~/.bob/hooks/debug.log
cat >> ~/.bob/hooks/debug.log
echo "" >> ~/.bob/hooks/debug.log

在任意 hook 下配置:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [{ "type": "command", "command": "sh ~/.bob/hooks/debug.sh" }]
      }
    ]
  }
}

注入会话上下文

SessionStart hook 返回文本,将其添加到模型上下文:

#!/bin/sh
# 输出项目元数据供模型使用
echo "Project: $(basename $PWD)"
echo "Git branch: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
echo "Node version: $(node --version 2>/dev/null || echo 'not installed')"

阻止 prompt

UserPromptSubmit hook 以 exit 代码 2 退出,阻止 prompt 被发送:

#!/bin/sh
# 阻止包含 "delete" 单词的 prompt
PROMPT=$(cat | python3 -c "import sys,json; print(json.load(sys.stdin)['prompt'])")
case "$PROMPT" in
  *delete*|*DELETE*)
    echo "Prompt blocked: contains 'delete'" >&2
    exit 2
    ;;
esac

阻止匹配的工具

PreToolUse hook 以 exit 代码 2 退出,阻止特定工具运行:

#!/bin/sh
# 阻止 src/ 目录以外的文件的 write_file 操作
PATH_VAL=$(cat | python3 -c "import sys,json; print(json.load(sys.stdin)['input'].get('path',''))")
case "$PATH_VAL" in
  src/*) ;;
  *)
    echo "Blocked: writes outside src/ are not allowed" >&2
    exit 2
    ;;
esac

从 Stop 运行后续自动化

使用 Stop 在会话结束后启动清理或报告:

#!/bin/sh
# Agent 完成后提交已暂存的变更
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob session"

当前限制

本版本仅支持 command hooks 和上述五种 hook 类型。以下功能尚未开放:

  • command 类型的 hook:不支持 function hooks、inline script hooks 等。
  • 定时 hooks:无法将 hook 设置为按计划或响应外部事件运行。
  • 输入改写:hook 无法在 prompt 或工具输入到达模型之前对其进行修改。
  • 沙盒运行:hook 以你的完整用户权限运行,不应用任何隔离。
  • 专用 hook 遥测:hook 活动不会在会话分析中单独追踪。
  • PostToolUseStop 阻塞:对这些 hooks,exit 代码 2 无效。
这个主题怎么样?