Si metes varios sitios en un repositorio y colocas reglas para la IA (CLAUDE.md o AGENTS.md) en la carpeta de cada sitio, la IA seguirá las reglas de ese sitio: eso es lo que uno tiende a suponer, pero ni Claude Code ni Codex «siempre leen» las reglas de las carpetas inferiores. Si inicias desde la raíz del repositorio, Claude Code no las carga hasta que toca archivos de esa carpeta, y Codex no las carga automáticamente (la IA puede abrirlas por su cuenta, pero no hay garantía). Este artículo compara, punto por punto y a partir de la documentación oficial de ambas herramientas, cuándo se cargan estos archivos y cómo comprobar si se cargaron, y después muestra cómo hacer cumplir las reglas con comprobaciones automáticas en lugar de documentos. Surge de lo que aprendimos al diseñar esta organización en un entorno donde agentes de IA se encargan de la operación de servidores y de varios proyectos.

¿Cuándo se cargan las reglas de la carpeta de cada sitio? (al iniciar desde la raíz del repositorio)

repo/ ├─ CLAUDE.md, AGENTS.md ← reglas de todo el repositorio └─ sites/ ├─ blog/CLAUDE.md, AGENTS.md ← reglas de blog ├─ shop/CLAUDE.md, AGENTS.md ← reglas de shop └─ shared/ ← componentes compartidos

Claude Code

  • Al iniciarEl CLAUDE.md de la raíz
  • Al tocarCarga el CLAUDE.md de blog cuando lee, escribe o edita un archivo de sites/blog/
  • Aún noLas reglas de una carpeta que todavía no ha tocado (shop) no están cargadas

Codex

  • Al iniciarEl AGENTS.md de la raíz
  • Sin garantíaEl AGENTS.md de sites/blog/ no se carga automáticamente (Codex no busca por debajo de la carpeta desde la que se inició)
  • Sin garantíaEl AGENTS.md de sites/shop/ (igual)

Por eso, inicia el trabajo de un sitio desde la carpeta de ese sitio y no confíes en documentos para lo que deba cumplirse sí o sí. Ejecuta una comprobación automática que «detenga el despliegue si cambió algo fuera de la carpeta asignada» y define el alcance de cada agente con un ajuste por worktree. Mantén los documentos de reglas para explicar a la IA los motivos y los pasos.

Fuentes: How Claude remembers your project de Anthropic y Custom instructions with AGENTS.md de OpenAI (ambas consultadas el 1 de noviembre de 2026).

1. Lo que aprendimos al poner reglas en la carpeta de cada sitio

En un entorno donde agentes de IA se encargan de la operación de servidores y de varios sitios, planteamos un diseño que mete varios sitios en un repositorio y coloca las reglas de cada sitio en su carpeta (se omiten los detalles que permitirían identificar lugares o nombres, y el contenido técnico está generalizado). El objetivo era un reparto de tareas: la IA asignada a blog lee solo las reglas de blog y nunca toca shop.

Pero al revisar la documentación oficial de ambas herramientas, vimos que no había garantía de que las reglas colocadas se cargaran antes de empezar a trabajar. Qué reglas se cargan depende de la carpeta desde la que se inicie. Además, la documentación de Claude Code describe CLAUDE.md como contexto, no como una configuración que se imponga. Aunque las reglas se carguen, nada garantiza que se cumplan.

  1. !

    Colocar reglas en carpetas no basta para repartir responsabilidades

    Riesgo
    Una IA iniciada en la raíz cambia archivos sin haber leído las reglas de ese sitio, o antes de leerlas
    Solución
    Inicia el trabajo de un sitio desde su carpeta y detén los cambios fuera del alcance con una comprobación en el despliegue (sección 4)
    Verificar
    Usa las herramientas para confirmar qué reglas se cargaron (sección 3) y cambia a propósito algo fuera del alcance para ver si el despliegue se detiene

Las causas generales por las que la IA ignora las reglas, y sus soluciones, se tratan en «Por qué la IA ignora las reglas: revisa CLAUDE.md, Cursor Rules y AGENTS.md». Este artículo se centra en lo que ocurre cuando repartes las reglas en varias carpetas. Otras dos precauciones del mismo entorno, sobre confiar varios repositorios a una IA, están en la sección 5.

