Lifecycle hooks

Uruchamiaj polecenia shell automatycznie w kluczowych momentach sesji Bob, aby rejestrować aktywność, wstrzykiwać kontekst lub blokować działania na podstawie własnej logiki.

Lifecycle hooks pozwalają uruchamiać polecenia shell w określonych momentach sesji Bob. Użyj ich do rejestrowania aktywności, wstrzykiwania kontekstu do modelu, zezwalania lub blokowania działań albo uruchamiania automatyzacji — bez modyfikowania Bob.

Obsługiwane hooks

HookKiedy się wykonujeBlokującyZachowanie stdout
SessionStartRaz przy starcie sesjiNieWstrzykiwany jako kontekst
UserPromptSubmitZa każdym razem, gdy wysyłasz promptTak (exit 2)Wstrzykiwany jako kontekst
PreToolUsePrzed uruchomieniem pasującego narzędziaTak (exit 2)Ignorowany
PostToolUsePo zakończeniu pasującego narzędziaNieIgnorowany
StopGdy agent się zatrzymujeNieIgnorowany

Konfiguracja

Hooks są definiowane pod kluczem hooks w pliku settings.json. Bob łączy hooks z dwóch lokalizacji:

ZakresPlik
Globalny (wszystkie workspace)~/.bob/settings/settings.json
Workspace (bieżący projekt).bob/settings.json

Globalne hooks zawsze się wykonują. Workspace hooks są nakładane na globalne i obowiązują tylko dla bieżącego projektu.

Schemat hook

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

Pola konfiguracji

PoleTypDomyślnieOpis
type"command"(brak)Wymagane. Obsługiwany jest tylko typ command.
commandstring(brak)Wymagane. Polecenie shell do wykonania. Uruchamiane przez sh -c na macOS/Linux, cmd /c na Windows.
matcherstring(brak)Opcjonalne. Regex dopasowywany do nazwy narzędzia (tylko PreToolUse, PostToolUse). Pomiń, aby dopasować wszystkie narzędzia.
timeoutnumber10Sekundy przed zatrzymaniem hook. Ustaw 0, aby wyłączyć timeout.

Referencja hooków

Wykonuje się raz przy starcie nowej sesji, przed pierwszą turą.

Schemat stdin

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

Przykładowy payload

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

Stdout: Zapisywany do kontekstu modelu jako dodatkowe informacje o sesji.

Blokujący: Kod wyjścia 2 nie jest obsługiwany. Sesja zawsze się uruchamia. Inne kody niezerowe są logowane i ignorowane.

Wykonuje się za każdym razem, gdy wysyłasz prompt, zanim zostanie przesłany do modelu.

Schemat stdin

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

Przykładowy payload

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

Stdout: Zapisywany do kontekstu modelu razem z promptem.

Blokujący: Kod wyjścia 2 blokuje wysłanie promptu. Bob wyświetla błąd i prompt nie jest przesyłany.

Wykonuje się przed uruchomieniem pasującego narzędzia, dając możliwość inspekcji lub zablokowania działania.

Schemat stdin

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

Przykładowy payload

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

Stdout: Ignorowany.

Blokujący: Kod wyjścia 2 uniemożliwia uruchomienie narzędzia. Bob zgłasza narzędzie jako zablokowane i kontynuuje sesję.

Wykonuje się po zakończeniu pasującego narzędzia, niezależnie od tego, czy się powiodło.

Schemat stdin

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

Przykładowy payload

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

Stdout: Ignorowany.

Blokujący: Kod wyjścia 2 nie ma efektu. Narzędzie zostało już uruchomione.

Wykonuje się gdy agent się zatrzymuje, po zakończeniu ostatniej tury.

Schemat stdin

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

Przykładowy payload

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

Stdout: Ignorowany.

Blokujący: Kod wyjścia 2 nie ma efektu. Sesja już się zakończyła.

Kody wyjścia i blokowanie

