Claude Code Hooks: settings.json, los 5 eventos y el bloqueo por exit code
Los hooks son la capa determinista de Claude Code: siempre corren, sin pedirle nada al modelo. Este recorrido ilustrado usa el video de hooks de la propia Anthropic para las imágenes — los cinco eventos, un script de bloqueo en PreToolUse, un deny JSON estructurado y una config completa de formateo en PostToolUse.
TL;DR — qué son los hooks de Claude Code
- Los hooks son deterministas: corren en puntos fijos del ciclo de vida de Claude Code, todas las veces. Una instrucción en CLAUDE.md tipo “corre Prettier después de cada edición” funciona casi siempre — un hook funciona siempre.
- Hay cinco eventos: UserPromptSubmit (antes de que se procese tu prompt), PreToolUse (antes de una llamada a herramienta), PostToolUse (cuando una herramienta termina), Notification y Stop (cuando Claude termina de responder).
- Un hook de PreToolUse que sale con exit code 2 bloquea la llamada a la herramienta, y el mensaje de stderr se le devuelve a Claude para que sepa por qué. El exit code 0 deja pasar la llamada.
- Los hooks viven en settings.json — un evento, un matcher de herramienta opcional y un comando. Guárdalos en el .claude/settings.json del proyecto y hazle commit, y todo tu equipo hereda las mismas garantías.
Hooks in Claude Code
Canal:Claude (official Anthropic channel)3:22
Claude Code Hooks, Explained Simply
Canal:Agentic Lab8:32
Claude Code - Getting Started with Hooks
Canal:Greg Baugues11:53
Hooks reference — Claude Code documentation
Docs:code.claude.com
Los cuadros de esta guía vienen del video explicativo oficial de hooks de Anthropic; el texto del recorrido se escribió de forma independiente y se contrastó con la referencia oficial de hooks.
Las capturas siguen siendo propiedad de sus creadores y se usan con atribución como documentación visual. Cada paso enlaza directo al momento exacto del video original.
Configura los hooks de Claude Code, paso a paso
1 · Cómo se ven los hooks en la vida real
- 1
Mira un hook dispararse al final de una respuesta
La línea de estado lee “Running stop hook · 39s · 484 tokens” — Claude Code está ejecutando un Stop hook antes de devolverte el turno. Esa es toda la idea en una captura: un comando que registraste corre en un punto fijo del ciclo de vida, en cada ocurrencia que aplique, sin depender de que el modelo se acuerde de hacer algo.

Un Stop hook ejecutándose tras la respuesta de Claude — 39 segundos, 484 tokens gastados.Ver en 0:10 - 2
Aprende los cinco eventos de hook
UserPromptSubmit corre en cuanto envías un prompt, antes de que Claude lo procese. PreToolUse corre antes de cada llamada a herramienta. PostToolUse corre cuando una llamada termina. Notification se dispara cuando Claude manda una notificación, y Stop corre cuando Claude termina de responder. Cada hook que escribas se engancha exactamente a uno de estos cinco puntos.

Los cinco eventos, del video oficial de hooks de Anthropic — todo lo demás cuelga de esta lista.Ver en 1:04
2 · Escribe tus primeros hooks
- 3
Agrega un bloque de hooks a settings.json
Un hook son tres cosas en settings.json: el nombre del evento, un matcher opcional que acota a qué herramienta aplica, y el comando a ejecutar. En la captura, el matcher de PreToolUse se está autocompletando con Edit — ese hook solo se disparará en llamadas de edición de archivos. Si prefieres no tocar JSON, el menú de /hooks edita la misma config de forma interactiva.

El matcher autocompleta Edit, acotando el hook de PreToolUse solo a ediciones de archivos.Ver en 0:14 - 4
Bloquea comandos peligrosos con exit code 2
Un hook de PreToolUse recibe el nombre de la herramienta y su input como JSON por stdin. Este script lo pasa por jq para tomar .tool_input.command, hace grep de patrones destructivos — rm -rf, git push --force — y al coincidir imprime la razón en stderr y sale con código 2. El exit code 2 bloquea la llamada; el texto de stderr se le devuelve a Claude como feedback, así el modelo sabe por qué fue bloqueado y puede ajustarse.

jq lee el comando de stdin; una coincidencia de rm -rf o --force imprime en stderr y sale con 2.Ver en 2:02 - 5
Envía una denegación estructurada en vez de un exit code
Para control más fino, un hook puede imprimir una decisión JSON en lugar de depender de exit codes. Aquí un hook de PreToolUse atrapa DROP TABLE, y el hookSpecificOutput lleva permissionDecision “deny” más una razón — “usa una migration en su lugar” — que aterriza en el contexto del modelo. La misma garantía dura, pero con una instrucción accionable adjunta.

