NeuralOS
GuíaAvanzado

Hooks de Claude Code · automatiza tu flujo con los eventos del ciclo de vida del agente

Ya sabes escribir un buen contrato para tu agente: le dices en el AGENTS.md cómo quieres que trabaje. El problema es que un LLM lee ese contrato y decide de nuevo en cada turno — así que la regla crítica se cumple casi siempre, y ese "casi" es justo el que te muerde. Los hooks son el peldaño siguiente: sacas la regla de la cabeza del modelo y la metes en la infraestructura, para que pase el 100% de las veces sin depender de su criterio. Te explico los eventos del ciclo de vida donde te enganchas, la anatomía del JSON, dónde vive cada hook y por qué importa, y te dejo tres hooks reales listos para pegar (auto-formateo, bloqueo de comandos peligrosos, notificación de escritorio) sacados de la documentación oficial de Anthropic. Un solo prompt maestro para montar tu primero con la seguridad puesta — porque un hook corre shell con tus permisos. Es el salto de "escribe el contrato" a "haz que el contrato se ejecute solo".

Jul 19, 202614 min
¿Para quién es esto?
Para ti, que ya construyes con IA en Claude Code y llevas semanas repitiendo la misma frase: "acuérdate de formatear", "no toques el .env", "corre los tests antes de commitear". Se te olvida a ti, se le olvida a la IA, y un día se cuela un cambio que no debía. Los hooks son el salto de "le pido que se acuerde" a "pasa siempre, aunque nadie se acuerde". No necesitas ser programador: necesitas entender un patrón y copiar tres bloques de JSON.

1. El momento · cuando descubres que "pedirle a la IA" no basta

Llega un punto en todo proyecto con IA en el que dejas de fiarte de la buena voluntad del modelo. Le escribiste en tu AGENTS.md que formatee el código, que no toque los archivos sensibles, que corra los tests. Y el 90% de las veces lo hace. Pero el 10% restante es justo el que te muerde: la vez que editó el .env de producción, la vez que se saltó el formato y el commit quedó sucio, la vez que ejecutó un rm -rf sobre la carpeta equivocada porque "parecía temporal".

El momento de los hooks es cuando piensas: "¿y si esto no dependiera de que el modelo decida hacerlo bien? ¿Y si simplemente pasara, siempre, sin depender de su criterio?". Esa es exactamente la promesa que la documentación oficial de Claude Code pone en el centro de la página de hooks: dan "control determinista" sobre el comportamiento del agente, "garantizando que ciertas acciones siempre ocurran en lugar de depender de que el LLM elija ejecutarlas" (traducción fiel del original en inglés). Esa frase es la tesis entera del recurso.

Imagínalo así
Un contrato (tu AGENTS.md) es como el reglamento pegado en la pared de una fábrica: dice cómo se deben hacer las cosas, y confías en que cada operario lo lea y lo cumpla. Un hook es el sensor en la cinta transportadora que para la máquina físicamente si una pieza sale mal. El reglamento persuade; el sensor obliga. Los hooks son el sensor — no piden por favor, cortan la corriente.

2. El dolor · de dónde sale y por qué pasa

El dolor no es un apocalipsis, es una erosión. Le pediste a la IA que hiciera algo "siempre" y a veces no lo hace, porque un LLM no es determinista: cada turno decide de nuevo, y en un turno cargado de contexto, tu recordatorio de formatear puede quedar sepultado bajo mil tokens de otra cosa. No es que la IA sea desobediente — es que le estás pidiendo consistencia a un sistema probabilístico. Es como pedirle a alguien brillante pero distraído que no olvide nunca cerrar la llave del gas: la mayoría de las noches la cierra, y esa es justo la razón por la que bajas la guardia.

