El ABS no espera que el conductor lo active. Se dispara automáticamente cuando detecta que una rueda se bloquea, de forma determinista, cada vez, sin importar si el conductor lo recuerda o no.
Los hooks son exactamente esto: controles deterministas que se ejecutan automáticamente en puntos específicos del ciclo de vida, sin importar qué instruya el prompt en ese momento.
Los hooks funcionan como Express middleware: interceptan el flujo en puntos específicos, pueden modificar datos, bloquear la ejecución o agregar contexto.
| Instrucción en CLAUDE.md | Hook PreToolUse |
|---|---|
| "No borres archivos .env" | Bloquea físicamente cualquier operación sobre .env |
| Claude puede olvidar o ignorar | Se ejecuta siempre, de forma determinista |
| Probabilístico | Determinista |
| Sin enforcement físico | Exit code 2 = bloqueado, sin negociación |
rm -rf tests/ patches/ plan/ ~/ — el ~/ final borró todo el Mac. Un hook PreToolUse con pattern rm -rf ~ habría bloqueado la operación.
.env con credenciales de producción y las copió a env.example, que fue commiteado. Un hook PostToolUse escaneando secrets habría detectado y revertido.
Inyectar contexto inicial
Validar / inyectar al prompt
Bloquear tool call
Bash, Edit, Write...
Format / audit / validate
Quality gate final
| Evento | Cuándo | ¿Bloquea? | Matcher |
|---|---|---|---|
PreToolUse | Antes de cualquier tool call | ✅ SÍ | Nombre de herramienta |
PostToolUse | Después de tool call exitoso | ❌ No | Nombre de herramienta |
PostToolUseFailure | Después de tool call fallido | ❌ No | Nombre de herramienta |
PostToolBatch | Tras TODAS las tool calls paralelas | ✅ SÍ — para el loop | Sin matcher |
PermissionRequest | Diálogo de permiso aparece | ✅ SÍ — deniega | Nombre de herramienta |
| Evento | Cuándo | ¿Bloquea? | Matcher |
|---|---|---|---|
SessionStart | Inicio o resume de sesión | ✅ — inyecta contexto | startup, resume, clear, compact |
SessionEnd | Sesión termina | ❌ No | clear, logout… |
UserPromptSubmit | Usuario envía prompt, antes de Claude | ✅ SÍ — bloquea y borra | Sin matcher (siempre) |
UserPromptExpansion | Slash command se expande | ✅ SÍ — bloquea expansión | command_name |
| Evento | Cuándo | ¿Bloquea? |
|---|---|---|
Stop | Claude termina de responder | ✅ SÍ — exit 2 = continúa trabajando |
StopFailure | Turno termina por error API | ❌ No |
Notification | Claude Code envía notificación | ❌ No |
| Evento | Cuándo | ¿Bloquea? |
|---|---|---|
SubagentStart | Subagente spawneado | ❌ No |
SubagentStop | Subagente termina | ✅ SÍ — previene que pare |
TeammateIdle | Teammate a punto de idle | ✅ SÍ — mantiene trabajando |
TaskCreated | Tarea creada vía TaskCreate | ✅ SÍ — rollback |
TaskCompleted | Tarea marcada como completada | ✅ SÍ — previene completar |
| Evento | Cuándo | ¿Bloquea? |
|---|---|---|
WorktreeCreate | Worktree siendo creado | ❌ No |
WorktreeRemove | Worktree siendo eliminado | ❌ No |
PreCompact | Antes de compactación de contexto | ✅ SÍ — bloquea compactación |
PostCompact | Después de compactación | ❌ No |
ConfigChange | Archivo de config cambia | ✅ SÍ — bloquea cambio |
FileChanged | Archivo observado cambia en disco | ❌ No |
Elicitation | MCP server solicita input del usuario | ✅ SÍ — deniega |
| Exit code | Significado | Comportamiento |
|---|---|---|
0 | Éxito / Continuar | Stdout como JSON → inyectado como contexto (SessionStart, UserPromptSubmit). Resto: solo debug log |
2 | Bloquear / Feedback | Stderr → enviado a Claude como error. Claude decide cómo reaccionar (en eventos bloqueantes: la operación se cancela) |
1+ | Error no-bloqueante | La operación continúa. Se registra en debug log |
El más común. Ejecuta un script shell. Recibe JSON en stdin.
Default timeout: 600s
Envía POST request. Útil para integración con sistemas externos.
Non-2xx = error no-bloqueante. Para bloquear: 2xx + decision:"block"
Invoca herramienta de un MCP server conectado. Para validaciones con herramientas externas.
Evaluación LLM para validaciones semánticas que un regex no puede hacer.
Default timeout: 30s
Subagente con herramientas Read/Grep/Glob para verificaciones complejas.
Default timeout: 60s
| Campo | Descripción | Default |
|---|---|---|
type | Requerido: command | http | mcp_tool | prompt | agent | — |
if | Filtro adicional con sintaxis de permission rules | Sin filtro |
timeout | Segundos de timeout | 600 / 30 / 60 según tipo |
statusMessage | Texto custom del spinner mientras ejecuta | Genérico |
once | Se ejecuta solo una vez por sesión (skills) | false |
async | Ejecutar sin esperar resultado | false |
asyncRewake | Despertar a Claude con output cuando async completa | false |
Un aeropuerto tiene múltiples capas de seguridad: scanner de maletas (PreToolUse), inspección aleatoria (PostToolUse), detección en puertas (Stop). Cada capa es independiente y determinista — no depende de que el viajero "recuerde" las reglas.
| Archivo | Scope | Prioridad |
|---|---|---|
~/.claude/settings.json | Usuario global | 1 (primero) |
.claude/settings.json | Proyecto | 2 |
.claude/settings.local.json | Proyecto local (no en git) | 3 |
--hooks CLI flag | Sesión | 4 |
Skill frontmatter hooks: | Cuando la skill está activa | 5 |
| Anti-patrón | Problema | Solución |
|---|---|---|
| Hook sin timeout | Bloquea la sesión indefinidamente | Siempre definir timeout |
| UI interactiva en el script | Hooks no tienen acceso a /dev/tty | Usar notificaciones o audit log |
| Exit 2 en PostToolUse para bloquear | PostToolUse no puede bloquear | Mover lógica a PreToolUse |
| Script sin logging en stderr | Falla silenciosamente | Siempre loggear errores en stderr |
| Lógica compleja (+50 líneas) | Difícil de mantener | Mover a MCP server |
Blake Crosley documentó públicamente por qué cada uno de sus 95 hooks existe:
| Categoría | Cantidad | Propósito |
|---|---|---|
| Seguridad | 23 hooks | Bash guard, file protection, secrets scanner |
| Calidad | 18 hooks | Auto-format, lint, type check post-edit |
| Observabilidad | 15 hooks | Audit log, session metrics, file change tracking |
| Flujo de trabajo | 39 hooks | Context injection, notification, CI/CD integration |
Dwarves Foundation publicó configuración hardened de seguridad para Claude Code con hooks de denegación de permisos, guards de shell y defensa contra prompt injection.
mafiaguy/claude-security-guardrails — dashboard React en tiempo real de eventos bloqueadosrulebricks/claude-code-guardrails — guardrails en tiempo realPatrón más adoptado en la comunidad para el hook Stop: notificación multi-canal cuando Claude termina un task largo.