En el post anterior monté la primera skill de verificación, siguiendo el curso Claude Code in Action de Anthropic.
El capítulo de hoy va de los permisos. Lo que te obliga a estar delante de la pantalla para decirle a Claude Code si puede o no hacer eso.
Todo el mundo que usa Claude Code pulsa Shift+Tab. Ves cambiar la barra de estado abajo, ves que ya no te pide confirmación por cada cambio que hace y tiras millas. Pero estaría bien saber primero cuantos modos hay y para que va bien usar cada uno de ellos.
En total, a día de hoy, hay seis modos. Y la diferencia entre ellos no es cuánto te fías de Claude, es qué pasa cuando se equivoca.
Los seis modos
Esta es la lista completa, con el nombre que usan la configuración y el flag --permission-mode.
| Modo | Se ejecuta sin preguntar | Para qué |
|---|---|---|
default (Manual) | Solo lecturas | Empezar, y todo lo delicado |
acceptEdits | Lecturas, ediciones y comandos comunes de ficheros | Iterar sobre código que vas a revisar |
plan | Solo lecturas, investiga y propone | Entender antes de tocar |
auto | Todo, con un clasificador revisando cada acción | Tareas largas sin estar encima |
dontAsk | Solo las herramientas que hayas preaprobado | CI y scripts sin nadie delante |
bypassPermissions | Todo, sin comprobación ninguna | Contenedores y máquinas virtuales |
Los puedes arrancar directamente desde el terminal.
claude --permission-mode plan
O dejarlos fijos en ~/.claude/settings.json para no acordarte cada vez.
{
"permissions": {
"defaultMode": "acceptEdits"
}
}
El ciclo del Shift+Tab por defecto solo recorre tres, que son: manual, accept edits y plan. auto se cuela en el ciclo si tu cuenta cumple los requisitos, bypassPermissions solo aparece si arrancaste la sesión con él activado y dontAsk no aparece nunca, que ese hay que pedirlo por flag.
El modo manual se llama Manual en la interfaz pero su valor de configuración es default, que es su primer nombre heredado. Desde la versión 2.1.200 acepta manual como alias, así que claude --permission-mode manual funciona igual.
Manual o default
Lee sin preguntar y para lo demás te consulta. Cada comando, petición o edición, te va a estar pidiendo confirmación.
La ventaja es evidente, está todo controlado y el riesgo no es tan evidente. Aprobar cosas una a una funciona los primeros diez minutos. Después, harto de todo, empiezas a darle a sí sin leer del todo lo que estás aprobando, y ahí la aprobación manual ya no te está protegiendo de nada, solo te está costando tiempo. Es el modo correcto cuando la sesión toca algo que da miedo y un desgaste inútil cuando estás renombrando variables.
Accept edits
Un Shift+Tab más desde el modo manual y Claude Code creará y editará ficheros dentro de tu directorio de trabajo sin preguntarte, y tú revisas el git diff cuando termina, si quieres claro.
Además de las ediciones, aprueba solo unos cuantos comandos de sistema de ficheros: mkdir, touch, rm, rmdir, mv, cp y sed. Ojo al rm de esa lista, que va incluido. El resto de comandos de bash siguen preguntando.
Lo que hace que este modo sea razonable es que las rutas fuera de tu directorio de trabajo siguen preguntando y hay unas cuantas rutas protegidas que no se aprueban solas ni aquí ni en ningún modo salvo bypass: .git, .claude, .vscode, tu .bashrc, tu .zshrc, .npmrc, .mcp.json y unas cuantas más. Es decir, puede reescribirte medio proyecto pero no puede tocarte la configuración de git ni su propia configuración por su cuenta.
ConsejoSi trabajas en accept edits, ten el árbol de git limpio antes de empezar. Es la diferencia entre revisar un diff y arqueología.
Plan
Plan lee, explora, ejecuta comandos para enterarse de cómo está montado el asunto y escribe un plan. No edita.
Ya hablé de él en el post de sesiones largas, así que aquí solo el detalle que aporta este capítulo. Cuando el plan está listo te ofrece varias salidas, y la que eliges determina en qué modo continúa la sesión. Puedes aprobar y seguir en auto, aprobar y revisar cada edición a mano, o decirle que siga planificando.
Fíjate en lo que implica: aprobar el plan cambia el modo de permisos de la sesión. No es solo un venga, tira.
Auto
En auto, Claude Code ejecuta sin parar, pero antes de cada acción hay un segundo modelo distinto que la revisa. Un clasificador cuyo único trabajo es decidir si eso que va a hacer se sale de lo que le pediste.
Lo que bloquea de serie es bastante concreto, y la lista es larga de verdad. Un par de ejemplos de los que se entienden solos:
- Descargar código y ejecutarlo, el clásico
curl | bash. - Despliegues y migraciones a producción,
terraform destroyy compañía. git reset --hard,git clean -fd,git stash dropy todo lo que presuponga tirar cambios sin commitear.- Enviar datos sensibles a sitios de fuera, o imprimir un token vivo en la conversación.
- Force push.
Y por el otro lado deja pasar sin ruido lo de todos los días: editar ficheros en tu directorio, instalar dependencias declaradas en tu lock, peticiones HTTP de lectura, y hacer push a las ramas del repositorio en el que estás trabajando.
Hay un detalle que me parece de las cosas mejor pensadas de todo esto: los límites que dices en la conversación cuentan como bloqueo. Si en algún momento le escribes no hagas push hasta que yo revise, el clasificador bloquea esa acción aunque sus reglas por defecto la permitieran. Y sigue en pie hasta que tú lo levantes en otro mensaje. Que Claude Code piense que ya se cumple la condición no lo levanta.
El truco no es para siempre porque estos limites no se guardan como regla en ningún sitio. El clasificador los relee del historial cada vez, así que si te comes ese mensaje en una compactación de contexto, el límite desaparece con él. Para algo que tiene que cumplirse siempre, una regla deny en la configuración y a dormir tranquilo.
Lo que el clasificador no puede ver
El clasificador revisa la intención, no si el código funciona. Le pides que refactorice la autenticación, la refactoriza mal y la deja rota. El clasificador lo deja pasar, y hace bien según sus reglas, porque roto no es lo mismo que peligroso. Nadie está intentando desplegar a producción ni borrarte el disco, solo has escrito código malo.
Por eso el capítulo empareja auto con un hook Stop, que se dispara cuando Claude Code termina de responder y ejecuta tus tests.
{
"hooks": {
"Stop": [
{
"hooks": [{ "type": "command", "command": "npm test" }]
}
]
}
}
Si el comando sale con código 2, el hook impide que Claude Code termine y le devuelve por stderr el motivo, así que sigue trabajando en vez de darte por bueno un desastre. Si prefieres tenerlo en un script:
#!/bin/bash
if ! npm test; then
echo "Los tests fallan, no puedes terminar aquí" >&2
exit 2
fi
exit 0
Uno vigila la intención antes de cada acción y el otro comprueba que lo que ha salido funciona cuando ya no queda nada por hacer. Sin el segundo, auto es delegar sin red.
AdvertenciaAuto reduce las interrupciones, no garantiza que nada salga mal. Sirve para tareas donde te fías de la dirección general, no para sustituir la revisión de lo delicado.
Cuando auto se rinde
Si el clasificador bloquea tres acciones seguidas o veinte en total, auto se pausa solo y Claude Code vuelve a preguntarte. Aprobar la acción que había pendiente lo reanuda. Los umbrales no se pueden tocar.
La idea detrás es que tres bloqueos seguidos normalmente no significan que Claude Code se haya vuelto loco, significan que al clasificador le falta contexto sobre tu infraestructura y está frenando cosas legítimas. En vez de dejarte en un bucle de rechazos, te retorna el timón del barco.
El clasificador es por defecto Sonnet 5, no es el modelo que tengas puesto con /model, y sus llamadas cuentan en tu consumo de tokens. Las lecturas y las ediciones dentro del directorio de trabajo se lo saltan, así que lo que pagas de más viene sobre todo de los comandos de shell y de lo que toque la red.
dontAsk: para cuando no hay nadie delante
El planteamiento es lo contrario de auto. En vez de dejar pasar casi todo con un vigilante, deniega automáticamente cualquier cosa que fuese a preguntarte. Solo se ejecuta lo que encaje en tus reglas permissions.allow, los comandos de lectura, y lo que apruebe un hook PreToolUse.
claude --permission-mode dontAsk
Su sitio es el pipeline de CI, el cron de la noche, el proceso automático que nadie está mirando. La alternativa en ese escenario es una sesión colgada esperando una aprobación que no va a llegar nunca, y una pipeline atascada hasta que alguien la mate a mano por la mañana.
Aquí también deniega la herramienta AskUserQuestion, que es la que Claude Code usa para preguntarte cosas. Tiene todo el sentido, porque no hay nadie para responder.
bypassPermissions: dentro de un contenedor o en ningún sitio
Es el equivalente al --dangerously-skip-permissions. Se salta las comprobaciones, ejecuta todo al momento y sí incluye las rutas protegidas que mencionaba antes.
claude --permission-mode bypassPermissions
No puedes entrar desde una sesión que no arrancó con él, tiene que estar activado desde el principio. La primera vez te sale un diálogo pidiéndote que aceptes la responsabilidad, y si dices que no, se cierra. En Linux y macOS directamente se niega a arrancar si eres root o vas por sudo:
--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons
Queda un único freno puesto, un cortocircuito contra el error tonto: los borrados que apuntan a la raíz del sistema de ficheros o a tu home, tipo rm -rf / o rm -rf ~, siguen preguntando incluso aquí.
Lo demás, no. Contra una inyección de prompt en este modo no tienes absolutamente nada para defenderte. Si has llegado hasta aquí buscando velocidad, lo que quieres es auto, que hace el mismo trabajo con un clasificador delante.
Cómo se trabaja con esto de verdad
Los seis modos existen, pero en un equipo que trabaja normal no se usan los seis. El reparto acaba siendo bastante estable.
El día a día vive entre plan y accept edits. Tarea que toca varios archivos o que todavía no tienes clara, arrancas en plan, lees lo que propone, y al aprobar el plan la sesión cae en accept edits para que trabaje mientras tú miras otra cosa. Al terminar, git diff y a revisar. La red de seguridad aquí no es el modo, es que el árbol estaba limpio antes de empezar.
Auto entra cuando la tarea es larga y repetitiva y sabes que vas a estar veinte minutos aprobando cosas parecidas. Migrar un patrón por cuarenta archivos, arreglar una batería de tests. Y entra acompañado del hook que ejecuta la verificación, que sin eso lo que has montado es una máquina de generar diffs sin revisar.
dontAsk no se elige a mano casi nunca, se configura una vez en el CI y ya no lo vuelves a ver.
Y bypassPermissions es de contenedor. No es una opinión moralista, es que hay flags para admitirlo (--allow-dangerously-skip-permissions lo deja disponible sin activarlo) y un ajuste de administrador para prohibirlo en toda la organización precisamente porque a nadie le hace gracia que ande suelto por los portátiles del equipo.
La pregunta útil cuando dudes entre dos modos no es cuánto te fías. Es qué pasa si esta sesión sale mal, y si la respuesta es pues miro el diff y hago git checkout, aflójalo sin miedo. Si la respuesta empieza por depende de si había tocado…, ya sabes que ese día toca manual.
EA! Nos vemos en los bares! 🍻