Síntomas de que necesitas hooks
Repites la misma instrucción en cada sesión ("formatea", "no toques X", "corre los tests") y aún así a veces se salta.
Descubriste después que la IA editó un archivo que jamás debía tocar: .env, un package-lock.json, algo dentro de .git/.
Un commit se coló con formato inconsistente y ensució el diff de todo el equipo.
Te da un poco de miedo dejar a la IA con permisos amplios porque no hay una red de seguridad que no dependa de ella misma.
Tu AGENTS.md tiene reglas críticas escritas en prosa, y "escrito" no es lo mismo que "garantizado".
El malentendido más común
Mucha gente cree que si escribe la regla con MAYÚSCULAS y signos de exclamación en el AGENTS.md, ya está "forzada". No lo está. Por muy enfática que sea, sigue siendo texto que el modelo lee y decide obedecer o no. La única forma de que algo pase de verdad —el 100% de las veces, sin excepción— es sacarlo de la cabeza del LLM y meterlo en la infraestructura. Eso son los hooks.

Y aquí está el ángulo que hace a este recurso avanzado: si ya leíste sobre escribir un buen contrato para tu agente (el AGENTS.md), los hooks son el siguiente peldaño. Pasas de "escribe el contrato" (declarativo: le dices qué quieres) a "haz que el contrato se ejecute solo" (determinista: la máquina lo cumple por ti). Es la diferencia entre una ley escrita en un papel y un policía parado en la esquina.

3. Qué es un hook (sin humo, en una frase)

Un hook es un comando de shell que Claude Code ejecuta automáticamente en un punto concreto de su ciclo de vida. Tú lo declaras una vez en un archivo settings.json; a partir de ahí, cada vez que ocurra ese punto del ciclo, tu comando corre. No lo dispara el modelo con su criterio: lo dispara el evento. Ahí está la magia — es determinista, no opinable.

La idea de fondo
Claude Code va emitiendo señales mientras trabaja: "acabo de recibir un prompt", "estoy a punto de usar una herramienta", "terminé de editar un archivo", "voy a comprimir el contexto", "terminé de responder". Un hook es engancharse a una de esas señales y decir: "cuando eso pase, corre ESTO". Enganchar (to hook) — de ahí el nombre y el emoji 🪝.

4. Los eventos del ciclo de vida (los puntos donde te enganchas)

La documentación oficial lista muchos eventos del ciclo de vida — hay uno para casi cualquier momento del trabajo del agente. No te aprendas el número ni la lista completa: aprende la idea y quédate con los que de verdad vas a usar el 95% del tiempo. Estos son, con sus nombres reales tal cual aparecen en la doc:

Los eventos que importan (nombres reales de la doc oficial)
`SessionStart` — cuando arranca o se reanuda una sesión. Ideal para inyectar contexto fresco (ej. tus convenciones, los últimos commits). Su salida a stdout se añade al contexto de Claude.
`UserPromptSubmit` — justo cuando envías un prompt, antes de que Claude lo procese. Puedes añadir contexto o incluso bloquear el prompt.
`PreToolUse`antes de que una herramienta se ejecute. Este puede bloquear la acción. Es tu guardaespaldas: aquí frenas un rm -rf o una edición a un archivo protegido.
`PostToolUse`después de que una herramienta tiene éxito. Aquí formateas el archivo recién editado, corres un lint, lo que quieras.
`Notification` — cuando Claude te necesita (pide permiso o está esperando). Perfecto para una notificación de escritorio.
`Stop` / `SubagentStop` — cuando Claude (o un subagente) termina de responder. Útil para un chequeo final antes de dar por cerrado el turno.
`PreCompact` (y SessionStart con matcher compact) — alrededor de la compactación del contexto, para no perder lo importante cuando la memoria se comprime.
`SessionEnd` — cuando la sesión termina. Para limpiar archivos temporales, cerrar cosas.
La distinción que lo aclara todo · Pre vs. Post
`PreToolUse` ocurre ANTES y PUEDE bloquear (la herramienta todavía no se ejecutó, así que puedes vetarla). `PostToolUse` ocurre DESPUÉS y NO puede deshacer (la herramienta ya corrió; la doc lo dice sin rodeos). Regla mental: si quieres impedir algo, engánchate a Pre. Si quieres reaccionar a algo que ya pasó (formatear, avisar, registrar), engánchate a Post.

5. Cómo se declara un hook (la anatomía del JSON)