2. ¿Cuándo se cargan las reglas de cada carpeta?

Que se carguen o no las reglas de la carpeta de cada sitio depende de desde qué carpeta inicias y de qué herramienta usas. Esto es lo que dice la documentación oficial de ambas herramientas, punto por punto.

PuntoClaude CodeCodex
Qué se carga al iniciarTodos los CLAUDE.md y CLAUDE.local.md de la carpeta de inicio (launch directory) y de todas las carpetas superioresDesde la raíz del proyecto (project root, normalmente la raíz de git) hasta la carpeta de inicio, un archivo por carpeta: AGENTS.override.md o, si no existe, AGENTS.md
Por debajo de la carpeta de inicioNo se carga al iniciar; se carga cuando Claude lee, escribe o edita otro archivo de esa carpetaNo se carga automáticamente (la búsqueda termina en la carpeta de inicio; la IA puede abrirlo por su cuenta)
¿Se añaden durante la sesión?Sí (las reglas de las carpetas que toca se añaden después)No (se arman una sola vez al comienzo de cada ejecución)
Límites de tamañoLa pauta es menos de 200 líneas por archivo (cuanto más largo, menos fiable es que se siga); en los CLAUDE.md de carpetas inferiores, lo que pase de 40 000 caracteres por archivo (con un contexto de 200 000 tokens) se corta y solo se pasa el principioNo se añade nada una vez que el total supera 32 KiB (el valor predeterminado de project_doc_max_bytes)
El archivo de reglas de la otra herramientaLee AGENTS.md cuando no hay CLAUDE.md, .claude/CLAUDE.md ni CLAUDE.local.md en la carpeta de inicio ni por encima (predeterminado)No lee CLAUDE.md (solo lee los nombres añadidos a project_doc_fallback_filenames)

Fuentes: How Claude remembers your project y Monorepos and large repos de Anthropic, y Custom instructions with AGENTS.md de OpenAI (consultadas el 1 de noviembre de 2026). El límite de Claude Code para carpetas inferiores se aplica desde la v2.1.309. Con un contexto de 1 millón de tokens, es de 150 000 caracteres (200 000 en Opus 4.6 y Sonnet 4.6). Claude Code lee AGENTS.md directamente desde la v2.1.277; el AGENTS.md de una carpeta inferior se lee cuando esa carpeta no tiene CLAUDE.md y Claude abre un archivo de ella con la herramienta Read. Para que lea ambos, ajusta Project instructions en /config a claude-md-and-agents-md.

El lugar desde el que inicias cambia qué reglas se cargan

Incluso en el mismo repositorio, el resultado depende de dónde inicies. Si inicias desde la carpeta de un sitio, ambas herramientas leen las reglas de ese sitio desde el principio.

Iniciar desdeClaude CodeCodex
La raíz del repositorioSolo las reglas de la raíz; las reglas de cada sitio se añaden cuando Claude toca archivos de ese sitioSolo las reglas de la raíz; las reglas de los sitios no se cargan automáticamente
sites/blog/Lee al iniciar las reglas de blog y de la raíz (editar archivos fuera de la carpeta de inicio pide aprobación)Lee la raíz y después blog; las reglas de shop no están en el camino, así que no se cargan automáticamente

Lo que es fácil pasar por alto es qué cuenta como «tocar» en «se carga al tocar». Lo que la documentación de Claude Code cuenta como lectura es leer, escribir o editar un archivo con sus herramientas, además de los comandos que muestran un solo archivo, como cat o head. Las operaciones que cambian archivos de otras maneras, como un buscar y reemplazar masivo en las carpetas de varios sitios, no figuran en esa lista. Los archivos de un sitio pueden cambiar antes de que se lean sus reglas.

En Codex, si inicias desde la raíz del repositorio y le pides «arregla blog y shop», no se carga automáticamente el AGENTS.md de ninguno de los dos sitios. La documentación dice que Codex deja de buscar al llegar a la carpeta de trabajo actual, así que las reglas de una carpeta inferior solo se incluyen con seguridad al iniciar cuando inicias desde esa carpeta o desde una inferior.

