Lifecycle hooks

Führe Shell-Befehle automatisch an wichtigen Punkten einer Bob Shell-Session aus, um Aktivitäten zu protokollieren, Kontext bereitzustellen oder Aktionen basierend auf deiner eigenen Logik zu blockieren.

Lifecycle hooks ermöglichen es dir, Shell-Befehle an bestimmten Punkten einer Bob Shell-Session auszuführen. Nutze sie, um Aktivitäten zu protokollieren, Kontext in das Modell zu injizieren, Aktionen zu erlauben oder zu blockieren oder Folgeautomatisierungen zu starten – alles ohne Bob Shell selbst zu verändern.

Unterstützte hooks

HookWann er ausgeführt wirdBlockierendStdout-Verhalten
SessionStartEinmal beim Start einer SessionNeinAls Kontext injiziert
UserPromptSubmitJedes Mal, wenn du einen Prompt absendestJa (Exit 2)Als Kontext injiziert
PreToolUseVor dem Ausführen eines passenden ToolsJa (Exit 2)Ignoriert
PostToolUseNach Abschluss eines passenden ToolsNeinIgnoriert
StopWenn der Agent stopptNeinIgnoriert

Konfiguration

Hooks werden unter dem Schlüssel hooks in deiner settings.json definiert. Bob Shell führt Hooks aus zwei Speicherorten zusammen:

GeltungsbereichDatei
Global (alle Workspaces)~/.bob/settings/settings.json
Workspace (aktuelles Projekt).bob/settings.json

Globale Hooks werden immer ausgeführt. Workspace-Hooks werden über die globalen Hooks gelegt und gelten nur für das aktuelle Projekt.

Wichtig:

Workspace-Hooks werden nur in vertrauenswürdigen Ordnern ausgeführt. Wenn der aktuelle Ordner nicht vertrauenswürdig ist, wird die .bob/settings.json nicht geladen und Workspace-Hooks werden stillschweigend übersprungen. Globale Hooks in ~/.bob/settings/settings.json sind von der Ordner-Vertrauensstellung nicht betroffen.

Weitere Informationen zum Speicherort und Laden von Einstellungsdateien findest du unter Bob Shell konfigurieren.

Hook-Schema

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

Konfigurationsfelder

FeldTypStandardBeschreibung
type"command"(kein)Pflichtfeld. Nur command wird unterstützt.
commandstring(kein)Pflichtfeld. Der auszuführende Shell-Befehl. Läuft über sh -c auf macOS/Linux.
matcherstring(kein)Optional. Ein Regex, der gegen den Tool-Namen abgeglichen wird (nur PreToolUse, PostToolUse). Weglassen, um alle Tools zu erfassen.
timeoutnumber10Sekunden, bevor der Hook abgebrochen wird. Auf 0 setzen, um den Timeout zu deaktivieren.

Hook-Referenz

Wird einmal ausgeführt, wenn eine neue Session beginnt, vor dem ersten Durchgang.

Stdin-Schema

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

Beispiel-Payload

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

Stdout: Wird als zusätzliche Session-Information in den Kontext des Modells geschrieben.

Blockierend: Exit-Code 2 wird nicht unterstützt. Die Session startet immer. Andere Nicht-Null-Exits werden protokolliert und ignoriert.

Wird jedes Mal ausgeführt, wenn du einen Prompt absendest, bevor er an das Modell gesendet wird.

Stdin-Schema

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

Beispiel-Payload

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

Stdout: Wird zusammen mit dem Prompt in den Kontext des Modells geschrieben.

Blockierend: Exit-Code 2 verhindert, dass der Prompt gesendet wird. Bob Shell zeigt einen Fehler an und der Prompt wird nicht übermittelt.

Wird ausgeführt, bevor ein passendes Tool läuft, und gibt dir die Möglichkeit, die Aktion zu prüfen oder zu blockieren.

Stdin-Schema

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

Beispiel-Payload

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

Stdout: Ignoriert.

Blockierend: Exit-Code 2 verhindert die Ausführung des Tools. Bob Shell meldet das Tool als blockiert und setzt die Session fort.

Wird ausgeführt, nachdem ein passendes Tool abgeschlossen hat, unabhängig davon, ob es erfolgreich war.

Stdin-Schema

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

Beispiel-Payload

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

Stdout: Ignoriert.

Blockierend: Exit-Code 2 hat keine Wirkung. Das Tool wurde bereits ausgeführt.

Wird ausgeführt, wenn der Agent stoppt, nachdem der letzte Durchgang abgeschlossen ist.