Todo hook vive dentro de un bloque "hooks" en tu settings.json. La estructura es siempre la misma muñeca rusa: el nombre del evento → un matcher (a qué se aplica) → una lista de hooks con type: "command" y el command a correr. Míralo una vez y ya no se te olvida:

json
{
  "hooks": {
    "PostToolUse": [                    // 1. el EVENTO del ciclo de vida
      {
        "matcher": "Edit|Write",         // 2. A QUÉ herramientas aplica
        "hooks": [
          {
            "type": "command",           // 3. es un comando de shell
            "command": "...tu comando..." // 4. QUÉ correr cuando ocurra
          }
        ]
      }
    ]
  }
}
El matcher, en simple
El matcher filtra a qué se aplica el hook. Para eventos de herramienta (PreToolUse, PostToolUse) filtra por nombre de herramienta: "Edit|Write" significa "solo cuando use Edit o Write", "Bash" solo comandos de shell. Un matcher vacío ("") se dispara siempre, para todo. La barra | separa alternativas (en versiones recientes de Claude Code también vale la coma: "Edit, Write" es equivalente).

6. Dónde vive un hook (y por qué importa el lugar)

El lugar donde pones el hook define su alcance. Esto es clave: un hook de proyecto se comparte con tu equipo (se commitea al repo); uno global es solo tuyo. La tabla oficial resume dónde va cada cosa:

Los tres sitios donde puede vivir un hook
`~/.claude/settings.json` — global, aplica a todos tus proyectos. No se comparte, es de tu máquina. Aquí van tus hooks personales (notificaciones de escritorio, por ejemplo).
`.claude/settings.json` (dentro del repo) — solo ese proyecto, y se puede commitear: todo tu equipo hereda la regla. Aquí van las reglas del proyecto (formateo, archivos protegidos).
`.claude/settings.local.json` — solo ese proyecto, privado: Claude Code lo gitignora cuando lo crea. Para tus ajustes locales que no quieres compartir.
La regla de oro del lugar
Si la regla debe cumplirla todo el que trabaje en este repo (formatear, no tocar archivos sensibles), va en .claude/settings.json y se commitea. Así el contrato deja de vivir en la cabeza de una persona y pasa a viajar con el código. Ese es el poder real: la disciplina se vuelve parte del repositorio, no un post-it que alguien tiene que recordar.

7. Tres hooks copy-paste que valen su peso en oro

Basta de teoría. Aquí tienes tres hooks reales, sacados de la documentación oficial, listos para pegar. Empieza por el que más te duela hoy.

a) Auto-formatear después de cada edición (PostToolUse)

El clásico. Cada vez que Claude edita o escribe un archivo, se pasa Prettier automáticamente. Nunca más un commit con formato inconsistente. Va en .claude/settings.json de tu proyecto:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}
Cómo funciona por dentro (para que no sea magia)
Cuando el evento se dispara, Claude Code le pasa a tu comando un JSON por la entrada estándar (stdin) con los datos: qué herramienta usó, sobre qué archivo, etc. Aquí jq -r '.tool_input.file_path' extrae la ruta del archivo editado de ese JSON, y xargs npx prettier --write se la pasa a Prettier. jq es un lector de JSON de línea de comandos — instálalo con brew install jq en macOS o apt-get install jq en Debian/Ubuntu.

b) Bloquear comandos peligrosos como rm -rf (PreToolUse)

Este es el que te quita el miedo. Un hook PreToolUse que revisa cada comando de Bash antes de ejecutarlo y lo veta si contiene algo destructivo. Aquí sí importa un detalle técnico que la doc deja clarísimo: se bloquea saliendo con código 2, y lo que escribas a stderr le llega a Claude como explicación para que se corrija. Primero el script:

bash
#!/bin/bash
# .claude/hooks/block-rm-rf.sh
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

if echo "$COMMAND" | grep -q "rm -rf"; then
  echo "Bloqueado: 'rm -rf' no está permitido. Borra rutas concretas, no recursivo-forzado." >&2
  exit 2   # exit 2 = bloquea la accion; stderr le llega a Claude como feedback
