← Claude Code Hub
✦ Tip #151 Jul 31, 2026

--dangerously-skip-permissions en Claude Code: por qué tu script acaba en verde sin haber hecho nada

Tu job de CI llama a `claude -p`, termina con exit 0 y el commit no está. Nadie te avisó de nada, y por eso medio internet acaba pegando `--dangerously-skip-permissions` en el pipeline.

Comparativa en Claude Code headless: a la izquierda lo que devuelve la ejecucion (exit code 0, subtype success, is_error false) en verde, a la derecha lo que paso de verdad (permission_denials 2, el fichero no existe) en rojo, y abajo las tres salidas ordenadas de mejor a peor: allowedTools, permission-mode dontAsk y dangerously-skip-permissions

TL;DR En headless, un permiso denegado no rompe la ejecución. claude -p devuelve exit code 0, "subtype": "success" y "is_error": false aunque Claude no haya tocado un solo fichero. La única huella está en el array permission_denials del JSON, que nadie mira. Léelo y falla el build tú mismo. Y para que Claude sí pueda trabajar, --allowedTools (di exactamente qué puede hacer) o --permission-mode dontAsk (deniega rápido, sin reintentos) antes que el --dangerously-skip-permissions al que llega todo el mundo.

Tu job de CI llama a claude -p, termina en verde, y el commit no está. No hay error, no hay aviso, no hay nada. Lo miras dos veces, no entiendes nada, y acabas donde acaba medio internet: pegando --dangerously-skip-permissions en el pipeline para que "deje de dar problemas".

El problema es que nunca dio problemas. Dio silencio.

Lo que ves, y lo que pasó de verdad

Lancé esto en un repo limpio, en modo Manual, con un comando que no está en mis reglas allow:

claude -p "Run this exact shell command and nothing else: touch ./needsperm.txt" \
  --permission-mode default --output-format json

Lo que devuelve la ejecución:

EXIT CODE : 0
subtype   : success
is_error  : False
denials   : 2  ['Bash', 'Bash']
fichero   : NO creado

Exit 0. success. is_error: false. Y el fichero no existe. Claude lo intentó dos veces, el sistema de permisos lo denegó las dos, y la ejecución terminó declarándose un éxito.

En una sesión interactiva esto no te pasa: aparece el diálogo de permisos y pulsas. Con -p no hay nadie a quien preguntar, así que la llamada se deniega y Claude sigue adelante con lo que le queda. Desde fuera, una ejecución que no pudo hacer su trabajo y una que lo hizo entero son indistinguibles.

Cómo detectarlo, que es lo primero

El dato está ahí, solo que fuera del sitio donde miras. Con --output-format json, cada denegación se apunta en permission_denials:

out=$(claude -p "$PROMPT" --output-format json)
denied=$(printf '%s' "$out" | jq '.permission_denials | length')

if [ "$denied" -gt 0 ]; then
  echo "Claude fue bloqueado $denied veces:"
  printf '%s' "$out" | jq -r '.permission_denials[] |
    "  \(.tool_name): \(.tool_input.command // .tool_input.file_path // "?")"'
  exit 1
fi

Contra la ejecución de arriba, eso imprime:

Claude fue bloqueado 2 veces:
  Bash: touch ./needsperm.txt
  Bash: touch ./needsperm.txt

Ponlo en el job y tu pipeline deja de mentirte. Esto es lo que vale la pena copiar aunque no cambies nada más.

Y usa printf '%s', no echo. El JSON lleva \n dentro de las cadenas y zsh (el shell por defecto de macOS) los convierte en saltos de línea reales, así que echo "$out" | jq te devuelve un parse error que parece un fallo de Claude Code y es tuyo. En bash funciona, que es justo lo que hace que cueste tanto encontrarlo.

Las cuatro salidas, de mejor a peor

Opción Qué hace Para qué sirve
--allowedTools Preaprueba exactamente lo que puede ejecutar CI donde sabes qué va a hacer Claude
--permission-mode dontAsk Deniega todo lo que pediría permiso, sin esperar Pipelines cerrados y entornos restringidos
--permission-mode auto Un clasificador aparte revisa cada acción Tareas largas donde no puedes enumerarlo todo
--dangerously-skip-permissions Se salta las comprobaciones Contenedores y VMs aisladas, y punto

1. --allowedTools, la que deberías usar por defecto

Le dices qué puede hacer y lo hace, sin diálogos y sin abrir la puerta a nada más:

claude -p "corrige los errores de lint" \
  --allowedTools "Read" "Edit" "Bash(npm run lint*)"

Comprobado en la misma prueba de antes: con la regla puesta, el comando se ejecuta y el fichero aparece.

2. --permission-mode dontAsk, cuando prefieres el portazo

Deniega de golpe todo lo que hubiera pedido permiso, y solo deja pasar tus reglas allow, los comandos de solo lectura y lo que apruebe un hook PreToolUse. La documentación lo describe para pipelines de CI y entornos restringidos, y la clave está en esta frase: "the session never waits for input".

La diferencia práctica con el modo Manual es el ruido. En mi prueba, Manual gastó 3 turnos reintentando el comando denegado; dontAsk lo cortó en 2 y sin reintentos.

3. --permission-mode auto, con un tope que conviene conocer

El clasificador de auto mode revisa cada acción en vez de preguntarte. Funciona bien, pero en headless tiene un final: si bloquea 3 veces seguidas o 20 en total, la sesión se aborta, porque no hay nadie a quien pasarle el turno. Ese es el error que verás:

Agent aborted: too many classifier denials in headless mode

4. --dangerously-skip-permissions, la que casi nunca es la respuesta

Es exactamente lo mismo que --permission-mode bypassPermissions. Y hay un detalle que dice bastante: el clasificador de auto mode bloquea por defecto lanzar un agente autónomo sin aprobación ni sandbox, y nombra esta flag como ejemplo. Claude Code frena cuando Claude Code intenta usarla.

Lo que esa flag no se salta (aunque lo parezca)

Aquí hay más matiz del que sugiere el nombre. Ni en modo bypass se saltan:

  • Tus reglas ask explícitas, que siguen abriendo diálogo
  • Las herramientas de conector que tu organización puso en ask
  • Las herramientas MCP marcadas como requiresUserInteraction
  • rm -rf / y rm -rf ~, que siguen preguntando como cortacircuitos, incluso metidos dentro de $(...), de comillas invertidas o de <(...)

Y dos negativas que te van a morder si automatizas:

--dangerously-skip-permissions cannot be used with root/sudo privileges
for security reasons

En Linux y macOS se niega a arrancar como root o bajo sudo, salvo dentro de un sandbox reconocido. Y una sesión en background con --bg no arranca en este modo hasta que hayas aceptado el diálogo de responsabilidad una vez en una sesión interactiva. Un contenedor recién creado no lo ha aceptado nunca.

Referencia

Modo en headless Qué pasa cuando algo pediría permiso
default (Manual) Se deniega, la ejecución continúa y termina en success
acceptEdits Pasan las ediciones y los comandos de fichero comunes (touch sí, chmod no); el resto se deniega igual de callado
dontAsk Se deniega inmediatamente, sin reintentos ni espera
auto Decide el clasificador; se aborta a los 3 bloqueos seguidos o 20 en total
bypassPermissions Se ejecuta, salvo las excepciones de la lista de arriba

Si lo tuyo es la sesión interactiva y no el pipeline, el mapa es otro: los 6 modos de permisos con Shift+Tab para el día a día, el sandbox para ejecutar sin diálogos con red y disco acotados, y montar a Claude como agente autónomo si lo que quieres es dejarlo trabajando de madrugada.

Documentación oficial: Permission modes · Non-interactive mode · CLI reference

Requisitos: --permission-mode dontAsk y el resto de valores están en Claude Code v2.1.x; el alias manual para default pide v2.1.200 o superior. Las ejecuciones de este tip las hice en v2.1.220. Los topes del clasificador, el cortacircuitos de rm -rf y las dos negativas de arranque salen de la documentación vigente, no de mis pruebas.

Guía gratuita

Los 51 esenciales, en PDF.

Una página por tip. Cinco capítulos. Lo que de verdad uso a diario en producción — sin teoría, sin humo.

  • I. Empieza bien 10 tips
  • II. Conciencia 3 tips
  • III. Maestría 22 tips
  • IV. Autonomía 10 tips
  • V. Comparativa 6 tips
¿Eres desarrollador/a Web profesional?

Recibirás la guía por email · Te unes a la newsletter Gravitas · Cancela cuando quieras

de 51
#

Wmedia · 51 Tips
Guía gratuita · 51 tips · 5 capítulos

Los 51 esenciales, en PDF.

¿Eres desarrollador/a Web profesional? · Cancela cuando quieras