Stdin-Schema

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

Beispiel-Payload

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

Stdout: Ignoriert.

Blockierend: Exit-Code 2 hat keine Wirkung. Die Session ist bereits beendet.

Exit-Codes und Blockierung

Exit-CodeVerhaltenGilt für
0Erfolg: Hook wurde ohne Problem ausgeführtAlle Hooks
2Blockieren: aktuelle Aktion stoppenUserPromptSubmit, PreToolUse
Jeder andere Nicht-Null-WertNicht-blockierender Fehler: protokolliert und ignoriertAlle Hooks
Hinweis:

Nur UserPromptSubmit und PreToolUse unterstützen Blockierung. Exit-Code 2 von SessionStart, PostToolUse oder Stop wird als nicht-blockierender Fehler behandelt.

Befehlsdetails

  • Arbeitsverzeichnis: Befehle werden aus dem Task-Arbeitsverzeichnis heraus ausgeführt (dem Ordner, in dem Bob arbeitet).
  • Standard-Timeout: 10 Sekunden. Pro Hook mit dem Feld timeout überschreibbar. Setze timeout auf 0, um den Timeout vollständig zu deaktivieren.
  • Stderr: Wird in Bob Shells Logs geschrieben, hat aber keinen Einfluss auf das Hook-Ergebnis.
  • Shell: Befehle werden über sh -c auf macOS und Linux ausgeführt.

Erste Schritte

Öffne oder erstelle deine globale Einstellungsdatei unter ~/.bob/settings/settings.json.

Füge einen hooks-Schlüssel mit dem gewünschten Hook hinzu. Das folgende Beispiel führt ein Skript vor jedem write_file-Aufruf aus:

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

Erstelle die Skript-Datei. Dieses minimale Skript protokolliert den eingehenden JSON-Payload:

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

Starte eine Bob Shell-Session und nutze das passende Tool. Prüfe ~/.bob/hooks/write-log.txt, um zu bestätigen, dass der Hook ausgeführt wurde und der Payload geschrieben wurde.

Beispiele

Alle Hook-Eingaben protokollieren

Schreibe den Stdin jedes Hooks zur Fehlersuche in eine Datei:

#!/bin/sh
# Eingehenden JSON-Payload mit Zeitstempel anfügen
echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> ~/.bob/hooks/debug.log
cat >> ~/.bob/hooks/debug.log
echo "" >> ~/.bob/hooks/debug.log

Konfiguriere dies unter einem beliebigen Hook:

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

Session-Kontext injizieren

Gib Text aus einem SessionStart-Hook zurück, um ihn zum Kontext des Modells hinzuzufügen:

#!/bin/sh
# Projekt-Metadaten für das Modell ausgeben
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')"

Einen Prompt blockieren

Beende mit Exit-Code 2 aus einem UserPromptSubmit-Hook, um zu verhindern, dass ein Prompt gesendet wird:

#!/bin/sh
# Prompts blockieren, die das Wort "delete" enthalten
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

Ein passendes Tool blockieren

Beende mit Exit-Code 2 aus einem PreToolUse-Hook, um ein bestimmtes Tool an der Ausführung zu hindern:

#!/bin/sh
# write_file-Operationen auf Dateien außerhalb des src/-Verzeichnisses blockieren
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

Folgeautomatisierung mit Stop ausführen

Nutze Stop, um nach dem Ende einer Session Bereinigung oder Reporting zu starten:

#!/bin/sh
# Gestaggte Änderungen nach Abschluss des Agents committen
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob Shell session"

Aktuelle Einschränkungen

In diesem Release werden nur command-Hooks und die fünf oben aufgeführten Hook-Typen unterstützt. Folgendes ist noch nicht verfügbar:

  • Andere Hook-Typen als command: Funktions-Hooks, Inline-Skript-Hooks und ähnliche werden nicht unterstützt.
  • Geplante Hooks: Hooks können nicht auf einen Timer oder als Reaktion auf ein externes Ereignis gesetzt werden.
  • Eingabe-Rewriting: Hooks können den Prompt oder die Tool-Eingabe nicht ändern, bevor sie das Modell erreichen.
  • Isolierte Ausführung: Hooks laufen mit deinen vollen Benutzerberechtigungen; keine Isolierung wird angewendet.
  • Dedizierte Hook-Telemetrie: Hook-Aktivität wird in der Session-Analyse nicht separat erfasst.
  • Blockierung von PostToolUse oder Stop: Exit-Code 2 hat für diese Hooks keine Wirkung.
Wie ist dieses Thema?