Dicho esto, las instrucciones predeterminadas (base_instructions/default.md) del repositorio de Codex le indican al modelo, en esencia, que revise los AGENTS.md aplicables cuando trabaje por debajo o fuera de la carpeta de trabajo actual. La IA puede abrir el AGENTS.md de un sitio por su cuenta, pero eso es criterio de la IA, no una garantía del mecanismo de carga.

Los archivos de configuración por carpeta también se heredan de forma distinta

Además de los documentos de reglas, las herramientas también difieren en cómo tratan las carpetas para archivos de configuración como los permisos.

PuntoClaude CodeCodex
Archivo de configuración del proyecto.claude/settings.json.codex/config.toml
De qué carpeta se leeEl de la carpeta de inicio (primary working directory); a diferencia de CLAUDE.md, no se hereda de las carpetas superioresDesde la raíz del proyecto hasta la carpeta de inicio (los más cercanos tienen prioridad)
Relación con la confianza (trust)Reglas como allow se aplican después de confiar en la carpeta; deny y ask se aplican de inmediatoLee .codex/ solo en proyectos de confianza

Fuentes: Claude Code settings y Monorepos and large repos de Anthropic, y Config basics de OpenAI (consultadas el 1 de noviembre de 2026).

3. Comprobar si las reglas se cargaron

Una vez colocadas las reglas, comprueba después de iniciar si realmente se cargaron. El método depende de la herramienta, y en Claude Code las reglas cargadas al iniciar y las cargadas después se ven en lugares distintos.

Qué comprobarClaude CodeCodex
Reglas cargadas al iniciarLa lista Memory files de /contextPide «Show which instruction files are active.» (es lo que la propia IA declara; para estar seguro, usa el registro de abajo)
Reglas cargadas durante la sesiónNo aparecen en Memory files; cuando se carga una, aparece en la terminal una línea Loaded con su rutaNo se añaden a mitad de la sesión (igual que arriba)
Dejar constanciaUsa el hook InstructionsLoaded para registrar qué reglas se cargaron, cuándo y por qué (no se dispara con un AGENTS.md leído directamente)Ejecuta codex -c log_dir=./.codex-log para generar el registro de la TUI (./.codex-log/codex-tui.log) y ver qué reglas se cargaron

Fuentes: la sección de solución de problemas de How Claude remembers your project de Anthropic y «Verify your setup» de Custom instructions with AGENTS.md de OpenAI (consultadas el 1 de noviembre de 2026). Añade la carpeta del registro a .gitignore para que no entre en git.

Para probar en Claude Code un archivo de reglas recién añadido en una carpeta inferior, sigue el consejo de la documentación: crea el archivo de reglas desde la shell en lugar de que lo escriba la IA, luego haz que la IA lea un archivo de esa carpeta y mira si aparece una línea Loaded.

4. Hacer cumplir las reglas con comprobaciones automáticas, no con documentos

Como se vio en la sección 2, las reglas colocadas en carpetas pueden no cargarse según dónde inicies y qué herramienta uses. E incluso cargadas, nada garantiza que se cumplan. Por eso conviene pensar el cumplimiento en tres capas.

Documentos de reglas
Explicar los motivos y los pasos CLAUDE.md y AGENTS.md. Puede que no se carguen y, aunque se carguen, nada garantiza que se cumplan. Aun así, la IA los necesita para entender por qué algo se detuvo
Bloqueos de la herramienta
Detener una acción antes de que ocurra Hooks y ajustes de permisos de la herramienta de IA (en este artículo, «bloqueos de la herramienta»). Cada herramienta los configura de forma distinta, y pueden no aplicarse según dónde inicies y los ajustes de confianza
Control del despliegue
La última barrera, sea cual sea la herramienta que hizo el trabajo Si cambió algo fuera de la carpeta asignada, el propio proceso de despliegue se detiene. No depende de la herramienta de IA

En este entorno, hicimos de la capa inferior, el control del despliegue, la salvaguarda decisiva. Tanto si cambias de herramienta de IA como si una persona hace el trabajo directamente, todo pasa por la misma comprobación.

Define el alcance de cada agente con un ajuste por worktree

