Lifecycle hooks

Ejecuta comandos de shell automáticamente en puntos clave de una sesión de Bob para registrar actividad, inyectar contexto o bloquear acciones según tu propia lógica.

Los lifecycle hooks te permiten ejecutar comandos de shell en puntos específicos de una sesión de Bob. Úsalos para registrar actividad, inyectar contexto en el modelo, permitir o bloquear acciones, o iniciar automatizaciones de seguimiento, todo sin modificar Bob.

Hooks disponibles

HookCuándo se ejecutaBloqueanteComportamiento de stdout
SessionStartUna vez al iniciar una sesiónNoInyectado como contexto
UserPromptSubmitCada vez que envías un promptSí (salida 2)Inyectado como contexto
PreToolUseAntes de ejecutar una herramienta coincidenteSí (salida 2)Ignorado
PostToolUseDespués de que una herramienta coincidente finalizaNoIgnorado
StopCuando el agente se detieneNoIgnorado

Configuración

Los hooks se definen bajo la clave hooks en tu settings.json. Bob combina hooks de dos ubicaciones:

ÁmbitoArchivo
Global (todos los workspaces)~/.bob/settings/settings.json
Workspace (proyecto actual).bob/settings.json

Los hooks globales siempre se ejecutan. Los hooks de workspace se combinan sobre los globales y solo aplican al proyecto actual.

Esquema del hook

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

Campos de configuración

CampoTipoPor defectoDescripción
type"command"(ninguno)Obligatorio. Solo se admite command.
commandstring(ninguno)Obligatorio. El comando de shell a ejecutar. Se ejecuta con sh -c en macOS/Linux y cmd /c en Windows.
matcherstring(ninguno)Opcional. Un regex que se compara con el nombre de la herramienta (solo PreToolUse, PostToolUse). Omítelo para coincidir con todas las herramientas.
timeoutnumber10Segundos antes de detener el hook. Establece 0 para desactivar el timeout.

Referencia de hooks

Se ejecuta una vez cuando comienza una nueva sesión, antes del primer turno.

Esquema de stdin

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

Payload de ejemplo

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

Stdout: Se escribe en el contexto del modelo como información adicional de sesión.

Bloqueante: El código de salida 2 no está soportado. La sesión siempre inicia. Otras salidas distintas de cero se registran y se ignoran.

Se ejecuta cada vez que envías un prompt, antes de enviarlo al modelo.

Esquema de stdin

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

Payload de ejemplo

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

Stdout: Se escribe en el contexto del modelo junto con el prompt.

Bloqueante: El código de salida 2 bloquea el envío del prompt. Bob muestra un error y el prompt no se envía.

Se ejecuta antes de que corra una herramienta coincidente, dándote la oportunidad de inspeccionar o bloquear la acción.

Esquema de stdin

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

Payload de ejemplo

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

Stdout: Ignorado.

Bloqueante: El código de salida 2 impide que la herramienta se ejecute. Bob reporta la herramienta como bloqueada y continúa la sesión.

Se ejecuta después de que una herramienta coincidente finaliza, independientemente de si tuvo éxito.

Esquema de stdin

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

Payload de ejemplo

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

Stdout: Ignorado.

Bloqueante: El código de salida 2 no tiene efecto. La herramienta ya se ejecutó.

Se ejecuta cuando el agente se detiene, tras completar el turno final.

Esquema de stdin

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

Payload de ejemplo

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

Stdout: Ignorado.

Bloqueante: El código de salida 2 no tiene efecto. La sesión ya ha finalizado.

Códigos de salida y bloqueo

Código de salidaComportamientoAplica a
0Éxito: el hook se ejecutó sin problemasTodos los hooks
2Bloquear: detener la acción actualUserPromptSubmit, PreToolUse
Cualquier otro valor distinto de ceroFallo no bloqueante: registrado e ignoradoTodos los hooks
Nota:

Solo UserPromptSubmit y PreToolUse admiten bloqueo. El código de salida 2 de SessionStart, PostToolUse o Stop se trata como un fallo no bloqueante.

Detalles del comando

  • Directorio de trabajo: Los comandos se ejecutan desde el directorio de trabajo de la tarea (la carpeta en la que Bob está trabajando).
  • Timeout por defecto: 10 segundos. Se puede sobreescribir por hook con el campo timeout. Establece timeout en 0 para desactivar el timeout por completo.
  • Stderr: Se escribe en los logs de Bob pero no afecta al resultado del hook.
  • Shell: Los comandos se ejecutan con sh -c en macOS y Linux, y cmd /c en Windows.

Primeros pasos

Abre o crea tu archivo de configuración global en ~/.bob/settings/settings.json.

Añade una clave hooks con el hook que quieras usar. El ejemplo siguiente ejecuta un script antes de cada llamada a write_file:

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

Crea el archivo de script. Este script mínimo registra el payload JSON entrante:

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

Inicia una sesión de Bob y usa la herramienta coincidente. Comprueba ~/.bob/hooks/write-log.txt para confirmar que el hook se ejecutó y el payload fue escrito.

Ejemplos

Registrar todas las entradas de hooks

Escribe el stdin de cada hook en un archivo para depuración:

#!/bin/sh
# Añadir el payload JSON entrante con un timestamp
echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> ~/.bob/hooks/debug.log
cat >> ~/.bob/hooks/debug.log
echo "" >> ~/.bob/hooks/debug.log

Configúralo bajo cualquier hook:

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

Inyectar contexto de sesión

Devuelve texto desde un hook SessionStart para añadirlo al contexto del modelo:

#!/bin/sh
# Mostrar metadatos del proyecto para que los use el modelo
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 un prompt

Sal con código 2 desde un hook UserPromptSubmit para evitar que un prompt sea enviado:

#!/bin/sh
# Bloquear prompts que contienen la palabra "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

Bloquear una herramienta coincidente

Sal con código 2 desde un hook PreToolUse para evitar que una herramienta específica se ejecute:

#!/bin/sh
# Bloquear operaciones write_file en archivos fuera del directorio 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

Ejecutar automatización de seguimiento desde Stop

Usa Stop para iniciar limpieza o reportes después de que termina una sesión:

#!/bin/sh
# Commitear los cambios staged después de que el agente termine
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob session"

Limitaciones actuales

En esta versión solo se admiten hooks de tipo command y los cinco tipos de hook listados anteriormente. Lo siguiente aún no está disponible:

  • Tipos de hook distintos de command: los function hooks, inline script hooks y similares no están soportados.
  • Hooks programados: los hooks no se pueden configurar para ejecutarse en un temporizador ni en respuesta a un evento externo.
  • Reescritura de entrada: los hooks no pueden modificar el prompt o la entrada de la herramienta antes de que llegue al modelo.
  • Ejecución en sandbox: los hooks se ejecutan con tus permisos de usuario completos; no se aplica ningún aislamiento.
  • Telemetría dedicada de hooks: la actividad de los hooks no se rastrea por separado en los analytics de la sesión.
  • Bloqueo desde PostToolUse o Stop: el código de salida 2 no tiene efecto para estos hooks.
¿Cómo es este tema?