"Quiero formateo automático después de cada edición." "Que nada reescriba jamás .env ni package-lock.json." "Detener los comandos peligrosos rm -rf." La forma de hacer reales estas reglas de "esto siempre debe ocurrir" —sin depender de los caprichos de la IA— son los hooks de Claude Code. Un hook es un comando de shell que se ejecuta automáticamente en puntos concretos del ciclo de vida de Claude Code, y los hooks también son una pieza fundamental de los plugins.

Este artículo expone, con base en la documentación oficial, qué son los hooks, la lista de eventos, cómo configurarlos, el contrato de entrada/salida, casos de uso y seguridad. Tres puntos por adelantado. ① Un hook es "lógica determinista que ejecuta el harness (el propio Claude Code)": se dispara con seguridad, sin esperar a que el modelo "decida" hacerlo. ② Los hooks se escriben en settings.json como nombre de evento → matcher → comando. ③ Eventos como PreToolUse pueden "bloquear" mediante el código de salida 2 o JSON: detienen ediciones a archivos protegidos o comandos peligrosos.

CLAUDE CODE · HOOKS

Se dispara "con seguridad" en puntos clave del ciclo de vida

— lo ejecuta el harness de forma determinista, no el criterio del modelo

SessionStart Comienza la sesión. La salida se inyecta como contexto
UserPromptSubmit Al enviar un prompt [puede bloquear]
PreToolUse Justo antes de que una herramienta se ejecute = el guardián [puede bloquear]
PostToolUse Después de que una herramienta tiene éxito = formateo automático / auditoría
Stop Cuando termina una respuesta = seguir hasta que pasen las pruebas, etc. [puede bloquear]

En cada punto se ejecuta tu comando de shell. Los clásicos: PreToolUse para frenar las acciones peligrosas en la puerta, PostToolUse para formatear automáticamente.

1. ¿Qué son los hooks de Claude Code?

La definición oficial dice: "Los hooks son comandos de shell definidos por el usuario que se ejecutan en puntos concretos del ciclo de vida de Claude Code. Proporcionan un control determinista sobre el comportamiento de Claude Code, garantizando que ciertas acciones siempre ocurran en lugar de depender de que el LLM elija ejecutarlas." Se usan para hacer cumplir las reglas del proyecto, automatizar tareas repetitivas e integrar Claude Code con tus herramientas existentes.

El núcleo es el determinismo. Pídele a Claude que "ejecute las pruebas" y que lo haga o no depende de su "criterio". Pero con un hook, el harness siempre lo ejecuta: no entra ningún capricho. Más allá de los comandos (command), ahora también hay tipos de manejador como HTTP, herramientas MCP, prompts de LLM y verificación por subagentes; pero para empezar, basta con pensar en los hooks como "un mecanismo para ejecutar siempre un comando de shell en puntos clave."

2. Los eventos de hook

Un evento representa "dónde, dentro del ciclo de vida, se dispara". Empieza por los nueve clásicos ("puede bloquear" = puedes detener esa acción mediante el código de salida 2 o JSON).

EventoSe dispara cuandoBloquea
SessionStartComienza o se reanuda una sesión (stdout se inyecta como contexto)No
UserPromptSubmitEnvías un prompt, antes de que Claude lo procese
PreToolUseJusto antes de una llamada a herramienta (el guardián principal)
PostToolUseDespués de que una herramienta tiene éxito (la acción en sí no se puede deshacer)
NotificationAnte una notificación (esperando entrada/permiso, etc.)No
StopCuando Claude termina de responder (bloquear = seguir trabajando)
SubagentStopCuando un subagente termina
SessionEndCuando una sesión finalizaNo
PreCompactAntes de la compactación del contexto

La documentación de 2026 añade muchos más eventos: PermissionRequest, PostToolUseFailure, ConfigChange, FileChanged, WorktreeCreate y otros. Pero los nombres de eventos pueden añadirse o cambiar entre versiones, así que este artículo se ancla en los nueve clásicos estables más el contrato de la siguiente sección (consulta la documentación oficial para ver la lista completa actual).

3. Cómo configurar los hooks