Da a cada sitio su propio worktree (git worktree) y, en la parte superior del worktree, coloca un pequeño archivo de configuración (.agent-owner) con las carpetas que puede cambiar el agente que trabaja allí. Si escribieras el alcance en un documento de reglas dentro del repositorio, sería idéntico en todos los worktrees y no podría variar según el lugar. Deja el archivo de configuración fuera de git (añádelo a .git/info/exclude) y escríbelo al crear el worktree.

Ten en cuenta que la IA no se inicia en la parte superior del worktree, sino en la carpeta del sitio dentro de él. La parte superior del worktree equivale a la raíz del repositorio, así que iniciar allí da el mismo resultado que «la raíz del repositorio» de la sección 2.

# Desde el checkout principal (/srv/repo), crea en /srv/work-blog un worktree para sites/blog
cd /srv/repo
git worktree add /srv/work-blog -b blog-work
printf 'sites/blog/\n' > /srv/work-blog/.agent-owner
echo '.agent-owner' >> .git/info/exclude

# Inicia la IA desde sites/blog/ dentro del worktree
cd /srv/work-blog/sites/blog
claude        # o codex para Codex

# Antes de desplegar, ejecuta en la parte superior del worktree la comprobación del checkout principal
cd /srv/work-blog
bash /srv/repo/tools/check-owner.sh origin/main

Ejecuta el script de comprobación desde el checkout principal (donde la IA no trabaja) o desde la CI, no la copia del worktree. Si ejecutas la copia del worktree, una IA que reescriba el propio script de comprobación pasaría sin problemas.

Detén el despliegue cuando cambie algo fuera del alcance

Pon la siguiente comprobación (el tools/check-owner.sh de arriba) al comienzo del proceso de despliegue. Supone que solo se despliega desde commits: se detiene si quedan cambios sin confirmar, y se detiene si el diff confirmado respecto a la base (origin/main o similar) incluye aunque sea un archivo fuera de las carpetas asignadas. Lee .agent-owner, así que ejecútala en la parte superior del worktree.

#!/usr/bin/env bash
# Ejecutar en la parte superior del worktree antes de desplegar: detener si cambió algo fuera de las carpetas asignadas
set -euo pipefail

base="${1:-origin/main}"
owner_file=".agent-owner"   # en la parte superior del worktree, fuera de git

if [ ! -s "$owner_file" ]; then
  echo "No hay archivo de alcance ($owner_file). Se detiene el despliegue" >&2
  exit 1
fi

# Detener si quedan cambios sin confirmar (desplegar solo desde commits)
if [ -n "$(git status --porcelain)" ]; then
  echo "Hay cambios sin confirmar. Se detiene el despliegue" >&2
  exit 1
fi