fi

exit 0     # exit 0 = sin objecion; sigue el flujo normal de permisos

Hazlo ejecutable y regístralo en tus settings apuntando al script:

bash
chmod +x .claude/hooks/block-rm-rf.sh
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm-rf.sh"
          }
        ]
      }
    ]
  }
}
Honestidad · este grep es una demo, no un candado hermético
Un grep -q "rm -rf" atrapa el caso obvio, pero se lo salta un rm -fr, un rm -rf con espacios raros, o un rm --recursive --force. Sirve de red visible y de feedback educativo para la IA, pero no lo confundas con un blindaje. La propia doc lo dice sin rodeos: el filtrado de hooks es best-effort y "falla abierto" (si no puede parsear el comando, lo deja pasar), así que para una prohibición DURA que nadie pueda saltarse, usa el sistema de permisos (permissions.deny), no un hook. El patrón correcto es: hook para reaccionar y avisar; permission rules para el candado real.
El detalle que te salva de verdad · el hook gana incluso en modo bypass
Esto es lo más poderoso y casi nadie lo sabe: según la doc oficial, un PreToolUse que devuelve una decisión de bloqueo veta la herramienta INCLUSO en `bypassPermissions` o con `--dangerously-skip-permissions`. Es decir: aunque tú (o la IA) hayan bajado todas las barreras de permisos, tu hook de bloqueo sigue en pie. La regla es asimétrica y está pensada así a propósito: los hooks pueden endurecer la política, nunca aflojarla más allá de lo que permiten las reglas de permisos. Un hook de bloqueo es una regla que ni tú puedes saltarte por accidente.

c) Notificación de escritorio cuando la IA te necesita (Notification)

Para dejar de vigilar la terminal. Cuando Claude termina o necesita tu permiso, te salta una notificación de escritorio y te vas a hacer otra cosa. Va en tu ~/.claude/settings.json global (ejemplo de macOS con osascript):

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code necesita tu atención\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
En Linux y Windows
El mismo hook, cambiando el comando: en Linux usa notify-send 'Claude Code' 'Claude Code necesita tu atención'; en Windows (PowerShell) un MessageBox de System.Windows.Forms. La estructura del JSON es idéntica — solo cambia la línea del command. Truco de macOS que documenta la propia guía: si no aparece la notificación, corre una vez osascript -e 'display notification "test"' y luego dale permiso a Script Editor en Ajustes del Sistema → Notificaciones.

8. El hábito · cuándo pensar en un hook (y cuándo NO)

Los hooks no son para todo. La regla mental es sencilla: si algo debe pasar siempre, de forma mecánica y sin criterio, es un hook. Si algo requiere juicio caso por caso, no lo fuerces con un hook determinista — deja que lo decida el modelo (o usa los hooks de tipo prompt/agente que la doc también soporta, pero eso es otra liga).

Momentos en que SIEMPRE deberías pensar en un hook
Cada vez que te descubras escribiendo "acuérdate de…" por tercera vez en tu AGENTS.md. Si lo repites, conviértelo en hook.
Cuando haya una acción que jamás debe ocurrir (tocar .env, borrar recursivo, escribir en .git/): eso es un PreToolUse de bloqueo — respaldado por una regla de permisos para el candado duro.
Cuando haya una acción que siempre debe ocurrir tras editar (formatear, ordenar imports, correr un lint): eso es un PostToolUse.
Cuando quieras que un contexto crítico se re-inyecte tras cada compactación, para que la IA no "olvide" tus convenciones a mitad de sesión.
El límite honesto de los hooks
Un hook de comando corre shell determinista: sirve para reglas mecánicas (esta ruta sí, esta no), no para juicios matizados ("¿este cambio es una buena idea?"). Y ojo con PostToolUse: no puede deshacer lo que ya pasó — solo reacciona. Para impedir, siempre PreToolUse. Meter demasiada lógica compleja en un hook lo vuelve frágil; mantenlos cortos y de un solo propósito.
Seguridad · los hooks corren shell con TUS permisos
La doc oficial lo advierte sin rodeos y hay que repetirlo: un hook ejecuta comandos de shell arbitrarios con tus credenciales, automáticamente. Nunca pegues un hook que no entiendas, jamás copies uno de una fuente que no sea de confianza, y revisa cada comando antes de guardarlo. Un hook malicioso es un comando malicioso corriendo solo. Léelos como leerías cualquier script que vas a correr en tu máquina.

