Contenido
"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.
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." Por cierto, los hooks de tipo prompt de LLM y de subagente tenían un error: si se redactaban como instrucciones ("Bloquea los comandos que..."), dejaban pasar lo que debían bloquear; se corrigió en la v2.1.294 (changelog oficial).
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).
| Evento | Se dispara cuando | Bloquea |
|---|---|---|
| SessionStart | Comienza o se reanuda una sesión (stdout se inyecta como contexto) | No |
| UserPromptSubmit | Envías un prompt, antes de que Claude lo procese (desde la v2.1.299, esto ocurre antes de que se expandan las habilidades y los comandos de barra personalizados; si lo bloqueas, tampoco se ejecutan los comandos de shell incrustados en ellos. documentación oficial · changelog, verificado el 18 de octubre de 2026) | Sí |
| PreToolUse | Justo antes de una llamada a herramienta (el guardián principal) | Sí |
| PostToolUse | Después de que una herramienta tiene éxito (la acción en sí no se puede deshacer) | No |
| Notification | Ante una notificación (esperando entrada/permiso, etc.) | No |
| Stop | Cuando Claude termina de responder (bloquear = seguir trabajando) | Sí |
| SubagentStop | Cuando un subagente termina | Sí |
| SessionEnd | Cuando una sesión finaliza | No |
| PreCompact | Antes de la compactación del contexto | Sí |
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 ni siquiera un "allow" en JSON puede anular el bloqueo).
Cuando falla el propio hook (no llega a arrancar, agota el tiempo o termina con un código de salida inesperado), en la mayoría de los eventos la acción sigue adelante por defecto. Un hook guardián con la ruta mal escrita solo muestra un aviso de error y no bloquea nada. Desde la v2.1.295, si añades "onFailure": "block" a un hook command o http, la acción se bloquea cuando el hook falla (el valor por defecto es "continue").
# 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)
Desde la v2.1.300 (14 de octubre de 2026), el updatedInput que devuelven los hooks PreToolUse y PermissionRequest se valida igual que la entrada de Claude. Las claves que la herramienta no reconoce se descartan, y si el hook devuelve una entrada que la herramienta no acepta, esa llamada se rechaza (changelog, verificado el 18 de octubre de 2026).
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. Este principio se aplica a los hooks definidos en archivos de configuración, que la documentación de los mods llama "settings hooks": desde la v2.1.287, un mod (un plugin cuyos hooks son funciones) que responde a tool.check puede aprobar una llamada que una regla ask habría consultado o que un hook PreToolUse bloqueó (salvo que ese hook esté en la configuración gestionada); sus aprobaciones se saltan el clasificador del modo auto y, salvo en equipos con configuración gestionada o con sesión iniciada en un plan Team o Enterprise, puede aprobar incluso una llamada que una regla deny rechazó (documentación oficial). Instala solo mods de autores en los que confíes. Es decir, los hooks pueden ampliar cómo se evalúan los permisos, pero las reglas de base están en otro lugar: las reglas de permisos de Claude Code (allow/ask/deny) se definen en settings.json. 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.
Las automatizaciones clásicas
PostToolUse + Edit|Write ejecuta prettier / un linter automáticamente.PreToolUse bloquea (exit 2) ediciones a .env, .git/, etc.PreToolUse detecta rm -rf, etc., y devuelve deny.SessionStart recarga las convenciones y notas cada vez (incluso tras la compactación).Notification para alertas de escritorio; PostToolUse para registrar el historial de comandos.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.
Si solo quieres el comportamiento de «seguir hasta que se cumpla una condición» sin escribir tú mismo un hook Stop, /goal está disponible en el momento (un hook de tipo prompt que funciona solo dentro de la conversación).
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 de comando ejecutan comandos de shell con todos los permisos de tu usuario. Pueden modificar, eliminar o acceder a cualquier archivo al que tenga acceso tu cuenta. Revisa y prueba todos los comandos de los hooks antes de añadirlos a tu configuración." 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.
Confianza en la carpeta (una medida de seguridad clave): en una sesión interactiva, los hooks de los archivos de configuración no se ejecutan hasta que aceptas el diálogo de confianza de la carpeta (incluidos los de tu propio ~/.claude/settings.json). Una sesión con -p o del SDK no muestra el diálogo y trata la carpeta como de confianza, así que revisa la configuración en .claude/ de un repositorio antes de ejecutarlo ahí. Los cambios hechos directamente en los archivos de configuración normalmente se aplican solos.
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, salvo la excepción de los mods de la sección 4). 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 en las sesiones interactivas, los hooks de los archivos de configuración no se ejecutan hasta que confías en la carpeta. Relacionado: plugins, MCP, errores de Claude Code, mods (resumen oficial) y nuestra guía detallada: Mods 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". La excepción es un mod (un plugin cuyos hooks son funciones): al responder a tool.check puede anular estas decisiones y, salvo en equipos con configuración gestionada o con sesión iniciada en un plan Team o Enterprise, puede aprobar incluso una llamada que una regla deny rechazó (documentación oficial). Instala solo mods de autores en los que confíes.
P. Cambié mi configuración pero no surte efecto.
R. Normalmente, los cambios se aplican solos: al editar directamente un archivo de configuración, el vigilante de archivos detecta el cambio. Si tras unos segundos sigue sin aplicarse, puede que el vigilante lo haya pasado por alto, así que reinicia la sesión. Comprueba también que el JSON sea válido (sin comas finales ni comentarios). En una sesión interactiva, los hooks de los archivos de configuración no se ejecutan hasta que aceptas el diálogo de confianza de la carpeta. Ten en cuenta que /hooks es una lista de solo lectura; para añadir o cambiar hooks, edita 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 advierte que se ejecutan "con todos los permisos de tu usuario". 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.