# --no-renames: contar un movimiento desde otra carpeta como eliminación y adición
# Añadir / al final de cada entrada del alcance (para que sites/blog no coincida con sites/blog-old)
# Probado con gawk (Git Bash). BSD awk puede fallar si un valor de -v contiene saltos de línea
outside=$(git diff --name-only --no-renames "$base"...HEAD |
  awk -v list="$(tr -d '\r' < "$owner_file")" '
    BEGIN { n = split(list, own, "\n")
            for (i = 1; i <= n; i++) if (own[i] != "" && substr(own[i], length(own[i])) != "/") own[i] = own[i] "/" }
    { ok = 0; for (i = 1; i <= n; i++) if (own[i] != "" && index($0, own[i]) == 1) ok = 1
      if (!ok) print }')

if [ -n "$outside" ]; then
  echo "Han cambiado archivos fuera del alcance. Se detiene el despliegue:" >&2
  echo "$outside" >&2
  exit 1
fi
echo "Solo hay cambios dentro del alcance"

Estos son los resultados cuando Claude Code, que escribió este artículo, creó un repositorio de prueba con dos sitios y una carpeta compartida y ejecutó la comprobación el 1 de noviembre de 2026, con Git 2.56 (Git Bash en Windows).

Qué probamosResultado
El agente de blog cambió solo archivos de blogPasa
Se movió un archivo de shop a la carpeta de blogSe detiene (aparece el archivo original de shop)
Se cambió un archivo de la carpeta compartidaSe detiene (la carpeta compartida queda fuera del alcance si no se incluye)
Se escribió el alcance sin / final y se añadió sites/blog-old/Se detiene (una versión que no añadía la / lo dejaba pasar)
Se dejaron cambios sin confirmar en shopSe detiene (una versión que solo revisa el diff confirmado no lo detecta)
Se eliminó el archivo de alcanceSe detiene

--no-renames es lo que impide que los movimientos se cuelen. Sin él, git muestra un cambio que considera un movimiento solo con el nombre de destino, así que un cambio que trae archivos de otro sitio pasa desapercibido. La comprobación también «se detiene» en lugar de «pasar» cuando falta el archivo de configuración, para que no pase un worktree cuyo alcance nunca se definió.

Esta comprobación evita confusiones, no infracciones deliberadas. Si la IA reescribe .agent-owner, la comprobación pasa. Para evitar también eso, usa los bloqueos de la herramienta de abajo para denegar también la edición de este archivo de configuración.

Añade bloqueos de la herramienta

Detener solo antes del despliegue significa que te enteras después de que la IA ya haya reescrito algo fuera del alcance. Para detenerlo antes de la escritura, añade las funciones propias de las herramientas.

PuntoClaude CodeCodex
Bloquear la escritura de archivosAñade Edit(ruta) a deny en los ajustes de permisos (se aplica a las herramientas integradas y a los comandos que Claude Code reconoce, como sed, tee y las redirecciones)En un hook PreToolUse, revisa dónde escribe apply_patch (que también coincide como Edit y Write) y devuelve deny como permissionDecision
Bloquear comandosAñade Bash(comando *) a deny, o devuelve el código de salida 2 o un JSON de denegación desde un hook PreToolUseLa regla prefix_rule(pattern=[...], decision="forbidden") (experimental) y los hooks PreToolUse
Bloquear cualquier procesoEl sandbox (deny no detiene un script que abre y escribe archivos por sí mismo)El sandbox (sandbox_mode = "workspace-write" limita la escritura a la carpeta de inicio; writable roots añade lugares donde se puede escribir, así que no los añadas a la ligera)
Condiciones al colocarlos en el proyectoLee .claude/settings.json de la carpeta de inicio; deny se aplica incluso antes de confiar en la carpetaLee el .codex/ del proyecto solo cuando el proyecto es de confianza; los hooks no se ejecutan hasta que los revisas y confías en ellos

Fuentes: Configure permissions y Hooks guide de Anthropic, y Hooks y Rules de OpenAI (consultadas el 1 de noviembre de 2026).

En Claude Code, los ajustes que impiden que el worktree de blog cambie el archivo de alcance (.agent-owner), los scripts de comprobación (tools/), las reglas de la raíz, shop y la carpeta compartida son así (suponiendo que el worktree está en /srv/work-blog). Las rutas que empiezan por // son rutas absolutas. La ubicación de los worktrees cambia de una máquina a otra, así que añade esto a los ajustes de usuario de esa máquina (~/.claude/settings.json) al crear el worktree, no a los ajustes incluidos en el repositorio.

{
  "permissions": {
    "deny": [
      "Edit(//srv/work-blog/.agent-owner)",
      "Edit(//srv/work-blog/tools/**)",
      "Edit(//srv/work-blog/CLAUDE.md)",
      "Edit(//srv/work-blog/AGENTS.md)",
      "Edit(//srv/work-blog/sites/shop/**)",
      "Edit(//srv/work-blog/sites/shared/**)",
      "Edit(//srv/repo/**)"
    ]
  }
}

En Codex, registra el script de comprobación en PreToolUse dentro de la configuración de hooks (tu ~/.codex/hooks.json personal, el .codex/hooks.json del repositorio o similar), con apply_patch como matcher. Los hooks no se ejecutan hasta que los revisas y confías en ellos con /hooks en Codex (si los cambias, hay que volver a confiar en ellos).

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "^apply_patch$",
        "hooks": [ { "type": "command", "command": "python3 ~/.codex/hooks/owner_guard.py" } ] }
    ]
  }
}

El script de comprobación extrae las rutas de destino de las líneas *** Add File:, *** Update File:, *** Delete File: y *** Move to: de la entrada de apply_patch, y devuelve deny si alguna está fuera del alcance o protegida. Este es un ejemplo mínimo.

