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.
Hooks verwalten
Führe /hooks aus, um einen Dialog zu öffnen, der alle konfigurierten globalen und Workspace-Hooks auflistet. Der Dialog zeigt für jeden Hook den Ereignistyp, den Matcher, den Geltungsbereich, den Status und den Befehl an. Du kannst einzelne Hooks ein- oder ausschalten. Die Liste wird automatisch aktualisiert, wenn sich die Hook-Einstellungen auf dem Datenträger ändern.
Um Hooks für alle Nutzer in deiner Organisation durchzusetzen, siehe EnforcedHooks.
Unterstützte hooks
| Hook | Wann er ausgeführt wird | Blockierend | Stdout-Verhalten |
|---|---|---|---|
SessionStart | Einmal beim Start einer Session | Nein | Als Kontext injiziert |
UserPromptSubmit | Jedes Mal, wenn du einen Prompt absendest | Ja (Exit 2) | Als Kontext injiziert |
PreToolUse | Vor dem Ausführen eines passenden Tools | Ja (Exit 2) | Ignoriert |
PostToolUse | Nach Abschluss eines passenden Tools | Nein | Ignoriert |
PreCompact | Bevor die Kontextkomprimierung beginnt | Ja (Exit 2) | Ignoriert |
PostCompact | Nach Abschluss der Kontextkomprimierung | Nein | Ignoriert |
Stop | Wenn der Agent stoppt | Nein | Ignoriert |
Konfiguration
Hooks werden unter dem Schlüssel hooks in deiner settings.json definiert. Bob Shell führt Hooks aus zwei Speicherorten zusammen:
| Geltungsbereich | Datei |
|---|---|
| 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.
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
| Feld | Typ | Standard | Beschreibung |
|---|---|---|---|
type | "command" | "https" | (kein) | Pflichtfeld. Der Handler-Typ. Verwende command, um einen lokalen Shell-Befehl auszuführen, oder https, um Ereignisse an einen HTTP-Endpunkt zu senden. |
command | string | (kein) | Pflichtfeld, wenn type gleich command ist. Der auszuführende Shell-Befehl. Läuft über sh -c auf macOS und Linux, cmd /c auf Windows. |
url | string | (kein) | Pflichtfeld, wenn type gleich https ist. Die HTTPS-URL, an die Hook-Ereignis-Payloads gesendet werden. |
matcher | string | (kein) | Optional. Ein Regex, der gegen den Tool-Namen abgeglichen wird (nur PreToolUse, PostToolUse). Weglassen, um alle Tools zu erfassen. |
timeout | number | 10 | Sekunden, 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
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"source": "startup | resume | compact"
}Beispiel-Payload
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "SessionStart",
"source": "startup"
}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
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"prompt": "string"
}Beispiel-Payload
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "UserPromptSubmit",
"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
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"tool_name": "string",
"tool_input": "object",
"tool_use_id": "string"
}Beispiel-Payload
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "PreToolUse",
"tool_name": "write_file",
"tool_input": {
"path": "src/index.ts",
"content": "..."
},
"tool_use_id": "toolu_01abc123"
}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
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"tool_name": "string",
"tool_input": "object",
"tool_response": "string",
"tool_use_id": "string"
}Beispiel-Payload
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "PostToolUse",
"tool_name": "write_file",
"tool_input": {
"path": "src/index.ts",
"content": "..."
},
"tool_response": "File written successfully",
"tool_use_id": "toolu_01abc123"
}Stdout: Ignoriert.
Blockierend: Exit-Code 2 hat keine Wirkung. Das Tool wurde bereits ausgeführt.
Wird ausgeführt, bevor die Kontextkomprimierung beginnt, und gibt dir die Möglichkeit, Bedingungen zu prüfen oder die Komprimierung zu blockieren.
Stdin-Schema
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"trigger": "manual | auto",
"custom_instructions": "string | null"
}Beispiel-Payload
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "PreCompact",
"trigger": "auto",
"custom_instructions": null
}Stdout: Ignoriert.
Blockierend: Exit-Code 2 blockiert die Komprimierung. Bob Shell meldet die Komprimierung als blockiert und setzt die Session fort.
Wird ausgeführt, nachdem die Kontextkomprimierung abgeschlossen ist.
Stdin-Schema
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"trigger": "manual | auto",
"compact_summary": "string"
}Beispiel-Payload
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "PostCompact",
"trigger": "auto",
"compact_summary": "..."
}Stdout: Ignoriert.
Blockierend: Exit-Code 2 hat keine Wirkung. Die Komprimierung wurde bereits abgeschlossen.
Wird ausgeführt, wenn der Agent stoppt, nachdem der letzte Durchgang abgeschlossen ist.
Stdin-Schema
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"last_assistant_message": "string | null"
}Beispiel-Payload
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "Stop",
"last_assistant_message": "Done. The auth module is refactored."
}Stdout: Ignoriert.
Blockierend: Exit-Code 2 hat keine Wirkung. Die Session ist bereits beendet.
Exit-Codes und Blockierung
| Exit-Code | Verhalten | Gilt für |
|---|---|---|
0 | Erfolg: Hook wurde ohne Problem ausgeführt | Alle Hooks |
2 | Blockieren: aktuelle Aktion stoppen | UserPromptSubmit, PreToolUse, PreCompact |
| Jeder andere Nicht-Null-Wert | Nicht-blockierender Fehler: protokolliert und ignoriert | Alle Hooks |
Nur UserPromptSubmit, PreToolUse und PreCompact unterstützen Blockierung. Exit-Code 2 von SessionStart, PostToolUse, PostCompact 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. Setzetimeoutauf0, 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 -cauf 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.txtStarte 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.logKonfiguriere 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
;;
esacEin 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)['tool_input'].get('path',''))")
case "$PATH_VAL" in
src/*) ;;
*)
echo "Blocked: writes outside src/ are not allowed" >&2
exit 2
;;
esacFolgeautomatisierung 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"Hook-Ereignisse an einen HTTPS-Endpunkt senden
Sende Ereignis-Payloads an einen externen Webservice oder ein Monitoring-Tool, indem du den Handler-type auf https setzt:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "https",
"url": "https://api.example.com/webhooks/bob-events",
"timeout": 10
}
]
}
]
}
}Aktuelle Einschränkungen
Folgendes ist noch nicht verfügbar:
- Andere Hook-Handler-Typen als
commandundhttps: 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 nicht-blockierenden Hooks: Exit-Code
2hat fürSessionStart,PostToolUse,PostCompactoderStopkeine Wirkung.