9. El protocolo de uso · monta tu primer hook útil

Aquí el detalle práctico: la propia doc te recomienda pedirle a Claude que te escriba el hook describiéndoselo. Pero para que salga bien —y sea seguro— conviene darle un encargo estructurado, no un "ponme un hook". Este es EL prompt maestro del recurso: uno solo, potente, que diseña tu primer hook con los frenos de seguridad puestos.

Prompt maestro · diseña tu primer hook útil (con seguridad)texto
Quiero montar mi primer hook de Claude Code para automatizar una regla de mi flujo. La regla que quiero garantizar SIEMPRE es: [DESCRIBE LA REGLA, ej: "formatear con prettier cada archivo que edites" / "bloquear cualquier comando que borre archivos de forma recursiva" / "impedir que se edite el .env o cualquier cosa dentro de .git/" / "avisarme por notificación cuando termines"].

Antes de escribir nada, ayúdame a diseñarlo bien respondiendo esto en lenguaje claro (yo no programo):

1. EL EVENTO correcto del ciclo de vida para esta regla. Si la regla es IMPEDIR algo, debe ser PreToolUse (ocurre antes y puede bloquear). Si es REACCIONAR a algo ya hecho (formatear, avisar, registrar), debe ser PostToolUse o Notification. Dime cuál eliges y por qué.

2. EL MATCHER exacto (a qué herramientas aplica: Edit|Write, Bash, o vacío para todas) y por qué ese y no otro. Mantenlo lo más ESTRECHO posible: un matcher demasiado amplio dispara el hook donde no debe.

3. EL LUGAR donde debe vivir el settings.json:
   - Si la regla debe cumplirla todo el equipo en este repo → .claude/settings.json (se commitea).
   - Si es solo para mi máquina y todos mis proyectos → ~/.claude/settings.json.
   - Si es local y privada → .claude/settings.local.json.
   Dime cuál y por qué.

4. EL BLOQUE JSON completo, listo para pegar, con el hook ya montado. Si necesita un script aparte (típico en bloqueos con PreToolUse), dame también el script .sh completo y recuérdame hacerlo ejecutable con chmod +x.

5. SI ES UN HOOK DE BLOQUEO: úsalo con exit 2 y un mensaje claro a stderr que me explique por qué se bloqueó, para que tú mismo (Claude) recibas el motivo y te corrijas. No lo hagas silencioso. Y AVÍSAME si esta regla merece además una regla de permisos (permissions.deny) como candado duro, porque un grep en un hook es best-effort y se puede saltar.

6. SEGURIDAD, obligatorio: explícame en una frase QUÉ comando de shell va a correr este hook y confírmame que no hace nada destructivo ni envía datos a ningún lado. Recuérdame que un hook corre shell con mis permisos y que solo debo guardar comandos que entiendo.

7. CÓMO LO PRUEBO: dime cómo verificar que el hook está registrado (el comando /hooks dentro de Claude Code) y una forma de probar que dispara de verdad, sin romper nada real.

Primero muéstrame SOLO el diseño (evento, matcher, lugar), luego el JSON y el script si hace falta, y al final la explicación de seguridad y la prueba. No modifiques mi settings.json todavía: quiero revisar el bloque antes de pegarlo yo.

Fíjate en el patrón: primero diseñas, revisas la seguridad, y tú pegas el bloque. Nunca dejas que un hook aparezca en tu configuración sin haberlo entendido. Es la misma disciplina de dos pasos que protege cualquier automatización potente: la máquina propone, tú apruebas.

10. Los caminos más fáciles · qué haces por chat y qué por archivo

Para que no se te enrede, esto es lo que puedes delegar a la IA por el chat y lo que sigue siendo cosa tuya:

