Revisada el 2026-10-09 · vigente hasta 2027-01-07
Haz que Claude Code ejecute un script tuyo en un momento fijo de la sesión, siempre y sin depender de que el modelo se acuerde.
El método: en un settings.json declaras qué evento dispara el hook y qué comando corre; el script recibe un JSON por la entrada estándar y responde con su código de salida o con otro JSON.1 A diferencia de una instrucción en CLAUDE.md, que es una petición, un hook es una garantía: salta siempre en su evento.2
Requisitos
- Claude Code instalado.
- Un script ejecutable (bash, Python) y
jqo Python para leer el JSON de entrada. - Tener presente que el hook corre con todos tus permisos de usuario: puede leer, cambiar o borrar lo mismo que tú. Revísalo y pruébalo antes de activarlo.1
Pasos
-
Elige el evento. Los más útiles:1
SessionStart: al empezar o reanudar sesión, y también tras/clearo una compactación. Para cargar contexto que cambia.UserPromptSubmit: al enviar un prompt, antes de que Claude lo procese. Para añadir contexto, validar o bloquear.PreToolUse: antes de usar una herramienta. Puede bloquearla.PostToolUse: después de una herramienta que ha ido bien. Por ejemplo, formatear o pasar el linter.Stop: cuando Claude termina de responder.Notification: cuando Claude Code envía un aviso, por ejemplo porque espera tu permiso.
-
Elige dónde guardarlo.
~/.claude/settings.jsonvale para todos tus proyectos;.claude/settings.json, para uno y se puede subir a git;.claude/settings.local.json, para uno y solo para ti. Los hooks de todos los niveles se suman.1 -
Escribe la entrada con tres niveles: evento, grupo con
matcher(qué herramienta; vacío equivale a todas) y lista de hooks contype,commandy, si quieres,timeouten segundos.1 Este ejemplo oficial avisa en macOS cuando Claude te necesita:3{ "hooks": { "Notification": [ { "matcher": "", "hooks": [ { "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" } ] } ] } }Si ya hay una clave
hooks, añade el evento nuevo a su lado; no sustituyas el objeto entero.3 -
Escribe el script. Recibe por stdin un JSON con, entre otros,
session_id,transcript_path,cwdyhook_event_name; en los eventos de herramientas, además,tool_nameytool_input.1 -
Decide cómo responde:1
- Código 0: todo bien. En
SessionStartyUserPromptSubmit, el texto que imprimas se añade al contexto de Claude. - Código 2: error que bloquea; lo que escribas en stderr le llega a Claude como motivo.
- Otro código: error que no bloquea; la acción sigue.
- JSON por stdout:
systemMessagees un aviso que ves tú yhookSpecificOutput.additionalContext, texto que lee Claude.
- Código 0: todo bien. En
-
Compruébalo con
/hooks, que lista los hooks configurados y su origen. Los cambios en los ajustes se suelen detectar solos; si no aparecen, reinicia la sesión.3 -
Pruébalo a mano: pásale un JSON de ejemplo por tubería (
echo '{...}' | ./mi-hook.sh) y mira el código de salida conecho $?.3
Errores frecuentes
- Un
echosin condición en el perfil de la shell se cuela delante del JSON y Claude Code deja de interpretarlo.3 - Poner
additionalContextfuera dehookSpecificOutput: se ignora sin avisar.3 - Hooks lentos en
UserPromptSubmit: frenan cada prompt. Su tiempo máximo por defecto es de 30 segundos; si se agota, la salida se descarta.1 - Usar
claude -psobre un repositorio ajeno: en ese modo no hay diálogo de confianza y sus hooks se ejecutan sin preguntar.1 - Variables sin comillas y rutas relativas: usa
"$VAR"y rutas absolutas.1
Cómo lo uso
Tengo dos hooks globales en ~/.claude/settings.json, ambos con un tiempo máximo de 10 segundos:
recordatorio-superficie.sh, enSessionStart. Lee elcwddel JSON de entrada, saca el nombre del proyecto y, según una tabla, recuerda qué conviene hacer en local y qué en la web o el móvil. Responde consystemMessage(lo leo yo) yadditionalContext(lo lee Claude).aviso-tokens.sh, enUserPromptSubmit. Leetranscript_path, busca el último registro de uso de tokens y calcula qué parte de la ventana está ocupada. Avisa una sola vez por sesión al 60 % y al 80 %, con un archivo marcador en/tmp. Al 80 % pide a Claude que escriba unhandoff.md. El comando acaba en|| true, así que un fallo nunca bloquea el prompt.- A mi entender, el patrón de responder a la vez con
systemMessageyadditionalContextes el más útil: un mensaje para mí y otro para Claude. - Pendiente:
aviso-tokens.shasume una ventana de 200.000 tokens salvo que se fije la variableCLAUDE_CONTEXT_WINDOW. Con modelos de un millón de tokens (ver ventana de contexto) el porcentaje no es el de la ventana real. A mi entender, hay que decidir si se mide contra la ventana real o se mantiene 200.000 como umbral prudente, y dejarlo escrito en el script.
Véase también
Referencias
Footnotes
-
Hooks reference. Anthropic, documentación de Claude Code. Consultado el 2026-10-09. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Extend Claude Code. Anthropic, documentación de Claude Code. Consultado el 2026-10-09. ↩
-
Automate actions with hooks. Anthropic, documentación de Claude Code. Consultado el 2026-10-09. ↩ ↩2 ↩3 ↩4 ↩5 ↩6