Lifecycle hooks
Exécute des commandes shell automatiquement à des moments clés d'une session Bob Shell pour journaliser l'activité, injecter du contexte ou bloquer des actions selon ta propre logique.
Les lifecycle hooks te permettent d'exécuter des commandes shell à des moments précis d'une session Bob Shell. Utilise-les pour journaliser l'activité, injecter du contexte dans le modèle, autoriser ou bloquer des actions, ou déclencher des automatisations de suivi — sans modifier Bob Shell.
Gérer les hooks
Exécute /hooks pour ouvrir un dialogue listant tous les hooks globaux et de workspace configurés. Le dialogue affiche le type d'événement, le matcher, la portée, le statut et la commande de chaque hook. Tu peux activer ou désactiver des hooks individuels. La liste se rafraîchit automatiquement lorsque les paramètres des hooks changent sur le disque.
Pour appliquer des hooks à tous les utilisateurs de ton organisation, consulte EnforcedHooks.
Hooks disponibles
| Hook | Quand il s'exécute | Bloquant | Comportement de stdout |
|---|---|---|---|
SessionStart | Une fois au démarrage d'une session | Non | Injecté comme contexte |
UserPromptSubmit | À chaque envoi d'un prompt | Oui (exit 2) | Injecté comme contexte |
PreToolUse | Avant l'exécution d'un outil correspondant | Oui (exit 2) | Ignoré |
PostToolUse | Après la fin d'un outil correspondant | Non | Ignoré |
PreCompact | Avant le début de la compaction du contexte | Oui (exit 2) | Ignoré |
PostCompact | Après la fin de la compaction du contexte | Non | Ignoré |
Stop | Quand l'agent s'arrête | Non | Ignoré |
Configuration
Les hooks sont définis sous la clé hooks dans ton settings.json. Bob Shell fusionne les hooks de deux emplacements :
| Portée | Fichier |
|---|---|
| Global (tous les workspaces) | ~/.bob/settings/settings.json |
| Workspace (projet actuel) | .bob/settings.json |
Les hooks globaux s'exécutent toujours. Les hooks de workspace sont fusionnés par-dessus les hooks globaux et s'appliquent uniquement au projet actuel.
Les hooks de workspace ne s'exécutent que dans les dossiers de confiance. Si le dossier actuel n'est pas de confiance, le fichier .bob/settings.json n'est pas chargé et les hooks de workspace sont silencieusement ignorés. Les hooks globaux dans ~/.bob/settings/settings.json ne sont pas affectés par la confiance des dossiers.
Pour plus de détails sur la localisation et le chargement des fichiers de configuration, consulte Configurer Bob Shell.
Schéma du hook
{
"hooks": {
"PreToolUse": [
{
"matcher": "^write_file$",
"hooks": [
{
"type": "command",
"command": "sh .bob/hooks/check.sh",
"timeout": 5
}
]
}
]
}
}Champs de configuration
| Champ | Type | Par défaut | Description |
|---|---|---|---|
type | "command" | "https" | (aucun) | Obligatoire. Le type de gestionnaire. Utilise command pour exécuter une commande shell locale ou https pour envoyer des événements à un endpoint HTTP. |
command | string | (aucun) | Obligatoire quand type est command. La commande shell à exécuter. Lancée via sh -c sur macOS et Linux, cmd /c sur Windows. |
url | string | (aucun) | Obligatoire quand type est https. L'URL HTTPS vers laquelle envoyer les payloads d'événements de hook. |
matcher | string | (aucun) | Optionnel. Un regex comparé au nom de l'outil (uniquement PreToolUse, PostToolUse). Omets-le pour correspondre à tous les outils. |
timeout | number | 10 | Secondes avant l'arrêt du hook. Mets 0 pour désactiver le timeout. |
Référence des hooks
S'exécute une fois au démarrage d'une nouvelle session, avant le premier tour.
Schéma stdin
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"source": "startup | resume | compact"
}Payload d'exemple
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "SessionStart",
"source": "startup"
}Stdout : Écrit dans le contexte du modèle comme information de session supplémentaire.
Bloquant : Le code de sortie 2 n'est pas pris en charge. La session démarre toujours. Les autres sorties non nulles sont journalisées et ignorées.
S'exécute à chaque envoi d'un prompt, avant qu'il soit transmis au modèle.
Schéma stdin
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"prompt": "string"
}Payload d'exemple
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "UserPromptSubmit",
"prompt": "Refactor the auth module"
}Stdout : Écrit dans le contexte du modèle avec le prompt.
Bloquant : Le code de sortie 2 empêche l'envoi du prompt. Bob Shell affiche une erreur et le prompt n'est pas soumis.
S'exécute avant qu'un outil correspondant ne soit lancé, te donnant la possibilité d'inspecter ou de bloquer l'action.
Schéma stdin
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"tool_name": "string",
"tool_input": "object",
"tool_use_id": "string"
}Payload d'exemple
{
"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 : Ignoré.
Bloquant : Le code de sortie 2 empêche l'outil de s'exécuter. Bob Shell signale l'outil comme bloqué et continue la session.
S'exécute après la fin d'un outil correspondant, qu'il ait réussi ou non.
Schéma stdin
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"tool_name": "string",
"tool_input": "object",
"tool_response": "string",
"tool_use_id": "string"
}Payload d'exemple
{
"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 : Ignoré.
Bloquant : Le code de sortie 2 n'a aucun effet. L'outil a déjà été exécuté.
S'exécute avant le début de la compaction du contexte, te donnant la possibilité d'inspecter les conditions ou de bloquer la compaction.
Schéma stdin
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"trigger": "manual | auto",
"custom_instructions": "string | null"
}Payload d'exemple
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "PreCompact",
"trigger": "auto",
"custom_instructions": null
}Stdout : Ignoré.
Bloquant : Le code de sortie 2 empêche la compaction de se poursuivre. Bob Shell signale la compaction comme bloquée et continue la session.
S'exécute après la fin de la compaction du contexte.
Schéma stdin
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"trigger": "manual | auto",
"compact_summary": "string"
}Payload d'exemple
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "PostCompact",
"trigger": "auto",
"compact_summary": "..."
}Stdout : Ignoré.
Bloquant : Le code de sortie 2 n'a aucun effet. La compaction est déjà terminée.
S'exécute quand l'agent s'arrête, après la fin du dernier tour.
Schéma stdin
{
"session_id": "string",
"cwd": "string",
"hook_event_name": "string",
"last_assistant_message": "string | null"
}Payload d'exemple
{
"session_id": "3f2a9c1e8b7d4f6a0e5c2b1d9a8f7e6c",
"cwd": "/path/to/project",
"hook_event_name": "Stop",
"last_assistant_message": "Done. The auth module is refactored."
}Stdout : Ignoré.
Bloquant : Le code de sortie 2 n'a aucun effet. La session est déjà terminée.
Codes de sortie et blocage
| Code de sortie | Comportement | S'applique à |
|---|---|---|
0 | Succès : le hook s'est exécuté sans problème | Tous les hooks |
2 | Bloquer : arrêter l'action en cours | UserPromptSubmit, PreToolUse, PreCompact |
| Tout autre non-zéro | Échec non bloquant : journalisé et ignoré | Tous les hooks |
Seuls UserPromptSubmit, PreToolUse et PreCompact prennent en charge le blocage. Le code de sortie 2 de SessionStart, PostToolUse, PostCompact ou Stop est traité comme un échec non bloquant.
Détails des commandes
- Répertoire de travail : Les commandes s'exécutent depuis le répertoire de travail de la tâche (le dossier dans lequel Bob travaille).
- Timeout par défaut : 10 secondes. Peut être remplacé par hook avec le champ
timeout. Metstimeoutà0pour désactiver complètement le timeout. - Stderr : Écrit dans les logs de Bob Shell mais n'affecte pas le résultat du hook.
- Shell : Les commandes s'exécutent via
sh -csur macOS et Linux.
Démarrage rapide
Ouvre ou crée ton fichier de configuration global à ~/.bob/settings/settings.json.
Ajoute une clé hooks avec le hook que tu veux utiliser. L'exemple ci-dessous exécute un script avant chaque appel à write_file :
{
"hooks": {
"PreToolUse": [
{
"matcher": "^write_file$",
"hooks": [
{
"type": "command",
"command": "sh ~/.bob/hooks/log-write.sh"
}
]
}
]
}
}Crée le fichier de script. Ce script minimal journalise le payload JSON entrant :
#!/bin/sh
# ~/.bob/hooks/log-write.sh
cat >> ~/.bob/hooks/write-log.txtLance une session Bob Shell et utilise l'outil correspondant. Vérifie ~/.bob/hooks/write-log.txt pour confirmer que le hook s'est exécuté et que le payload a été écrit.
Exemples
Journaliser toutes les entrées de hooks
Écris le stdin de chaque hook dans un fichier pour le débogage :
#!/bin/sh
# Ajouter le payload JSON entrant avec un timestamp
echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> ~/.bob/hooks/debug.log
cat >> ~/.bob/hooks/debug.log
echo "" >> ~/.bob/hooks/debug.logConfigure cela sous n'importe quel hook :
{
"hooks": {
"SessionStart": [
{
"hooks": [{ "type": "command", "command": "sh ~/.bob/hooks/debug.sh" }]
}
]
}
}Injecter du contexte de session
Retourne du texte depuis un hook SessionStart pour l'ajouter au contexte du modèle :
#!/bin/sh
# Afficher les métadonnées du projet pour le modèle
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')"Bloquer un prompt
Sors avec le code 2 depuis un hook UserPromptSubmit pour empêcher l'envoi d'un prompt :
#!/bin/sh
# Bloquer les prompts contenant le mot "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
;;
esacBloquer un outil correspondant
Sors avec le code 2 depuis un hook PreToolUse pour empêcher un outil spécifique de s'exécuter :
#!/bin/sh
# Bloquer les opérations write_file sur des fichiers hors du répertoire src/
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
;;
esacLancer une automatisation de suivi depuis Stop
Utilise Stop pour démarrer un nettoyage ou un reporting après la fin d'une session :
#!/bin/sh
# Committer les changements staged après la fin de l'agent
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob Shell session"Envoyer des événements de hooks vers un endpoint HTTPS
Envoie les payloads d'événements à un service web externe ou un outil de monitoring en définissant le type du gestionnaire sur https :
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "https",
"url": "https://api.example.com/webhooks/bob-events",
"timeout": 10
}
]
}
]
}
}Limitations actuelles
Les capacités suivantes ne sont pas encore disponibles :
- Types de gestionnaires de hooks autres que
commandethttps: les function hooks, inline script hooks et similaires ne sont pas pris en charge. - Hooks planifiés : les hooks ne peuvent pas être configurés pour s'exécuter selon un timer ou en réponse à un événement externe.
- Réécriture d'entrée : les hooks ne peuvent pas modifier le prompt ou l'entrée de l'outil avant qu'il n'atteigne le modèle.
- Exécution en sandbox : les hooks s'exécutent avec tes pleines permissions utilisateur ; aucune isolation n'est appliquée.
- Télémétrie dédiée des hooks : l'activité des hooks n'est pas suivie séparément dans les analytics de session.
- Blocage depuis les hooks non bloquants : le code de sortie
2n'a aucun effet pourSessionStart,PostToolUse,PostCompactouStop.