Lo que la IA hace por ti (por el chat)
Escribirte el bloque JSON del hook completo si le describes la regla (la doc oficial lo recomienda explícitamente).
Generarte el script .sh para los hooks de bloqueo, con su jq, su exit 2 y su mensaje a stderr.
Explicarte qué evento y qué matcher encajan con tu regla, y en qué settings.json debe vivir.
Recordarte los pasos de instalación: chmod +x del script, brew install jq si te falta.
Lo que decides y haces TÚ (no lo delegues)
Pegar el bloque en tu settings.json — tras leerlo y entenderlo. La red de seguridad no puede ser código que no revisaste.
Elegir el lugar (repo compartido vs. global vs. local): eso define quién hereda la regla.
Confirmar que el comando del hook es seguro (corre shell con tus permisos: si no lo entiendes, no lo guardas).
Verificar con `/hooks` dentro de Claude Code que quedó registrado, y probar que dispara sin romper nada real.
El truco para verificar
Dentro de Claude Code, escribe `/hooks` para abrir el navegador de hooks: verás todos los configurados agrupados por evento, con su matcher y su comando. Es de solo lectura (para editar, tocas el JSON o le pides a la IA), pero es tu confirmación de que el hook existe y está donde debe. Si no aparece, revisa que el JSON sea válido (nada de comas colgantes ni comentarios) y que el archivo esté en la ruta correcta; a veces basta con reiniciar la sesión para que el file watcher lo recoja.

Resumen · tu checklist de hooks

Antes de dar por montado un hook, confirma
Elegí el evento correcto: PreToolUse para impedir, PostToolUse/Notification para reaccionar.
El matcher es lo más estrecho posible (no dispara donde no debe).
Está en el lugar correcto: repo compartido, global tuyo, o local privado.
Si bloquea, usa `exit 2` con un mensaje claro a stderr para que la IA se corrija — y si es una prohibición dura, la respaldé con una regla de permisos.
Entiendo el comando que corre (shell con mis permisos): no guardé nada que no revisé.
Lo verifiqué con `/hooks` y probé que dispara sin romper nada real.
Saqué la regla de la prosa de mi AGENTS.md y la convertí en algo que pasa siempre.
En NeuralOS · la misma disciplina, a escala de plataforma
Los hooks materializan una idea que en NeuralOS tomamos en serio: la capa donde las reglas críticas no dependen del criterio de nadie porque la propia infraestructura las obliga. Es exactamente lo que hace, por dentro, el gate de advisors de Supabase de la plataforma: antes de sellar cualquier cambio de base de datos, un chequeo automático corre solo y bloquea el merge si algo viola las reglas de seguridad. Nadie tiene que "acordarse" de revisarlo — pasa siempre, como un PreToolUse que veta lo que no debe entrar. Es la misma filosofía de un hook, aplicada a un equipo entero en vez de a una terminal: que la calidad no sea una promesa que alguien recuerda, sino un sensor en la cinta que no se puede saltar. Tú pones la regla una vez; el sistema la cumple para siempre.
El protocolo C-A-R · construir sin bugs
Los hooks son el brazo determinista del C-A-R: donde el protocolo pide disciplina, un hook la vuelve automática. La pareja perfecta para que la calidad no dependa de acordarse.
Loop engineering · la IA trabaja sola hacia la meta
Cuando dejas a la IA iterar sola en un bucle, los hooks son sus frenos y guardarraíles: garantizan que ciertas cosas pasen (o NO pasen) en cada vuelta, sin depender de su criterio.
Documentación oficial · Automate actions with hooks (Anthropic)
La fuente de todo lo de este recurso: los eventos del ciclo de vida, los ejemplos copy-paste y las consideraciones de seguridad. Léela antes de desplegar hooks en un entorno compartido.
#hooks#Claude Code#automatización#ciclo de vida#avanzado#determinismo
¿Listo para construir?

Empieza a construir en
menos de 3 minutos

Únete a 4.200+ creadores. Sin tarjeta. Construye tu primera app con IA en minutos.