import json, posixpath, re, sys

# Hook PreToolUse de Codex: detener apply_patch si cambia archivos fuera del alcance o protegidos
OWN = ["/srv/work-blog/sites/blog/"]                  # alcance (incluye la / final)
PROTECT = ["/srv/work-blog/.agent-owner", "/srv/work-blog/tools/"]

event = json.load(sys.stdin)
command = event.get("tool_input", {}).get("command", "")
if isinstance(command, list):
    command = "\n".join(command)

bad = []
for m in re.finditer(r"^\*\*\* (?:Add File|Update File|Delete File|Move to): (.+)$", command, re.M):
    path = posixpath.normpath(posixpath.join(event.get("cwd", ""), m.group(1).strip()))
    if not any(path.startswith(o) for o in OWN) or any(path.startswith(p) for p in PROTECT):
        bad.append(path)

if bad:
    print(json.dumps({"hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "deny",
        "permissionDecisionReason": "Archivos fuera del alcance: " + ", ".join(bad)}}, ensure_ascii=False))

Claude Code, que escribió este artículo, ejecutó este script con entradas creadas a mano en el formato que pasa Codex (dentro del alcance, shop, .agent-owner, un movimiento a shared y una eliminación en tools/) y confirmó que solo pasaba el cambio dentro del alcance. No lo hemos ejecutado dentro de Codex.

Los comandos de Bash pueden escribirse de muchas maneras, así que un hook no puede determinar del todo dónde escriben. La propia OpenAI define los hooks como «a useful guardrail, not a complete enforcement boundary» (una barrera útil, no un límite de cumplimiento completo). Bloquea los comandos que quieras impedir, como rm, con una regla que use decision = "forbidden", y deja que el control del despliegue atrape el resto. Las reglas van en la carpeta rules/ de una capa de configuración, como ~/.codex/rules/default.rules. El .codex/rules/ de un proyecto solo se lee cuando ese proyecto es de confianza.

Los bloqueos de la herramienta hay que reescribirlos para cada herramienta, y pueden no aplicarse según dónde inicies y los ajustes de confianza. Por eso, toma como base el control del despliegue, por el que todo cambio tiene que pasar al final, y superpón los bloqueos de la herramienta para detectar los problemas antes. Para escribir hooks de Claude Code, consulta «¿Qué son los hooks de Claude Code?»; para los ajustes de solo lectura, «Cómo usar Codex y Claude Code en solo lectura».

5. Ten en cuenta también: confundir repositorios y las variables de entorno

En el mismo entorno, ocurrieron otras dos cosas al confiar varios repositorios a una IA. Ambas se detectaron antes de convertirse en incidentes graves, pero, aparte de cómo coloques las reglas, define procedimientos para ellas.

Distingue los repositorios de nombre parecido por su URL remota

Una IA decidió que el repositorio de otro servicio con un nombre muy parecido era «una copia antigua del mismo servicio» y lo movió a otro lugar (se restauró enseguida, sin cambios en su contenido). Su razonamiento fue «no hay cambios locales y la última actualización es antigua», pero eso solo demuestra que «no hay nada a medio cambiar» y que «nadie lo ha editado últimamente». Cuanto más estable funciona un servicio, menos se actualiza.

Antes de mover o eliminar algo, ejecuta lo siguiente tanto en la carpeta objetivo como en la que se usa en producción, y compara los resultados uno al lado del otro.

# URL remota (elimina cualquier token o contraseña incluidos en la URL antes de mostrarla)
git -C <carpeta> remote get-url origin | sed -E 's#://[^/@]+@#://#'

# Comprueba primero que no sea un clon superficial (si da true, el siguiente resultado no es fiable)
git -C <carpeta> rev-parse --is-shallow-repository

# Commit raíz (las copias que salieron del mismo historial lo comparten)
git -C <carpeta> rev-list --max-parents=0 HEAD
  • Compara las URL remotas por host y ruta del repositorio: https://github.com/org/app.git y git@github.com:org/app.git son el mismo repositorio escrito de forma distinta; a la inversa, con espejos o alias de host, el mismo repositorio puede parecer distinto
  • En un clon superficial, el commit raíz no es el primer commit real: en un clon obtenido con --depth 1, obtienes el commit más antiguo descargado (en nuestra prueba, el propio HEAD)
  • No muestres los tokens incluidos en la URL: una URL remota puede contener un token de autenticación, y mostrarla tal cual filtra un secreto en la salida, igual que las variables de entorno de abajo

