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 無效。
這個主題如何?