Qué es y por qué importa
El vídeo hablaba de Jev: una IA que no escribe texto, sino que responde con un tipo concreto, o sea una elección, una puntuación o un verdadero/falso, con las probabilidades y lo segura que está. Qué hacer con la respuesta lo decide tu código. De momento hay una lista de espera. Aquí me interesa una sola idea: un control que se pone entre la IA y el comando, antes de que el comando se ejecute. Eso tu Claude Code ya puede tenerlo hoy, sin esperar en ninguna lista.
El problema es sencillo. Claude Code ejecuta comandos en el terminal de tu ordenador. Casi siempre son inofensivos: instala un paquete, lanza los tests, lee un archivo. Pero algunos no se pueden deshacer. rm -rf borra una carpeta con todo lo que tiene dentro, sin pasar por la papelera. git push --force sobrescribe el historial del proyecto en línea. git reset --hard tira los cambios que todavía no has guardado en un commit. Un drop table borra una tabla de la base de datos.
No hace falta que Claude se equivoque a propósito. Basta una instrucción mal entendida, una ruta equivocada, una sesión larga en la que se ha liado. Y si apruebas las confirmaciones deprisa, o las has reducido para ir más rápido, el momento en que podías decir que no pasa sin que te des cuenta.
Hay otra cosa que conviene saber. El rewind de Claude Code (Esc dos veces, o /rewind) deshace los cambios hechos con sus herramientas de archivos, pero no los que hacen los comandos en el terminal. Si un rm borra un archivo, el rewind no te lo devuelve.
Así que el freno hay que ponerlo antes. Dos formas: una lista de comandos prohibidos, la sencilla, y un pequeño script que lee cada comando antes de que se ejecute, la más lista. Luego está el prompt para que las haga Claude.
1. La lista de comandos prohibidos
Claude Code lee los ajustes del proyecto del archivo .claude/settings.json, en la carpeta del proyecto. Si quieres las mismas reglas en todos los proyectos, usa ~/.claude/settings.json en tu carpeta de usuario. Dentro escribe esto:
{
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(git reset --hard *)"
]
}
}Un «deny» gana siempre a cualquier permiso que hayas dado. Claude Code mira primero las reglas deny, luego las que piden confirmación y luego las que permiten. Así que aunque un día respondieras «sí, no me lo vuelvas a preguntar» a un comando, el deny sigue siendo más fuerte. Y vale en todos los modos de permiso, también en bypassPermissions.
El límite: la regla bloquea el comando escrito así, no sus variantes. Bash(rm -rf *) para rm -rf build/, pero no el mismo comando dentro de bash -c, o escrito como /bin/rm -rf build/. También rm -fr, con las letras al revés, pasa. Es una red, no un muro.
2. El guardián: un hook que revisa cada comando
Un hook es un script que Claude Code lanza solo en un momento concreto. El que nos hace falta se llama PreToolUse: se ejecuta antes de cada llamada a una herramienta, y con el filtro «Bash» solo mira los comandos del terminal. Recibe el comando en JSON. Si el script sale con código 2, el comando no se ejecuta y Claude lee el motivo que has escrito. Si sale con 0, el comando sigue con los permisos normales.
La ventaja frente a la lista: el script busca las palabras peligrosas en todo el texto del comando. Así que también pilla un rm -rf escondido dentro de bash -c.
Crea el archivo .claude/hooks/guardian.sh en el proyecto y pega esto dentro:
#!/bin/bash
command -v jq >/dev/null || { echo "hace falta jq" >&2; exit 2; }
CMD=$(jq -r '.tool_input.command')
if echo "$CMD" | grep -Eiq 'rm -rf|git push --force|git reset --hard|drop table'; then
echo "Bloqueado: comando destructivo. Pídeme permiso primero." >&2
exit 2
fi
exit 0Hazlo ejecutable con chmod +x .claude/hooks/guardian.sh. El script usa jq para leer el JSON: si no lo tienes, en el Mac lo instalas con brew install jq. Si falta, la primera línea del script bloquea todos los comandos en vez de dejarlos pasar.
Luego añade en .claude/settings.json, junto a «permissions», esta parte:
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guardian.sh" }]
}
]
}$CLAUDE_PROJECT_DIR indica la carpeta del proyecto, y las comillas de alrededor mantienen la ruta entera aunque tenga espacios. Juntas, las dos partes dan un archivo así:
{
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(git reset --hard *)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guardian.sh" }]
}
]
}
}La lista del script la amplías tú: pon los comandos que en tu proyecto hacen daño, por ejemplo el que vacía la base de datos o el script que publica la app.
3. Si no te apetece hacerlo a mano
Puedes pedirle a Claude que lo haga todo: el script, el archivo de ajustes y la prueba. Escríbele:
Configura en .claude/settings.json un hook PreToolUse que bloquee los comandos destructivos antes de que se ejecuten (rm -rf, git push --force, git reset --hard, drop table) y añade las mismas reglas a la lista deny de los permisos. Luego crea una carpeta vacía de prueba y comprueba que rm -rf sobre ella queda bloqueado.
Cuando termine, lee tú el archivo .claude/settings.json y el script. Son pocas líneas. Si algo no te cuadra, pide que te lo explique:
Enséñame el contenido de .claude/settings.json y del script del hook, y explícame línea por línea qué bloquea y qué deja pasar.
4. La prueba
Una regla que no has probado es una regla que esperas que funcione. Escribe /hooks en Claude Code: se abre la lista de hooks configurados, y el tuyo tiene que aparecer bajo PreToolUse. Normalmente Claude Code lee enseguida los cambios en el archivo de ajustes. Si tu hook no aparece, cierra y vuelve a abrir Claude Code.
Ojo con un detalle: con el deny activo, un rm -rf escrito normal ya lo para la lista. Para ver si el guardián funciona por sí solo, pídele a Claude el mismo comando dentro de bash -c: la lista no lo ve, el guardián sí.
Crea una carpeta vacía llamada prueba-guardian e intenta borrarla con bash -c 'rm -rf prueba-guardian'. Luego dime qué te ha parado: la lista deny o el hook.
Si el comando pasa, el guardián no está funcionando: normalmente el script no es ejecutable o la ruta en settings.json está mal, y en esos casos Claude Code no recibe el código 2 y deja seguir el comando. Si en cambio se bloquea todo, hasta un simple ls, y el motivo es «hace falta jq», falta jq.
5. La red de debajo: git
El guardián reduce el riesgo, no lo elimina. Las variantes de un comando son muchas y no las vas a prever todas. Por eso la verdadera red de debajo es git: haz un commit antes de darle a Claude un trabajo largo, y ten una copia del proyecto también en línea, por ejemplo en GitHub. Si algo sale mal, vuelves al último commit.
Y el modo bypassPermissions, el que se salta las peticiones de confirmación, la documentación de Claude Code lo recomienda solo en entornos aislados, como un contenedor o una máquina virtual. No en el ordenador donde lo tienes todo.
Errores comunes
- Sobrescribir el settings.json que ya había: añade las partes nuevas a lo que hay y revisa las comas, porque basta una coma que falte para romper el archivo.
- Pensar que el deny cubre todas las variantes: bloquea el comando escrito así, así que ponle al lado el guardián que lee todo el texto del comando.
- Olvidar chmod +x: el script no arranca y el guardián no bloquea nada sin avisarte, así que haz siempre la prueba con una carpeta vacía.
- Fiarse del rewind para los archivos borrados: el rewind no deshace los comandos del terminal, así que haz un commit antes de los trabajos largos.
Lista de comprobación
- Reglas deny en .claude/settings.json
- Script guardián creado y hecho ejecutable
- jq instalado
- Hook visible en /hooks bajo PreToolUse
- Prueba con una carpeta vacía: comando bloqueado
- Commit hecho antes de los trabajos largos
Preguntas frecuentes
¿Claude Code no pide ya permiso antes de los comandos?
En el modo Manual, sí: pregunta antes de cada comando que no sea de solo lectura. Pero si respondes «sí, no me lo vuelvas a preguntar», o trabajas en un modo que pregunta menos, esa confirmación desaparece. El deny y el guardián, en cambio, siguen activos también ahí.
¿Qué es mejor, la lista deny o el hook?
Las dos cosas. El deny son tres líneas y no necesita nada más. El hook lee todo el texto del comando y pilla las variantes más comunes. Uno tapa los huecos del otro.
¿El guardián puede bloquear también comandos inofensivos?
Sí: si un comando contiene esas palabras, por ejemplo una búsqueda de texto con «rm -rf» dentro, se para. No pasa nada: Claude lee el motivo y te pregunta cómo seguir. Si pasa a menudo, haz la lista más precisa.
¿Vale para todos mis proyectos?
En .claude/settings.json vale para ese proyecto, y si el archivo está en git vale también para quien trabaja en él contigo. En ~/.claude/settings.json vale para todos tus proyectos: en ese caso pon el script en ~/.claude/hooks y escribe esa ruta en el comando del hook.