Aunque la comparación muestre que es «una copia sin uso», no la elimines enseguida; muévela primero a otro lugar. Anota adónde fue, dónde estaba y el comando para devolverla, y elimínala solo después de comprobar durante un tiempo que nada se ha roto. En este entorno, la confusión pudo deshacerse enseguida precisamente porque la carpeta se movió en lugar de eliminarse.

Mira solo los nombres de las variables de entorno

Una IA ejecutó un comando para inspeccionar la configuración de un contenedor que mostró las variables de entorno con sus valores, y una cadena de conexión a la base de datos (con la contraseña) apareció en la salida. Una vez que un valor aparece en la salida, queda en el registro de la conversación y además se envía al modelo. Si solo quieres ver qué está definido, basta con los nombres.

Variables de entorno del contenedor

Muestra los valores (no usar)

docker inspect <contenedor>
docker exec <contenedor> printenv
docker exec <contenedor> sh -c 'env | cut -d= -f1'

Solo nombres

docker inspect --format '{{range .Config.Env}}{{index (split . "=") 0}}{{println}}{{end}}' <contenedor>
docker exec <contenedor> awk 'BEGIN{for(k in ENVIRON) print k}'

Sin opciones, docker inspect muestra toda la configuración, y su Env contiene los valores tal cual. En contenedores sin awk, usa docker inspect --format.

Configuración de Docker Compose

Muestra los valores (no usar)

docker compose config

Sin interpolar variables

docker compose config --no-interpolate

Con --no-interpolate, ${DB_URL} se muestra tal cual, y de env_file solo se muestra la ruta del archivo. Las variables cuyos valores están escritos directamente en compose.yaml sí se muestran.

Shell local

Muestra los valores (no usar)

env
printenv
Get-ChildItem Env:

Solo nombres

compgen -e                  # bash
(Get-ChildItem Env:).Name   # PowerShell

Estos son los resultados cuando Claude Code, que escribió este artículo, hizo pruebas con valores ficticios el 1 de noviembre de 2026, con Docker 29.8 y Docker Compose v5.6. En un contenedor con un valor que contenía saltos de línea (la forma que se usa al pasar el contenido de un archivo de clave), ejecutar env | cut -d= -f1 mostró tal cual la segunda y la tercera línea del valor, mezcladas con los nombres de las variables. ENVIRON de awk y docker inspect --format no mostraron los valores. docker compose config mostró los valores ficticios escritos en .env y env_file; con --no-interpolate, no apareció ninguno de los dos, y solo se mostró el valor escrito directamente en compose.yaml.

Para ir sobre seguro, escribe «mira solo los nombres de las variables de entorno» en los documentos de reglas y, además, deniega con los bloqueos de la herramienta de la sección 4 los comandos que muestran valores. Si aun así se muestra un valor, trátalo como «visto» y decide si lo rotas. Para un ajuste de Codex que evita que las propias variables de entorno lleguen a los comandos de la IA, consulta la sección 6 de «Cómo impedir que Codex lea archivos secretos».

6. Lista de comprobación antes de delegar el trabajo

  • Decidiste que el trabajo de cada sitio inicia la IA desde la carpeta del sitio dentro del worktree
  • Después de iniciar, confirmaste que se incluyen las reglas del sitio: Memory files en /context en Claude Code y la lista de archivos de instrucciones activos en Codex
  • Para el trabajo iniciado en la raíz, preparaste una forma de ver si las reglas de carpetas inferiores se cargaron a mitad de la sesión (la línea Loaded de Claude Code, el hook InstructionsLoaded)
  • Añadiste una comprobación que detiene el despliegue si cambió algo fuera de las carpetas asignadas, y viste cómo se detenía ante un cambio deliberado fuera del alcance
  • Escribiste el alcance de cada worktree con / final e hiciste que la comprobación se detenga cuando falta el archivo de alcance
  • Denegaste con bloqueos de la herramienta la escritura fuera del alcance y en el archivo de alcance
  • Escribiste en las reglas un procedimiento para comparar la URL remota y el commit raíz con producción antes de mover o eliminar una carpeta, y para mover en lugar de eliminar
  • Escribiste en las reglas los comandos que muestran solo los nombres de las variables de entorno, y denegaste con bloqueos de la herramienta los comandos que muestran valores
