Hooks contra alucinaciones
Siete hooks concretos de Claude Code que impiden que el modelo invente cosas, rompa convenciones o ejecute comandos destructivos.
Las alucinaciones no son solo un problema de modelo, son un problema de herramienta. Cuando Claude Code edita ficheros sin haberlos leído antes, o cuando se atreve con git push --force en main porque lo mencionaste una vez en una conversación temprana, esas son consecuencias de alucinación que puedes evitar con hooks.
Siete hooks que usamos en StudioMeyer. Todos copy-paste, activables individualmente. No necesitas un sistema de plugins, todo va por ~/.claude/settings.json y pequeños scripts bash en ~/.claude/hooks/.
Estado abril 2026, todos los hooks probados en Claude Code 2.1.x.
1. Read-before-Edit Guard
El problema: Claude Code a veces edita ficheros sin haberlos visto antes con la tool Read. Stella Laurenzo (AMD AI Director) mostró en 6852 sesiones que la ratio Read-a-Edit cayó de 6.6 a 2.0, con 33.7 por ciento de blind edits. Eso lleva a ficheros que se rompen porque el modelo no conocía la estructura existente.
La solución: hook PreToolUse que bloquea Edit/Write si el fichero objetivo no se cargó vía Read en la sesión. Bypass con env var CLAUDE_SKIP_READ_BEFORE_EDIT=1 para emergencias.
En ~/.claude/hooks/read-before-edit.sh (patrón ver docs StudioMeyer en ~/.claude/CLAUDE.md). En ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/read-before-edit.sh" }]
}
]
}
}
Efecto: el modelo TIENE que llamar Read antes de editar. Edits por alucinación van a cero.
2. Bash Safety Guard
El problema: Claude Code conoce comandos bash destructivos y puede ejecutarlos bajo ciertos prompts. rm -rf /, git push --force en main, prisma db push --force-reset, DROP DATABASE son las trampas más comunes.
La solución: hook PreToolUse que implementa una allowlist/blocklist dura sobre comandos bash. En el script:
#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')
if echo "$cmd" | grep -qE 'rm -rf /(\s|$)|git push.*--force.*(main|master)|prisma db push.*--force-reset|prisma migrate reset|DROP DATABASE'; then
echo "BLOCKED: destructive command pattern" >&2
exit 2
fi
exit 0
En settings.json extiende el mismo bloque PreToolUse con "matcher": "Bash". Efecto: incluso si Claude cree que necesita un force-push, no pasa.
3. Sender-Reputation Guard para mails
El problema: cuando envías mails de prueba vía SMTP/Brevo/Mailgun y el destinatario tiene +-tag en un dominio que rechaza plus-addressing (Yahoo, Outlook, GMX, propio MX), generas hard bounces. Seis hard bounces en una sesión, reputación de sender rota, todos los mails al spam.
La solución: hook PreToolUse que bloquea comandos bash mail-intent (curl a Brevo, sendmail, swaks) cuando el destinatario matchea un patrón peligroso.
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')
if echo "$cmd" | grep -qE 'curl.*api.brevo.com|sendmail|swaks'; then
if echo "$cmd" | grep -qE '\+\w+@(yahoo|outlook|hotmail|gmx|t-online|aol)\.[a-z]{2,3}'; then
echo "BLOCKED: +tag plus-addressing on hard-rejecting provider. Use MAIL_TEST_OK=1 to bypass." >&2
exit 2
fi
fi
exit 0
4. n8n Webhook Side-Effect Guard
El problema: los webhooks n8n suelen tener side-effects pesados. Un simple curl https://n8n.studiomeyer.io/webhook/signup triggea de verdad un envío de welcome mail porque en el workflow hay un nodo Brevo Send. Costó cinco hard bounces en una sesión en abril 2026.
La solución: hook PreToolUse que bloquea cada request POST a n8n.studiomeyer.io/webhook/*. Inspection vía GET a /api/v1/workflows/{id} se mantiene permitida.
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')
if echo "$cmd" | grep -qE 'curl.*-X *POST.*n8n\.studiomeyer\.io/webhook'; then
echo "BLOCKED: n8n webhook POST. Inspect workflow first via /api/v1/workflows/{id}. Bypass with N8N_TEST_OK=1." >&2
exit 2
fi
5. Reindex-after-Edit Reminder
El problema: editas ficheros de código, pero el codebase-memory-graph (codebase-memory-mcp) no se reindexa automáticamente. Llamadas a tools posteriores devuelven datos obsoletos y el modelo decide sobre base equivocada.
La solución: hook PostToolUse que tras Edit/Write en ficheros de código (.ts, .tsx, .js, .jsx) deja un recordatorio de reindex en el output.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [{ "type": "command", "command": "echo 'Reminder: index_repository tras cambio de código'" }]
}
]
}
}
Es más blando que un block: recordatorio en output, sin stop. Funciona igual porque el modelo ve la lista de recordatorios en su contexto.
6. SessionStart Reminder para Memory + Codebase
El problema: las sesiones nuevas arrancan sin contexto de memoria y sin index del codebase. El modelo empieza a adivinar en lugar de mirar.
La solución: hook SessionStart que emite un recordatorio:
{
"hooks": {
"SessionStart": [
{
"hooks": [{
"type": "command",
"command": "echo 'OBLIGATORIO: llama nex_session_start + nex_proactive. En trabajo de código: index_repository + get_architecture.'"
}]
}
]
}
}
El output del hook aterriza automáticamente en el contexto del sistema del primer mensaje del usuario. El modelo lo ve antes de cada respuesta.
7. PreCompact Memory-Snapshot Reminder
El problema: cuando Claude Code hace auto-compact del contexto (en sesiones largas), se pierden detalles que aún no se han escrito en memoria. Si luego preguntas "qué tratamos", solo te llega lo que estaba en el compact summary.
La solución: hook PreCompact que recuerda al modelo justo antes del compact hacer un nex_summarize para que el conocimiento actual aterrice en memoria antes de que el contexto se reduzca.
{
"hooks": {
"PreCompact": [
{
"hooks": [{
"type": "command",
"command": "echo 'Antes de compact: llama nex_summarize para que las decisions/learnings actuales aterricen en memoria.'"
}]
}
]
}
}
Auto Mode en vez de --dangerously-skip-permissions
Con Claude Code v2.1.118, --dangerously-skip-permissions está prácticamente muerto porque hay un reemplazo mucho mejor: Auto Mode. En vez de aceptar ciegamente cada permission, Claude Code enruta cada permission request por un classifier de Sonnet-4.6 que distingue entre "inofensivo" (Read, Glob, el séptimo git status) y "potencialmente caro" (Bash con rm, llamada a API externa, fichero en ~/.ssh/). Los inofensivos se aprueban silenciosamente, el resto cae en el prompt del usuario como siempre.
En ~/.claude/settings.json:
{
"autoMode": {
"enabled": true,
"classifier": "claude-sonnet-4-6"
}
}
Esto reemplaza el flag --dangerously-skip-permissions para el 90 por ciento de los casos. Importante: el classifier no es perfecto, no te confíes para rutas críticas de verdad. Además: Auto Mode cuesta un poco (calls a Sonnet), pero en Max Plan es flat-rate.
Para CI runs o routines no supervisadas donde realmente no hay usuario para aprobar, --dangerously-skip-permissions sigue disponible. Pero para uso diario, Auto Mode es el default mejor.
Orden de activación
Si montas estos siete hooks de cero, este orden:
- Read-before-Edit Guard (ya, máximo impacto)
- Bash Safety Guard (ya, protege ante catástrofes)
- Sender-Reputation + n8n Webhook Guards (si triggeras mails o workflows)
- SessionStart + PreCompact Reminders (quality-of-life, sin riesgo)
- Reindex Reminder (si usas codebase-memory-mcp productivamente)
Cada hook es aislado, no necesitas todos. Pero 1 y 2 son los que sinceramente no me quito.
Dónde están los scripts reales
Los snippets aquí están reducidos didácticamente. Las versiones de producción van en tu propio setup, mejor documentadas en tu ~/.claude/CLAUDE.md (sección "Claude Code Hooks") y activadas en tu ~/.claude/settings.json.
Qué tienes después
Siete hooks que juntos impiden que Claude Code rompa ficheros, ejecute comandos destructivos, lance mails al aire o use datos obsoletos del codebase. Setup unos 30 minutos copy-paste, una hora si ajustas cada hook. Las primeras semanas necesitarás algunos bypasses cuando bloquees casos legítimos, lo afinas iterativamente.
No desaparecen todas las alucinaciones. Pero las más comunes y caras quedan capturadas.