Kod wyjściaZachowanieDotyczy
0Sukces: hook wykonał się bez problemuWszystkie hooks
2Blokada: zatrzymaj bieżące działanieUserPromptSubmit, PreToolUse
Dowolny inny niezerowyNieblokujące niepowodzenie: logowane i ignorowaneWszystkie hooks
Uwaga:

Blokowanie obsługują tylko UserPromptSubmit i PreToolUse. Kod wyjścia 2 z SessionStart, PostToolUse lub Stop jest traktowany jako nieblokujące niepowodzenie.

Szczegóły poleceń

  • Katalog roboczy: Polecenia są wykonywane z katalogu roboczego zadania (folderu, w którym pracuje Bob).
  • Domyślny timeout: 10 sekund. Można go nadpisać dla każdego hook za pomocą pola timeout. Ustaw timeout na 0, aby całkowicie wyłączyć timeout.
  • Stderr: Zapisywany do logów Bob, ale nie wpływa na wynik hook.
  • Shell: Polecenia są uruchamiane przez sh -c na macOS i Linux oraz cmd /c na Windows.

Pierwsze kroki

Otwórz lub utwórz globalny plik ustawień pod ścieżką ~/.bob/settings/settings.json.

Dodaj klucz hooks z hookiem, którego chcesz użyć. Poniższy przykład uruchamia skrypt przed każdym wywołaniem write_file:

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

Utwórz plik skryptu. Ten minimalny skrypt loguje przychodzący payload JSON:

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

Uruchom sesję Bob i użyj pasującego narzędzia. Sprawdź ~/.bob/hooks/write-log.txt, aby potwierdzić, że hook się wykonał i payload został zapisany.

Przykłady

Logowanie wszystkich danych wejściowych hooków

Zapisuj stdin każdego hooka do pliku w celach debugowania:

#!/bin/sh
# Dołącz przychodzący payload JSON ze znacznikiem czasu
echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> ~/.bob/hooks/debug.log
cat >> ~/.bob/hooks/debug.log
echo "" >> ~/.bob/hooks/debug.log

Skonfiguruj to pod dowolnym hookiem:

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

Wstrzykiwanie kontekstu sesji

Zwróć tekst z hooka SessionStart, aby dodać go do kontekstu modelu:

#!/bin/sh
# Wyświetl metadane projektu dla modelu
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')"

Blokowanie promptu

Zakończ z kodem 2 z hooka UserPromptSubmit, aby uniemożliwić wysłanie promptu:

#!/bin/sh
# Blokuj prompty zawierające słowo "delete"
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

Blokowanie pasującego narzędzia

Zakończ z kodem 2 z hooka PreToolUse, aby uniemożliwić uruchomienie konkretnego narzędzia:

#!/bin/sh
# Blokuj operacje write_file na plikach poza katalogiem src/
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

Uruchamianie automatyzacji po zatrzymaniu agenta

Użyj Stop, aby uruchomić czyszczenie lub raportowanie po zakończeniu sesji:

#!/bin/sh
# Zatwierdź zmiany w stage po zakończeniu agenta
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob session"

Aktualne ograniczenia

W tej wersji obsługiwane są tylko hooki typu command oraz pięć wymienionych typów hooków. Następujące funkcje nie są jeszcze dostępne:

  • Typy hooków inne niż command: function hooks, inline script hooks i podobne nie są obsługiwane.
  • Zaplanowane hooki: hooków nie można ustawiać do uruchamiania według timera ani w odpowiedzi na zdarzenie zewnętrzne.
  • Przepisywanie danych wejściowych: hooki nie mogą modyfikować promptu ani danych wejściowych narzędzia przed dotarciem do modelu.
  • Uruchamianie w piaskownicy: hooki są wykonywane z pełnymi uprawnieniami użytkownika; izolacja nie jest stosowana.
  • Dedykowana telemetria hooków: aktywność hooków nie jest śledzona oddzielnie w analityce sesji.
  • Blokowanie z PostToolUse lub Stop: kod wyjścia 2 nie ma efektu dla tych hooków.
Jak oceniasz ten temat?