Ejemplo de texto para los documentos de reglas (listo para usar)
## Reglas al trabajar con varios proyectos
- El alcance de este worktree son solo las carpetas listadas en .agent-owner. No cambies archivos fuera de ellas
  (los cambios fuera detienen la comprobación del despliegue)
- Antes de mover o eliminar una carpeta, compara git remote get-url origin y
  git rev-list --max-parents=0 HEAD con producción (cuidado con los clones superficiales).
  Mueve en lugar de eliminar, y anota cómo restaurarla
- Mira solo los nombres de las variables de entorno. No uses env, printenv, docker inspect (sin --format) ni
  docker compose config (sin --no-interpolate)

Escribe los documentos no como un medio para hacer cumplir, sino como una explicación, para que, cuando algo se detenga, la IA entienda por qué y elija el procedimiento correcto.

Resumen

  • Si inicias desde la raíz, Claude Code no carga las reglas colocadas en la carpeta de cada sitio hasta que toca archivos de esa carpeta, y Codex no las carga automáticamente (la IA puede abrirlas por su cuenta, pero no hay garantía)
  • En cualquiera de las dos herramientas, iniciar desde la carpeta del sitio carga las reglas de ese sitio desde el principio (con un worktree, inicia desde la carpeta del sitio dentro de él)
  • Comprueba lo cargado al iniciar con /context en Claude Code o con la lista de archivos de instrucciones activos de Codex, y lo que Claude Code cargó a mitad de la sesión con la línea Loaded o el hook InstructionsLoaded
  • Convierte lo que deba cumplirse en una comprobación automática que detenga el despliegue si cambió algo fuera de las carpetas asignadas, y superpón los bloqueos de la herramienta para detectar los problemas antes
  • Además, distingue los repositorios de nombre parecido por la URL remota y el commit raíz, y mira solo los nombres de las variables de entorno

Preguntas frecuentes

P. ¿Se carga un CLAUDE.md colocado en un subdirectorio?

R. Sí, pero no al iniciar. Claude Code carga el CLAUDE.md de una carpeta cuando Claude lee, escribe o edita un archivo dentro de esa carpeta. En ese momento no aparece en Memory files de /context; en su lugar, aparece en la terminal una línea Loaded con su ruta. Si inicias desde esa carpeta, se carga al iniciar y aparece en Memory files.

P. ¿Cómo hago que Codex lea un AGENTS.md de un subdirectorio?

R. Inicia Codex desde esa carpeta (en la CLI, codex --cd <carpeta>). Al iniciar, Codex lee los AGENTS.md desde la raíz del proyecto hasta la carpeta de inicio, y no busca por debajo. Si inicias desde la raíz, el AGENTS.md de una carpeta inferior se lee si la IA lo abre por su cuenta, pero la documentación oficial no ofrece ningún ajuste que lo cargue con seguridad.

P. En un monorepo, ¿debo reunir los documentos de reglas en un solo archivo en la raíz?

R. La documentación de ambas herramientas recomienda poner en la raíz las reglas de todo el repositorio y en la carpeta de cada sitio las reglas propias de ese sitio. Sin embargo, las reglas de un sitio pueden no cargarse si no inicias desde esa carpeta, así que lo que causaría problemas si se ignora debe salir de los documentos y pasar al control del despliegue o a los bloqueos de la herramienta.

P. ¿Cómo hago que Claude Code lea tanto CLAUDE.md como AGENTS.md?

R. De forma predeterminada, si hay un CLAUDE.md, .claude/CLAUDE.md o CLAUDE.local.md en la carpeta de inicio o por encima, no se lee AGENTS.md. Impórtalo con una sola línea @AGENTS.md en CLAUDE.md, o ajusta Project instructions en /config a claude-md-and-agents-md.

Fuentes