Los hooks se escriben bajo la clave "hooks" en settings.json. La ubicación define el alcance: usuario (~/.claude/settings.json) / proyecto (.claude/settings.json, compartible por git) / local (.claude/settings.local.json) / política gestionada (organización) / el hooks/hooks.json de un plugin. La forma del JSON es así.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

La estructura es "hooks → nombre de evento → un array de { matcher, hooks:[...] } → cada hook tiene type + command." El matcher especifica el nombre de la herramienta objetivo: "*" (u omitido) coincide con todas, "Edit|Write" es una lista separada por |, y otros caracteres son regex (p. ej. mcp__memory__.*). Distingue mayúsculas y minúsculas. El comando /hooks lista los hooks configurados, pero es de solo lectura: para añadir o cambiar, edita settings.json directamente. Desactívalos todos con "disableAllHooks": true.

4. El contrato de entrada/salida

Un hook recibe JSON en la entrada estándar (stdin) y devuelve su resultado mediante el código de salida o JSON en la salida estándar.

Entrada (stdin): los campos comunes incluyen session_id, transcript_path, cwd y hook_event_name. Los eventos de herramienta añaden tool_name y tool_input (p. ej. {"command":"rm -rf /tmp/build"}); UserPromptSubmit añade prompt. Códigos de salida: 0 = éxito (para algunos eventos, stdout se añade al contexto, aunque un exit 0 en PreToolUse no es "aprobación"; sigue aplicándose el flujo de permisos normal), 2 = bloquear (stderr se pasa a Claude como material para ajustarse, y la salida JSON se ignora).

# Ejemplo: "deny" desde PreToolUse mediante salida JSON estructurada (impresa en stdout)
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Database writes are not allowed"
  }
}
# Campos comunes: continue (false = detener por completo) / decision:"block"+reason /
#                additionalContext (anadido para Claude) / updatedInput (reescribir argumentos)

El principio más importante: "los hooks pueden endurecer las restricciones, pero no relajarlas." Devolver allow solo omite la solicitud de permiso; las reglas deny de cualquier alcance (incluida la configuración gestionada) siempre tienen prioridad. Un deny de PreToolUse bloquea incluso bajo bypassPermissions / --dangerously-skip-permissions. Para el modelo de permisos en general, consulta los modos de permiso y la seguridad.

5. Ejemplos de uso

Los clásicos oficiales, junto con su configuración.

CASOS DE USO

Las automatizaciones clásicas

Formateo automático tras editar
PostToolUse + Edit|Write ejecuta prettier / un linter automáticamente.
Proteger archivos críticos
PreToolUse bloquea (exit 2) ediciones a .env, .git/, etc.
Detener comandos peligrosos
PreToolUse detecta rm -rf, etc., y devuelve deny.
Reinyectar contexto
El stdout de SessionStart recarga las convenciones y notas cada vez (incluso tras la compactación).
Notificaciones y registro de auditoría
Notification para alertas de escritorio; PostToolUse para registrar el historial de comandos.
Probar antes de detenerse
Stop no deja que Claude se detenga hasta que pasen las pruebas (seguir trabajando hasta que estén en verde).

Nota: Claude también puede cambiar archivos mediante Bash. Para detectar cada cambio, añade un hook Stop que escanee el árbol de trabajo una vez por turno.

6. Seguridad

Los hooks son potentes, pero ejecutan comandos de shell arbitrarios de forma automática con tus privilegios: no te lo tomes a la ligera.

⚠️ La advertencia oficial

"Los hooks ejecutan comandos de shell arbitrarios de forma automática. Eres el único responsable de la seguridad de los hooks que configuras. ÚSALO BAJO TU PROPIA RESPONSABILIDAD." Los hooks pueden leer archivos, modificar tu base de código, exfiltrar datos o ejecutar cualquier comando: configura solo aquellos en los que confíes plenamente.

Instantánea al inicio (una función de seguridad clave): la configuración de los hooks se captura al iniciar la sesión, de modo que los cambios de configuración a mitad de sesión no surten efecto. Esto evita que un prompt malicioso o la salida de una herramienta reescriban la configuración de tus hooks durante una sesión. Aplica los cambios en una nueva sesión.