Un permissionDecision de deny bloquea el comando SQL y le dice al modelo qué hacer en su lugar.Ver en 2:16 - 6
Mantén los hooks en el repo para que el equipo los reciba
Los hooks configurados en el .claude/settings.json del proyecto son de nivel proyecto y se pueden commitear. Todos los que clonen el repo corren los mismos hooks automáticamente — incluidos los que bloquean. Guarda los scripts auxiliares en .claude/hooks/ y refiérelos con la variable de entorno CLAUDE_PROJECT_DIR para que las rutas resuelvan sin importar dónde esté el directorio de trabajo de Claude.

La carpeta .claude del proyecto guarda settings.json más un directorio hooks/ de scripts compartidos.Ver en 0:17 - 7
Copia una config de hooks completa y real
Esta config hace dos trabajos a la vez. El bloque de PostToolUse matchea Edit|Write|MultiEdit y corre .claude/hooks/auto-format.sh con un timeout de 30 segundos, así todo archivo que Claude toque queda formateado. Debajo, un segundo hook matchea Bash y loguea cada comando ejecutado — el patrón de compliance. Los campos timeout y async evitan que los formateadores lentos traben la sesión.

Auto-formateo de PostToolUse con timeout de 30s, más un hook de Bash que loguea cada comando.Ver en 2:46
3 · Úsalos como equipo
- 8
Apréndete de memoria el contrato de exit codes
Exit code 0 significa continuar. Exit code 2 significa bloquear — y el stderr se le pasa a Claude como feedback sobre el que puede actuar. Cualquier otro exit code te muestra el stderr a ti, el usuario, pero la llamada continúa; úsalo para advertencias que quieres ver sin bloquear duro al agente.
- 9
Registra hooks desde el menú /hooks y elige tus recetas
El comando /hooks abre la misma configuración de forma interactiva — útil para verificar qué hooks están registrados y en qué scope. De ahí salen las cuatro recetas de trabajo: auto-formatear tras editar (PostToolUse), loguear todos los comandos ejecutados (PostToolUse sobre Bash), bloquear operaciones peligrosas (PreToolUse con exit 2), y avisarte cuando Claude termina (Stop). Regla de oro: si algo debe pasar siempre sin falta, no lo pongas en un prompt — ponlo en un hook.
El contrato de exit codes, en una tabla
Cada comando de hook se comunica por su exit code. Tres casos cubren todo lo que necesitas:
- exit 0Continuar. La llamada corre normal. El stdout del hook es visible en modo transcript (Ctrl-R).
- exit 2Bloquear. La llamada se rechaza y el stderr del hook se devuelve a Claude como feedback, así el modelo corrige el rumbo — eso vuelve a los hooks de exit-2 enseñables y no solo fatales.
- exit 1Cualquier otro código: avisar, no bloquear. El stderr se te muestra pero la llamada continúa. Úsalo para hooks de asesoría — “este archivo normalmente se genera, ¿seguro?”
Un camino de upgrade más: en vez de exit codes, un hook puede imprimir una decisión JSON (hookSpecificOutput con permissionDecision) para denegar con una razón estructurada, como en el paso 5. Los exit codes son el contrato simple; las decisiones JSON son el tipeado.
Cuatro recetas que vale la pena commitear hoy
El video oficial llama cuatro casos de uso; aquí van como intención lista para copiar:
- 1Auto-formateo tras editar — un hook de PostToolUse que matchea Edit|MultiEdit, revisa la extensión del archivo y corre el formateador correcto: Prettier para TypeScript, gofmt para Go, Ruff para Python.
- 2Loguear cada comando ejecutado — un hook de PostToolUse sobre Bash que agrega cada comando a un archivo. A los equipos de compliance les encanta; a ti del futuro debuggeando el martes pasado también.
- 3Bloquear operaciones peligrosas — un hook de PreToolUse con exit 2 que protege directorios de config de producción, patrones de rm -rf o commits a main. Estos pasan de sugerencias a garantías.
- 4Avisar cuando la tarea termina — un hook de Stop o Notification que dispara una notificación de escritorio o sonido, así las corridas largas del agente no necesitan niñera.
Las cuatro caben en un solo .claude/settings.json. Empieza por el formateador — es el hook que vas a sentir en cada guardado.
