docs.theus.pe/docs/hooks theus.peInicio docs

Hooks

Los hooks son comandos definidos por ti que Theus ejecuta automáticamente en puntos concretos de su ciclo de vida: antes o después de usar una herramienta, al enviar un prompt, al iniciar o cerrar una sesión, y mucho más.

Qué son

Un hook asocia un evento (por ejemplo, "justo antes de ejecutar una herramienta") con una acción (ejecutar un comando de shell, evaluar un prompt, llamar a una URL o lanzar un subagente verificador). Cuando el evento ocurre, Theus lanza esas acciones, les entrega información del evento por stdin en formato JSON, y actúa según lo que devuelven.

Los usos típicos son: formatear código automáticamente después de cada escritura, bloquear comandos peligrosos antes de que se ejecuten, inyectar contexto adicional al enviar un prompt, o disparar notificaciones y auditorías.

Todos los hooks ejecutan comandos arbitrarios en tu máquina. Por seguridad, Theus solo ejecuta hooks en un espacio de trabajo de confianza (el diálogo de confianza debe haberse aceptado). Revisa siempre lo que configuras: un hook es código que corre con tus permisos.

El comando /hooks

Dentro de Theus, el comando slash /hooks abre un menú interactivo para revisar y gestionar la configuración de hooks por evento de herramienta, mostrando las herramientas disponibles en tu contexto actual. Es la vía recomendada para inspeccionar qué hooks están activos.

Dónde se configuran

Los hooks viven bajo la clave hooks de tu settings.json. Theus lee la configuración de varias fuentes y las combina por precedencia:

ArchivoÁmbito
~/.theus/settings.jsonUsuario (global, para todos tus proyectos)
.theus/settings.jsonProyecto (compartido, versionable en el repo)
.theus/settings.local.jsonProyecto, local (solo tú, no se versiona)
managed-settings.jsonGestionado por administrador (requiere permisos de admin)

Formato de configuración

La clave hooks es un objeto donde cada clave es el nombre del evento y cada valor es una lista de matchers. Cada matcher tiene un patrón opcional (matcher) y una lista de hooks a ejecutar:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "prettier --write \"$THEUS_PROJECT_DIR\""
          }
        ]
      }
    ]
  }
}

El matcher es un patrón de texto que se compara con el valor asociado al evento (para eventos de herramienta, el nombre de la herramienta, p. ej. Write o Bash). Si se omite, el matcher aplica a todos los casos del evento.

Tipos de hook

Cada entrada dentro de hooks se distingue por su campo type:

typeQué haceCampos clave
commandEjecuta un comando de shellcommand, shell, timeout, async
promptEvalúa un prompt con un modeloprompt, model, timeout
httpHace un POST del JSON del evento a una URLurl, headers, allowedEnvVars
agentLanza un subagente verificadorprompt, model, timeout

Campos comunes

  • if: filtra cuándo corre el hook usando sintaxis de reglas de permiso (p. ej. "Bash(git *)"). El hook solo se lanza si la llamada de herramienta coincide con el patrón; así evitas lanzar hooks para comandos que no aplican.
  • timeout: tiempo máximo en segundos para esa acción concreta.
  • statusMessage: mensaje personalizado a mostrar en el spinner mientras el hook corre.
  • once: si es true, el hook corre una sola vez y se elimina tras ejecutarse.
  • async (solo command): si es true, el hook corre en segundo plano sin bloquear. Con asyncRewake además despierta al modelo si termina con código de salida 2 (error bloqueante).

Eventos disponibles

Estos son los eventos que puedes usar como clave dentro de hooks:

