Lifecycle hooks
Execute comandos de shell automaticamente em pontos chave de uma sessão Bob para registrar atividade, injetar contexto ou bloquear ações com base na sua própria lógica.
Os lifecycle hooks permitem executar comandos de shell em momentos específicos de uma sessão Bob. Use-os para registrar atividade, injetar contexto no modelo, permitir ou bloquear ações, ou iniciar automatizações de acompanhamento — tudo sem modificar o Bob.
Hooks disponíveis
| Hook | Quando executa | Bloqueante | Comportamento do stdout |
|---|---|---|---|
SessionStart | Uma vez ao iniciar uma sessão | Não | Injetado como contexto |
UserPromptSubmit | Cada vez que envias um prompt | Sim (exit 2) | Injetado como contexto |
PreToolUse | Antes de uma ferramenta correspondente ser executada | Sim (exit 2) | Ignorado |
PostToolUse | Após uma ferramenta correspondente ser concluída | Não | Ignorado |
Stop | Quando o agente para | Não | Ignorado |
Configuração
Os hooks são definidos sob a chave hooks no teu settings.json. O Bob combina hooks de dois locais:
| Âmbito | Ficheiro |
|---|---|
| Global (todos os workspaces) | ~/.bob/settings/settings.json |
| Workspace (projeto atual) | .bob/settings.json |
Os hooks globais executam sempre. Os hooks de workspace são combinados por cima dos globais e aplicam-se apenas ao projeto atual.
Esquema do hook
{
"hooks": {
"PreToolUse": [
{
"matcher": "^write_file$",
"hooks": [
{
"type": "command",
"command": "sh .bob/hooks/check.sh",
"timeout": 5
}
]
}
]
}
}Campos de configuração
| Campo | Tipo | Padrão | Descrição |
|---|---|---|---|
type | "command" | (nenhum) | Obrigatório. Apenas command é suportado. |
command | string | (nenhum) | Obrigatório. O comando shell a executar. Corre via sh -c em macOS/Linux, cmd /c no Windows. |
matcher | string | (nenhum) | Opcional. Um regex comparado com o nome da ferramenta (apenas PreToolUse, PostToolUse). Omite para corresponder a todas as ferramentas. |
timeout | number | 10 | Segundos antes de o hook ser interrompido. Define 0 para desativar o timeout. |
Referência de hooks
Executa uma vez quando uma nova sessão começa, antes do primeiro turno.
Esquema stdin
{
"event": "string",
"session_id": "string"
}Payload de exemplo
{
"event": "SessionStart",
"session_id": "ses_01abc123"
}Stdout: Escrito no contexto do modelo como informação adicional da sessão.
Bloqueante: O código de saída 2 não é suportado. A sessão inicia sempre. Outros códigos de saída não nulos são registados e ignorados.
Executa cada vez que envias um prompt, antes de ser enviado ao modelo.
Esquema stdin
{
"event": "string",
"session_id": "string",
"prompt": "string"
}Payload de exemplo
{
"event": "UserPromptSubmit",
"session_id": "ses_01abc123",
"prompt": "Refactor the auth module"
}Stdout: Escrito no contexto do modelo junto com o prompt.
Bloqueante: O código de saída 2 bloqueia o envio do prompt. O Bob mostra um erro e o prompt não é submetido.
Executa antes de uma ferramenta correspondente ser lançada, dando-te a oportunidade de inspecionar ou bloquear a ação.
Esquema stdin
{
"event": "string",
"session_id": "string",
"tool": "string",
"input": "object"
}Payload de exemplo
{
"event": "PreToolUse",
"session_id": "ses_01abc123",
"tool": "write_file",
"input": {
"path": "src/index.ts",
"content": "..."
}
}Stdout: Ignorado.
Bloqueante: O código de saída 2 impede a ferramenta de ser executada. O Bob reporta a ferramenta como bloqueada e continua a sessão.
Executa após uma ferramenta correspondente ser concluída, independentemente de ter tido sucesso.
Esquema stdin
{
"event": "string",
"session_id": "string",
"tool": "string",
"input": "object",
"output": "string"
}Payload de exemplo
{
"event": "PostToolUse",
"session_id": "ses_01abc123",
"tool": "write_file",
"input": {
"path": "src/index.ts",
"content": "..."
},
"output": "File written successfully"
}Stdout: Ignorado.
Bloqueante: O código de saída 2 não tem efeito. A ferramenta já foi executada.
Executa quando o agente para, após o turno final ser concluído.
Esquema stdin
{
"event": "string",
"session_id": "string"
}Payload de exemplo
{
"event": "Stop",
"session_id": "ses_01abc123"
}Stdout: Ignorado.
Bloqueante: O código de saída 2 não tem efeito. A sessão já terminou.
Códigos de saída e bloqueio
| Código de saída | Comportamento | Aplica-se a |
|---|---|---|
0 | Sucesso: hook executou sem problemas | Todos os hooks |
2 | Bloquear: parar a ação atual | UserPromptSubmit, PreToolUse |
| Qualquer outro não nulo | Falha não bloqueante: registada e ignorada | Todos os hooks |
Apenas UserPromptSubmit e PreToolUse suportam bloqueio. O código de saída 2 de SessionStart, PostToolUse ou Stop é tratado como falha não bloqueante.
Detalhes dos comandos
- Diretório de trabalho: Os comandos são executados a partir do diretório de trabalho da tarefa (a pasta onde o Bob está a trabalhar).
- Timeout padrão: 10 segundos. Pode ser substituído por hook com o campo
timeout. Definetimeoutcomo0para desativar o timeout completamente. - Stderr: Escrito nos logs do Bob mas não afeta o resultado do hook.
- Shell: Os comandos são executados via
sh -cem macOS e Linux, ecmd /cno Windows.
Introdução
Abre ou cria o teu ficheiro de configuração global em ~/.bob/settings/settings.json.
Adiciona uma chave hooks com o hook que queres usar. O exemplo abaixo executa um script antes de cada chamada a write_file:
{
"hooks": {
"PreToolUse": [
{
"matcher": "^write_file$",
"hooks": [
{
"type": "command",
"command": "sh ~/.bob/hooks/log-write.sh"
}
]
}
]
}
}Cria o ficheiro de script. Este script mínimo regista o payload JSON recebido:
#!/bin/sh
# ~/.bob/hooks/log-write.sh
cat >> ~/.bob/hooks/write-log.txtInicia uma sessão Bob e usa a ferramenta correspondente. Verifica ~/.bob/hooks/write-log.txt para confirmar que o hook executou e o payload foi escrito.
Exemplos
Registar todas as entradas de hooks
Escreve o stdin de cada hook para um ficheiro para depuração:
#!/bin/sh
# Acrescentar o payload JSON recebido com um timestamp
echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> ~/.bob/hooks/debug.log
cat >> ~/.bob/hooks/debug.log
echo "" >> ~/.bob/hooks/debug.logConfigura isto sob qualquer hook:
{
"hooks": {
"SessionStart": [
{
"hooks": [{ "type": "command", "command": "sh ~/.bob/hooks/debug.sh" }]
}
]
}
}Injetar contexto de sessão
Devolve texto de um hook SessionStart para o adicionar ao contexto do modelo:
#!/bin/sh
# Mostrar metadados do projeto para o modelo usar
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')"Bloquear um prompt
Sai com código 2 de um hook UserPromptSubmit para impedir o envio de um prompt:
#!/bin/sh
# Bloquear prompts que contenham a palavra "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
;;
esacBloquear uma ferramenta correspondente
Sai com código 2 de um hook PreToolUse para impedir a execução de uma ferramenta específica:
#!/bin/sh
# Bloquear operações write_file em ficheiros fora do diretório 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
;;
esacExecutar automatização de acompanhamento a partir do Stop
Usa Stop para iniciar limpeza ou relatórios após o fim de uma sessão:
#!/bin/sh
# Fazer commit das alterações em stage após o agente terminar
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob session"Limitações atuais
Nesta versão apenas são suportados hooks do tipo command e os cinco tipos de hooks listados acima. Os seguintes não estão ainda disponíveis:
- Tipos de hook distintos de
command: function hooks, inline script hooks e similares não são suportados. - Hooks agendados: os hooks não podem ser configurados para executar num temporizador ou em resposta a um evento externo.
- Reescrita de entrada: os hooks não podem modificar o prompt ou a entrada da ferramenta antes de chegar ao modelo.
- Execução em sandbox: os hooks executam com as tuas permissões de utilizador completas; não é aplicado qualquer isolamento.
- Telemetria dedicada de hooks: a atividade dos hooks não é monitorizada separadamente nas análises da sessão.
- Bloqueio a partir de
PostToolUseouStop: o código de saída2não tem efeito para estes hooks.