En la práctica: valida y entrecomilla siempre las entradas (extrae con jq; las variables sin comillas pueden convertirse en argumentos extra o en sintaxis de shell), usa rutas absolutas y ${CLAUDE_PROJECT_DIR}, no toques archivos sensibles como .env o .ssh, y nunca uses eval sobre la salida de una herramienta. Los hooks se ejecutan sin terminal controladora (sin /dev/tty). En las organizaciones, los administradores pueden restringir los hooks con allowManagedHooksOnly.

Resumen

Los hooks de Claude Code son comandos de shell definidos por el usuario que se ejecutan automáticamente en puntos clave del ciclo de vida, haciendo que el "esto siempre debe ocurrir" sea real y determinista sin depender del criterio del modelo. Los eventos clásicos son nueve: SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Notification / Stop / SubagentStop / SessionEnd / PreCompact (PreToolUse y otros pueden bloquear: detienen ediciones a archivos protegidos o comandos peligrosos). Se configuran en settings.json bajo "hooks" como evento → matcher → type + command.

La E/S es JSON en stdin, código de salida 0 (éxito) / 2 (bloquear), o JSON estructurado en stdout. El principio: "puedes endurecer pero no relajar las restricciones" (deny siempre gana). Los casos de uso clásicos: formateo automático, proteger archivos, detener comandos peligrosos, reinyectar contexto, auditoría y probar antes de detenerse. Pero como ejecutan código arbitrario, sé estricto al confiar solo en hooks seguros y validar/entrecomillar las entradas, y ten en cuenta que la configuración se captura al inicio. Relacionado: plugins, MCP, errores de Claude Code.

Preguntas frecuentes

P. ¿Para qué sirven los hooks?
R. Automatizan de forma determinista "esto siempre debe ocurrir." Cosas como "formatear tras editar", "que nunca se reescriban los archivos protegidos", "detener los peligrosos rm -rf" y "pasar las pruebas antes de detenerse" las ejecuta con seguridad el harness, sin depender del criterio de la IA. Un hook es un comando de shell que se ejecuta en puntos clave del ciclo de vida, configurado en settings.json.

P. ¿Qué eventos (momentos) hay?
R. Los clásicos son nueve: SessionStart (inicio), UserPromptSubmit (al enviar), PreToolUse (justo antes de una herramienta), PostToolUse (después de una herramienta), Notification, Stop (fin de respuesta), SubagentStop, SessionEnd (finalización), PreCompact (antes de la compactación). De estos, PreToolUse, UserPromptSubmit, Stop, PreCompact y otros pueden bloquear y detener la acción. La versión de 2026 añade muchos más eventos, pero los nombres pueden cambiar entre versiones, así que consulta la documentación oficial para lo más reciente.

P. ¿Puedo detener ediciones a archivos protegidos o comandos peligrosos?
R. Sí, con un hook PreToolUse. Un script inspecciona la ruta del archivo o el comando en tool_input, y si coincide con .env, rm -rf, etc., devuelve el código de salida 2 (o JSON con permissionDecision:"deny") para bloquearlo. Y lo crucial: deny siempre tiene prioridad y se detiene incluso bajo bypassPermissions. Los hooks solo funcionan en la dirección de "endurecer las restricciones".

P. Cambié mi configuración pero no surte efecto.
R. Eso es por diseño (una función de seguridad). La configuración de los hooks se captura como una instantánea al iniciar la sesión, de modo que los cambios a mitad de sesión no se aplican. Esto evita que un prompt malicioso o la salida de una herramienta reescriban en silencio la configuración de tus hooks. Inicia una nueva sesión para aplicarlo. Ten en cuenta que /hooks es una lista de solo lectura; añade o cambia hooks editando settings.json directamente.

P. ¿Son seguros los hooks?
R. No incondicionalmente. Los hooks ejecutan comandos de shell arbitrarios con tus privilegios, por eso la documentación dice "úsalo bajo tu propia responsabilidad". Configura solo hooks en los que confíes, valida y entrecomilla las entradas con jq, usa rutas absolutas y no toques .env / .ssh, y nunca uses eval sobre la salida de una herramienta. En las organizaciones, los administradores pueden restringir los hooks con allowManagedHooksOnly.