EventoCuándo se dispara
PreToolUseAntes de ejecutar una herramienta. Puede aprobar, denegar o pedir permiso, y modificar la entrada.
PostToolUseDespués de que una herramienta se ejecuta con éxito.
PostToolUseFailureDespués de que una herramienta falla.
UserPromptSubmitAl enviar un prompt. Puede inyectar contexto adicional.
SessionStartAl iniciar la sesión. Puede añadir contexto o rutas a vigilar.
SessionEndAl cerrar o limpiar la sesión (con un tiempo de ejecución ajustado).
Stop / StopFailureCuando el asistente termina (o falla al terminar) su turno.
SubagentStart / SubagentStopAl iniciar o terminar un subagente.
PreCompact / PostCompactAntes y después de compactar la conversación.
NotificationAl emitirse una notificación.
PermissionRequest / PermissionDeniedAl solicitarse o denegarse un permiso.
SetupDurante la configuración inicial.
TaskCreated / TaskCompletedAl crearse o completarse una tarea.
Elicitation / ElicitationResultEn flujos de solicitud de datos al usuario.
ConfigChangeAl cambiar la configuración.
WorktreeCreate / WorktreeRemoveAl crear o eliminar un worktree de git.
InstructionsLoadedAl cargarse las instrucciones del proyecto.
CwdChangedAl cambiar el directorio de trabajo.
FileChangedAl cambiar un archivo vigilado.
TeammateIdleCuando un compañero de equipo queda inactivo.

Datos que recibe el hook

Cada hook recibe por stdin un JSON con la información del evento. Todos los eventos incluyen campos base:

  • session_id: identificador de la sesión.
  • transcript_path: ruta al transcript de la conversación.
  • cwd: directorio de trabajo actual.
  • hook_event_name: nombre del evento (p. ej. PreToolUse).
  • permission_mode, agent_id, agent_type: presentes según el contexto (por ejemplo, cuando el hook se dispara dentro de un subagente).

Los eventos de herramienta añaden además tool_name, tool_input y tool_use_id; PostToolUse incorpora también tool_response.

Variables de entorno

Theus expone variables útiles al proceso del hook:

  • THEUS_PROJECT_DIR: raíz estable del proyecto (no la ruta del worktree), para que las rutas relativas resuelvan siempre contra el repositorio real.
  • THEUS_ENV_FILE: ruta a un archivo .sh donde el hook puede escribir variables de entorno que se aplicarán a la sesión.

Cómo responde un hook

Un hook puede simplemente terminar (su código de salida y su stdout se registran), o devolver por stdout un JSON para controlar el flujo. Campos habituales:

  • continue: si es false, Theus no continúa; usa stopReason para el mensaje.
  • suppressOutput: oculta el stdout del transcript.
  • decision: approve o block, con reason como explicación.
  • systemMessage: mensaje de aviso que se muestra al usuario.
  • hookSpecificOutput: salida específica del evento. Por ejemplo, en PreToolUse permite permissionDecision (allow/deny/ask) y updatedInput; en UserPromptSubmit y SessionStart, additionalContext.

Un hook también puede responder { "async": true } (con asyncTimeout opcional) para ejecutarse en segundo plano.

Ejemplos

Formatear tras cada escritura

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          { "type": "command", "command": "prettier --write \"$THEUS_PROJECT_DIR\"" }
        ]
      }
    ]
  }
}

Bloquear un comando peligroso antes de ejecutarlo

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(rm -rf *)",
            "command": "echo '{\"decision\":\"block\",\"reason\":\"Comando destructivo bloqueado por política.\"}'"
          }
        ]
      }
    ]
  }
}

Inyectar contexto al enviar un prompt

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          { "type": "command", "command": "git-context.sh" }
        ]
      }
    ]
  }
}

Si el comando imprime { "hookSpecificOutput": { "hookEventName": "UserPromptSubmit", "additionalContext": "..." } }, ese texto se añade al contexto del turno.

Verificador con subagente

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "Verifica que las pruebas unitarias se ejecutaron y pasaron."
          }
        ]
      }
    ]
  }
}

Controles de seguridad

Además de requerir un espacio de trabajo de confianza, la configuración admite ajustes de seguridad relevantes:

  • Deshabilitar por completo la ejecución de hooks (y de la status line).
  • Ejecutar únicamente los hooks definidos en la configuración gestionada por el administrador, ignorando los de usuario, proyecto y local.
  • Para hooks de tipo http, restringir a qué URLs pueden apuntar mediante una allowlist con comodines (p. ej. https://hooks.example.com/*) y qué variables de entorno pueden interpolarse en las cabeceras.

Empieza siempre por /hooks para revisar tu configuración activa antes de editar settings.json a mano. Usa if para acotar cuándo corre cada hook y evita sobrecargar cada ejecución de herramienta.

Theus — agente de código local-first y multimodelo · Hecho en Perú