Lifecycle hooks

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

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

支持的 hooks

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

配置

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

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

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

重要:

Workspace hooks 仅在受信任的文件夹中运行。如果当前文件夹不受信任,.bob/settings.json 文件不会被加载,workspace hooks 会被静默跳过。~/.bob/settings/settings.json 中的全局 hooks 不受文件夹信任设置的影响。

有关设置文件如何定位和加载的详细信息,请参阅配置 Bob Shell

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 运行。
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 Shell 显示错误且 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 Shell 将该工具报告为已阻止并继续会话。

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

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 Shell 的日志,但不影响 hook 结果。
  • Shell:命令在 macOS 和 Linux 上通过 sh -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 Shell 会话并使用匹配的工具。检查 ~/.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 Shell session"

当前限制

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

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