Se você coloca vários sites em um repositório e põe regras para a IA (CLAUDE.md ou AGENTS.md) na pasta de cada site, a IA vai seguir as regras daquele site: é o que se tende a supor, mas nem o Claude Code nem o Codex “sempre leem” as regras das pastas inferiores. Se você inicia a partir da raiz do repositório, o Claude Code não as carrega até tocar em arquivos daquela pasta, e o Codex não as carrega automaticamente (a IA pode abri-las por conta própria, mas não há garantia). Este artigo compara, item por item e com base na documentação oficial das duas ferramentas, quando esses arquivos são carregados e como verificar se foram, e depois mostra como fazer as regras serem cumpridas com verificações automáticas em vez de documentos. Ele nasceu do que aprendemos ao projetar essa organização em um ambiente onde agentes de IA cuidam da operação de servidores e de vários projetos.
Quando as regras da pasta de cada site são carregadas? (ao iniciar a partir da raiz do repositório)
Claude Code
- Ao iniciarO
CLAUDE.mdda raiz - Ao tocarCarrega o
CLAUDE.mddo blog quando lê, escreve ou edita um arquivo emsites/blog/ - Ainda nãoAs regras de uma pasta em que ainda não tocou (shop) não estão carregadas
Codex
- Ao iniciarO
AGENTS.mdda raiz - Sem garantiaO
AGENTS.mddesites/blog/não é carregado automaticamente (o Codex não procura abaixo da pasta em que foi iniciado) - Sem garantiaO
AGENTS.mddesites/shop/(idem)
Por isso, inicie o trabalho de um site a partir da pasta desse site e não dependa de documentos para o que precisa ser cumprido de qualquer jeito. Rode uma verificação automática que “interrompa a publicação se algo fora da pasta atribuída tiver mudado” e defina o escopo de cada agente com uma configuração por worktree. Mantenha os documentos de regras para explicar à IA os motivos e os passos.
Fontes: How Claude remembers your project, da Anthropic, e Custom instructions with AGENTS.md, da OpenAI (ambas consultadas em 1º de novembro de 2026).
1. O que aprendemos ao colocar regras na pasta de cada site
Em um ambiente onde agentes de IA cuidam da operação de servidores e de vários sites, pensamos em um projeto que coloca vários sites em um repositório e põe as regras de cada site na pasta dele (omitimos os detalhes que identificariam locais ou nomes, e o conteúdo técnico foi generalizado). O objetivo era uma divisão de tarefas: a IA responsável pelo blog lê só as regras do blog e nunca toca no shop.
Mas, ao conferir a documentação oficial das duas ferramentas, vimos que não havia garantia de que as regras colocadas fossem carregadas antes de o trabalho começar. Quais regras são carregadas depende da pasta a partir da qual se inicia. Além disso, a documentação do Claude Code descreve o CLAUDE.md como contexto, não como uma configuração imposta. Mesmo quando as regras são carregadas, nada garante que serão seguidas.
- !
Colocar regras em pastas não basta para dividir responsabilidades
- Risco
- Uma IA iniciada na raiz altera arquivos sem ter lido as regras daquele site, ou antes de lê-las
- Solução
- Inicie o trabalho de um site a partir da pasta dele e barre as alterações fora do escopo com uma verificação na publicação (seção 4)
- Verificar
- Use as ferramentas para confirmar quais regras foram carregadas (seção 3) e altere de propósito algo fora do escopo para ver se a publicação é interrompida
As causas gerais de a IA ignorar regras, e as soluções, estão em “Por que a IA ignora regras: verificando CLAUDE.md, Cursor Rules e AGENTS.md”. Este artigo se concentra no que acontece quando você divide as regras entre pastas. Dois outros cuidados do mesmo ambiente, sobre entregar vários repositórios a uma IA, estão na seção 5.
2. Quando as regras de cada pasta são carregadas?
Se as regras da pasta de cada site são carregadas ou não depende de a partir de qual pasta você inicia e de qual ferramenta você usa. Veja o que diz a documentação oficial das duas ferramentas, item por item.
| Item | Claude Code | Codex |
|---|---|---|
| O que é carregado ao iniciar | Todos os CLAUDE.md e CLAUDE.local.md da pasta de inicialização (launch directory) e de todas as pastas acima dela | Da raiz do projeto (project root, normalmente a raiz do git) até a pasta de inicialização, um arquivo por pasta: AGENTS.override.md ou, se não houver, AGENTS.md |
| Abaixo da pasta de inicialização | Não é carregado ao iniciar; é carregado quando o Claude lê, escreve ou edita outro arquivo daquela pasta | Não é carregado automaticamente (a busca para na pasta de inicialização; a IA pode abri-lo por conta própria) |
| Novas regras entram durante a sessão? | Sim (as regras das pastas em que toca são adicionadas depois) | Não (montadas uma única vez no início de cada execução) |
| Limites de tamanho | A referência é menos de 200 linhas por arquivo (quanto mais longo, menos confiável é que seja seguido); nos CLAUDE.md de pastas inferiores, o que passar de 40.000 caracteres por arquivo (com um contexto de 200 mil tokens) é cortado, e só o início é repassado | Nada é adicionado depois que o total passa de 32 KiB (o padrão de project_doc_max_bytes) |
| O arquivo de regras da outra ferramenta | Lê o AGENTS.md quando não há CLAUDE.md, .claude/CLAUDE.md nem CLAUDE.local.md na pasta de inicialização ou acima dela (padrão) | Não lê o CLAUDE.md (só lê os nomes adicionados a project_doc_fallback_filenames) |
Fontes: How Claude remembers your project e Monorepos and large repos, da Anthropic, e Custom instructions with AGENTS.md, da OpenAI (consultadas em 1º de novembro de 2026). O limite do Claude Code para pastas inferiores vale a partir da v2.1.309. Com um contexto de 1 milhão de tokens, ele é de 150.000 caracteres (200.000 no Opus 4.6 e no Sonnet 4.6). O Claude Code lê o AGENTS.md diretamente a partir da v2.1.277; o AGENTS.md de uma pasta inferior é lido quando essa pasta não tem CLAUDE.md e o Claude abre um arquivo dela com a ferramenta Read. Para que ele leia os dois, defina Project instructions em /config como claude-md-and-agents-md.
O lugar de onde você inicia muda quais regras são carregadas
Mesmo no mesmo repositório, o resultado depende de onde você inicia. Se iniciar a partir da pasta de um site, as duas ferramentas leem as regras desse site desde o começo.
| Iniciar a partir de | Claude Code | Codex |
|---|---|---|
| A raiz do repositório | Só as regras da raiz; as regras de cada site são adicionadas quando o Claude toca em arquivos daquele site | Só as regras da raiz; as regras dos sites não são carregadas automaticamente |
sites/blog/ | Lê ao iniciar as regras do blog e da raiz (editar arquivos fora da pasta de inicialização pede aprovação) | Lê a raiz e depois o blog; as regras do shop não estão no caminho, então não são carregadas automaticamente |
O que é fácil deixar passar é o que conta como “tocar” em “carregado ao tocar”. O que a documentação do Claude Code conta como leitura é ler, escrever ou editar um arquivo com as ferramentas dele, além de comandos que exibem um único arquivo, como cat ou head. Operações que alteram arquivos de outras formas, como um localizar e substituir em massa nas pastas de vários sites, não estão nessa lista. Os arquivos de um site podem mudar antes de as regras dele serem lidas.
No Codex, se você iniciar a partir da raiz do repositório e pedir “corrija o blog e o shop”, o AGENTS.md de nenhum dos dois sites é carregado automaticamente. A documentação diz que o Codex para de procurar ao chegar à pasta de trabalho atual, então as regras de uma pasta inferior só entram com certeza ao iniciar quando você inicia a partir dessa pasta ou de uma abaixo dela.
Dito isso, as instruções padrão (base_instructions/default.md) do repositório do Codex dizem ao modelo, em essência, para conferir os AGENTS.md aplicáveis ao trabalhar abaixo ou fora da pasta de trabalho atual. A IA pode abrir o AGENTS.md de um site por conta própria, mas isso é critério da IA, não uma garantia do mecanismo de carregamento.
Os arquivos de configuração por pasta também são herdados de forma diferente
Além dos documentos de regras, as ferramentas também diferem na forma como tratam as pastas para arquivos de configuração, como os de permissões.
| Item | Claude Code | Codex |
|---|---|---|
| Arquivo de configuração do projeto | .claude/settings.json | .codex/config.toml |
| De qual pasta é lido | O da pasta de inicialização (primary working directory); ao contrário do CLAUDE.md, não é herdado das pastas acima | Da raiz do projeto até a pasta de inicialização (os mais próximos têm prioridade) |
| Relação com a confiança (trust) | Regras como allow passam a valer depois que você confia na pasta; deny e ask valem imediatamente | Lê .codex/ só em projetos confiáveis |
Fontes: Claude Code settings e Monorepos and large repos, da Anthropic, e Config basics, da OpenAI (consultadas em 1º de novembro de 2026).
3. Verificar se as regras foram carregadas
Depois de colocar as regras, verifique após iniciar se elas foram de fato carregadas. O método varia conforme a ferramenta, e no Claude Code as regras carregadas ao iniciar e as carregadas depois aparecem em lugares diferentes.
| O que verificar | Claude Code | Codex |
|---|---|---|
| Regras carregadas ao iniciar | A lista Memory files em /context | Peça “Show which instruction files are active.” (é o que a própria IA declara; para ter certeza, use o log abaixo) |
| Regras carregadas durante a sessão | Não aparecem em Memory files; quando uma é carregada, surge no terminal uma linha Loaded com o caminho dela | Nenhuma é adicionada no meio da sessão (como acima) |
| Manter um registro | Use o hook InstructionsLoaded para registrar quais regras foram carregadas, quando e por quê (ele não dispara para um AGENTS.md lido diretamente) | Rode codex -c log_dir=./.codex-log para gravar o log da TUI (./.codex-log/codex-tui.log) e ver quais regras foram carregadas |
Fontes: a seção de solução de problemas de How Claude remembers your project, da Anthropic, e “Verify your setup” em Custom instructions with AGENTS.md, da OpenAI (consultadas em 1º de novembro de 2026). Adicione a pasta do log ao .gitignore para que ela fique fora do git.
Para testar no Claude Code um arquivo de regras recém-adicionado em uma pasta inferior, siga a recomendação da documentação: crie o arquivo de regras pelo shell em vez de pedir à IA que o escreva, depois faça a IA ler um arquivo daquela pasta e veja se aparece uma linha Loaded.
4. Fazer cumprir as regras com verificações automáticas, não com documentos
Como mostrou a seção 2, regras colocadas em pastas podem não ser carregadas, dependendo de onde você inicia e de qual ferramenta usa. E, mesmo carregadas, nada garante que sejam seguidas. Por isso, pense no cumprimento em três camadas.
CLAUDE.md e AGENTS.md. Podem não ser carregados e, mesmo quando são, nada garante que sejam seguidos. Ainda assim, a IA precisa deles para entender por que algo foi interrompidoNeste ambiente, fizemos da camada de baixo, a verificação da publicação, a proteção decisiva. Quer você troque de ferramenta de IA, quer uma pessoa faça o trabalho diretamente, tudo passa pela mesma verificação.
Defina o escopo de cada agente com uma configuração por worktree
Dê a cada site seu próprio worktree (git worktree) e, no topo do worktree, coloque um pequeno arquivo de configuração (.agent-owner) listando as pastas que o agente que trabalha ali pode alterar. Se você escrevesse o escopo em um documento de regras dentro do repositório, ele seria idêntico em todos os worktrees e não poderia variar conforme o lugar. Mantenha o arquivo de configuração fora do git (adicione-o a .git/info/exclude) e escreva-o ao criar o worktree.
Observe que a IA não é iniciada no topo do worktree, e sim na pasta do site dentro dele. O topo do worktree equivale à raiz do repositório, então iniciar ali dá o mesmo resultado que “a raiz do repositório” da seção 2.
# A partir do checkout principal (/srv/repo), crie em /srv/work-blog um 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
# Inicie a IA a partir de sites/blog/ dentro do worktree
cd /srv/work-blog/sites/blog
claude # ou codex para o Codex
# Antes de publicar, rode no topo do worktree a verificação do checkout principal
cd /srv/work-blog
bash /srv/repo/tools/check-owner.sh origin/main
Rode o script de verificação a partir do checkout principal (onde a IA não trabalha) ou da CI, não a cópia dentro do worktree. Se você rodar a cópia do worktree, uma IA que reescreva o próprio script de verificação passaria direto.
Interrompa a publicação quando algo fora do escopo mudar
Coloque a verificação a seguir (o tools/check-owner.sh acima) no início do processo de publicação. Ela pressupõe que só se publica a partir de commits: para se restarem alterações não commitadas, e para se o diff commitado em relação à base (origin/main ou similar) incluir nem que seja um arquivo fora das pastas atribuídas. Ela lê o .agent-owner, então rode-a no topo do worktree.
#!/usr/bin/env bash
# Rodar no topo do worktree antes de publicar: parar se algo fora das pastas atribuídas mudou
set -euo pipefail
base="${1:-origin/main}"
owner_file=".agent-owner" # no topo do worktree, fora do git
if [ ! -s "$owner_file" ]; then
echo "Não há arquivo de escopo ($owner_file). Interrompendo a publicação" >&2
exit 1
fi
# Parar se restarem alterações não commitadas (publicar só a partir de commits)
if [ -n "$(git status --porcelain)" ]; then
echo "Há alterações não commitadas. Interrompendo a publicação" >&2
exit 1
fi
# --no-renames: contar uma movimentação de outra pasta como exclusão e adição
# Acrescentar / ao final de cada entrada do escopo (para que sites/blog não corresponda a sites/blog-old)
# Testado com gawk (Git Bash). O awk BSD pode falhar quando um valor de -v contém quebras de linha
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 "Arquivos fora do escopo foram alterados. Interrompendo a publicação:" >&2
echo "$outside" >&2
exit 1
fi
echo "Só há alterações dentro do escopo"
Estes são os resultados quando o Claude Code, que escreveu este artigo, criou um repositório de teste com dois sites e uma pasta compartilhada e rodou a verificação em 1º de novembro de 2026, com o Git 2.56 (Git Bash no Windows).
| O que testamos | Resultado |
|---|---|
| O agente do blog alterou só arquivos do blog | Passa |
| Um arquivo do shop foi movido para a pasta do blog | Para (aparece o arquivo original do shop) |
| Um arquivo da pasta compartilhada foi alterado | Para (a pasta compartilhada fica fora do escopo se não for listada) |
O escopo foi escrito sem a / final e sites/blog-old/ foi adicionado | Para (uma versão que não acrescentava a / deixava passar) |
| Alterações não commitadas foram deixadas no shop | Para (uma versão que só verifica o diff commitado não pega isso) |
| O arquivo de escopo foi excluído | Para |
O --no-renames é o que impede que movimentações escapem. Sem ele, o git lista uma alteração que considera movimentação só com o nome de destino, então uma alteração que traz arquivos de outro site passa despercebida. A verificação também “para” em vez de “passar” quando falta o arquivo de configuração, para que um worktree cujo escopo nunca foi definido não passe.
.agent-owner, a verificação passa. Para evitar isso também, use os bloqueios da ferramenta abaixo para negar também a edição deste arquivo de configuração.Adicione bloqueios da ferramenta
Barrar só antes da publicação significa descobrir depois que a IA já reescreveu algo fora do escopo. Para barrar antes da escrita, adicione os recursos das próprias ferramentas.
| Item | Claude Code | Codex |
|---|---|---|
| Bloquear a escrita de arquivos | Adicione Edit(caminho) a deny nas configurações de permissão (vale para as ferramentas integradas e para comandos que o Claude Code reconhece, como sed, tee e redirecionamentos) | Em um hook PreToolUse, confira onde o apply_patch (que também corresponde como Edit e Write) escreve e devolva deny como permissionDecision |
| Bloquear comandos | Adicione Bash(comando *) a deny, ou devolva o código de saída 2 ou um JSON de negação a partir de um hook PreToolUse | A regra prefix_rule(pattern=[...], decision="forbidden") (experimental) e os hooks PreToolUse |
| Bloquear qualquer processo | O sandbox (deny não impede um script que abre e escreve arquivos por conta própria) | O sandbox (sandbox_mode = "workspace-write" limita a escrita à pasta de inicialização; writable roots acrescenta lugares graváveis, então não os adicione sem necessidade) |
| Condições ao colocá-los no projeto | Lê o .claude/settings.json da pasta de inicialização; deny vale mesmo antes de você confiar na pasta | Lê o .codex/ do projeto só quando o projeto é confiável; os hooks não rodam até você revisá-los e confiar neles |
Fontes: Configure permissions e Hooks guide, da Anthropic, e Hooks e Rules, da OpenAI (consultadas em 1º de novembro de 2026).
No Claude Code, as configurações que impedem o worktree do blog de alterar o arquivo de escopo (.agent-owner), os scripts de verificação (tools/), as regras da raiz, o shop e a pasta compartilhada ficam assim (supondo que o worktree está em /srv/work-blog). Caminhos que começam com // são caminhos absolutos. A localização dos worktrees muda de máquina para máquina, então adicione isto às configurações de usuário daquela máquina (~/.claude/settings.json) ao criar o worktree, e não às configurações incluídas no repositório.
{
"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/**)"
]
}
}
No Codex, registre o script de verificação em PreToolUse na configuração de hooks (seu ~/.codex/hooks.json pessoal, o .codex/hooks.json do repositório ou similar), com apply_patch como matcher. Os hooks não rodam até você revisá-los e confiar neles com /hooks no Codex (se você os alterar, é preciso confiar neles de novo).
{
"hooks": {
"PreToolUse": [
{ "matcher": "^apply_patch$",
"hooks": [ { "type": "command", "command": "python3 ~/.codex/hooks/owner_guard.py" } ] }
]
}
}
O script de verificação extrai os caminhos de destino das linhas *** Add File:, *** Update File:, *** Delete File: e *** Move to: da entrada do apply_patch e devolve deny se algum estiver fora do escopo ou protegido. Veja um exemplo mínimo.
import json, posixpath, re, sys
# Hook PreToolUse do Codex: parar o apply_patch se ele alterar arquivos fora do escopo ou protegidos
OWN = ["/srv/work-blog/sites/blog/"] # escopo (inclua a / 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": "Arquivos fora do escopo: " + ", ".join(bad)}}, ensure_ascii=False))
O Claude Code, que escreveu este artigo, rodou este script com entradas montadas à mão no formato que o Codex repassa (dentro do escopo, shop, .agent-owner, uma movimentação para shared e uma exclusão em tools/) e confirmou que só a alteração dentro do escopo passou. Não o rodamos dentro do Codex.
Comandos de Bash podem ser escritos de muitas maneiras, então um hook não consegue determinar por completo onde eles escrevem. A própria OpenAI define os hooks como “a useful guardrail, not a complete enforcement boundary” (uma proteção útil, não um limite de aplicação completo). Bloqueie os comandos que você quer impedir, como rm, com uma regra que use decision = "forbidden", e deixe a verificação da publicação pegar o resto. As regras ficam na pasta rules/ de uma camada de configuração, como ~/.codex/rules/default.rules. O .codex/rules/ de um projeto só é lido quando esse projeto é confiável.
Os bloqueios da ferramenta precisam ser reescritos para cada ferramenta e podem não valer dependendo de onde você inicia e das configurações de confiança. Por isso, use como base a verificação da publicação, pela qual toda alteração tem de passar no fim, e sobreponha os bloqueios da ferramenta para pegar os problemas mais cedo. Para escrever hooks do Claude Code, veja “O Que São os Hooks do Claude Code?”; para configurações de somente leitura, “Como usar Codex e Claude Code em somente leitura”.
5. Atenção também a: confundir repositórios e variáveis de ambiente
No mesmo ambiente, aconteceram outras duas coisas ao entregar vários repositórios a uma IA. As duas foram detectadas antes de virar incidentes graves, mas, além de como você coloca as regras, defina procedimentos para elas.
Diferencie repositórios de nomes parecidos pela URL remota
Uma IA concluiu que o repositório de outro serviço, com nome muito parecido, era “uma cópia antiga do mesmo serviço” e o moveu para outro lugar (ele foi restaurado na hora, sem alteração no conteúdo). O raciocínio foi “não há alterações locais e a última atualização é antiga”, mas isso só mostra que “nada está no meio de uma alteração” e que “ninguém o editou recentemente”. Quanto mais estável é um serviço, menos ele é atualizado.
Antes de mover ou excluir qualquer coisa, rode o seguinte tanto na pasta-alvo quanto na pasta usada em produção, e compare os resultados lado a lado.
# URL remota (remova qualquer token ou senha embutidos na URL antes de exibi-la)
git -C <pasta> remote get-url origin | sed -E 's#://[^/@]+@#://#'
# Confira primeiro que não é um clone raso (se der true, o próximo resultado não é confiável)
git -C <pasta> rev-parse --is-shallow-repository
# Commit raiz (cópias que saíram do mesmo histórico o compartilham)
git -C <pasta> rev-list --max-parents=0 HEAD
- Compare as URLs remotas pelo host e pelo caminho do repositório:
https://github.com/org/app.gitegit@github.com:org/app.gitsão o mesmo repositório escrito de formas diferentes; ao contrário, com espelhos ou aliases de host, o mesmo repositório pode parecer diferente - Em um clone raso, o commit raiz não é o primeiro commit de verdade: em um clone obtido com
--depth 1, você recebe o commit mais antigo baixado (no nosso teste, o próprio HEAD) - Não exiba tokens embutidos na URL: uma URL remota pode conter um token de autenticação, e exibi-la como está vaza um segredo na saída, assim como as variáveis de ambiente abaixo
Mesmo que a comparação mostre que é “uma cópia sem uso”, não a exclua de imediato; mova-a primeiro para outro lugar. Anote para onde foi, onde estava e o comando para trazê-la de volta, e só a exclua depois de confirmar por um tempo que nada quebrou. Neste ambiente, a confusão pôde ser desfeita na hora justamente porque a pasta foi movida, e não excluída.
Veja só os nomes das variáveis de ambiente
Uma IA rodou um comando para inspecionar a configuração de um contêiner que exibiu as variáveis de ambiente com os valores, e uma string de conexão com o banco de dados (incluindo a senha) apareceu na saída. Quando um valor aparece na saída, ele fica no registro da conversa e também é enviado ao modelo. Se você só quer ver o que está definido, os nomes bastam.
Variáveis de ambiente do contêiner
Exibe os valores (não usar)
docker inspect <contêiner>
docker exec <contêiner> printenv
docker exec <contêiner> sh -c 'env | cut -d= -f1'Só os nomes
docker inspect --format '{{range .Config.Env}}{{index (split . "=") 0}}{{println}}{{end}}' <contêiner>
docker exec <contêiner> awk 'BEGIN{for(k in ENVIRON) print k}'Sem opções, o docker inspect exibe a configuração inteira, e o Env dela contém os valores como estão. Em contêineres sem awk, use o docker inspect --format.
Configuração do Docker Compose
Exibe os valores (não usar)
docker compose configSem interpolar variáveis
docker compose config --no-interpolateCom --no-interpolate, ${DB_URL} aparece como está, e do env_file aparece só o caminho do arquivo. Variáveis cujos valores estão escritos diretamente no compose.yaml aparecem.
Shell local
Exibe os valores (não usar)
env
printenv
Get-ChildItem Env:Só os nomes
compgen -e # bash
(Get-ChildItem Env:).Name # PowerShellEstes são os resultados quando o Claude Code, que escreveu este artigo, testou com valores fictícios em 1º de novembro de 2026, usando o Docker 29.8 e o Docker Compose v5.6. Em um contêiner com um valor contendo quebras de linha (a forma usada ao passar o conteúdo de um arquivo de chave), rodar env | cut -d= -f1 exibiu a segunda e a terceira linhas do valor como estavam, misturadas aos nomes das variáveis. O ENVIRON do awk e o docker inspect --format não exibiram os valores. O docker compose config exibiu os valores fictícios escritos no .env e no env_file; com --no-interpolate, nenhum dos dois apareceu, e só foi exibido o valor escrito diretamente no compose.yaml.
Para ter certeza, escreva “veja só os nomes das variáveis de ambiente” nos documentos de regras e, além disso, negue com os bloqueios da ferramenta da seção 4 os comandos que exibem valores. Se mesmo assim um valor for exibido, trate-o como “visto” e decida se vai trocá-lo. Para uma configuração do Codex que impede que as próprias variáveis de ambiente cheguem aos comandos da IA, veja a seção 6 de “Como impedir que o Codex leia arquivos secretos”.
6. Checklist antes de entregar o trabalho
- Ficou decidido que o trabalho de cada site inicia a IA a partir da pasta do site dentro do worktree
- Depois de iniciar, você confirmou que as regras do site estão incluídas: Memory files em
/contextno Claude Code e a lista de arquivos de instruções ativos no Codex - Para o trabalho iniciado na raiz, você preparou uma forma de ver se as regras de pastas inferiores foram carregadas no meio da sessão (a linha
Loadeddo Claude Code, o hookInstructionsLoaded) - Você adicionou uma verificação que interrompe a publicação se algo fora das pastas atribuídas mudou, e a viu parar diante de uma alteração proposital fora do escopo
- Você escreveu o escopo de cada worktree com / final e fez a verificação parar quando falta o arquivo de escopo
- Você negou com bloqueios da ferramenta a escrita fora do escopo e no arquivo de escopo
- Você escreveu nas regras um procedimento para comparar a URL remota e o commit raiz com a produção antes de mover ou excluir uma pasta, e para mover em vez de excluir
- Você escreveu nas regras os comandos que mostram só os nomes das variáveis de ambiente, e negou com bloqueios da ferramenta os comandos que exibem valores
Exemplo de texto para os documentos de regras (pronto para usar)
## Regras ao trabalhar com vários projetos
- O escopo deste worktree são só as pastas listadas em .agent-owner. Não altere arquivos fora delas
(alterações fora interrompem a verificação da publicação)
- Antes de mover ou excluir uma pasta, compare git remote get-url origin e
git rev-list --max-parents=0 HEAD com a produção (cuidado com clones rasos).
Mova em vez de excluir, e registre como restaurar
- Veja só os nomes das variáveis de ambiente. Não use env, printenv, docker inspect (sem --format) nem
docker compose config (sem --no-interpolate)
Escreva os documentos não como um meio de fazer cumprir, mas como uma explicação, para que, quando algo parar, a IA entenda por quê e escolha o procedimento certo.
Resumo
- Se você inicia a partir da raiz, as regras colocadas na pasta de cada site não são carregadas pelo Claude Code até ele tocar em arquivos daquela pasta, e não são carregadas automaticamente pelo Codex (a IA pode abri-las por conta própria, mas não há garantia)
- Em qualquer uma das duas ferramentas, iniciar a partir da pasta do site carrega as regras desse site desde o começo (com um worktree, inicie a partir da pasta do site dentro dele)
- Confira o que foi carregado ao iniciar com o
/contextdo Claude Code ou a lista de arquivos de instruções ativos do Codex, e o que o Claude Code carregou no meio da sessão com a linhaLoadedou o hookInstructionsLoaded - Transforme o que precisa ser cumprido em uma verificação automática que interrompa a publicação se algo fora das pastas atribuídas mudou, e sobreponha os bloqueios da ferramenta para pegar os problemas mais cedo
- Além disso, diferencie repositórios de nomes parecidos pela URL remota e pelo commit raiz, e veja só os nomes das variáveis de ambiente
Perguntas frequentes
P. Um CLAUDE.md colocado em um subdiretório é carregado?
R. Sim, mas não ao iniciar. O Claude Code carrega o CLAUDE.md de uma pasta quando o Claude lê, escreve ou edita um arquivo dentro dela. Nesse momento ele não aparece em Memory files no /context; em vez disso, surge no terminal uma linha Loaded com o caminho dele. Se você iniciar a partir daquela pasta, ele é carregado ao iniciar e aparece em Memory files.
P. Como faço o Codex ler um AGENTS.md de um subdiretório?
R. Inicie o Codex a partir daquela pasta (na CLI, codex --cd <pasta>). Ao iniciar, o Codex lê os AGENTS.md da raiz do projeto até a pasta de inicialização, e não procura abaixo dela. Se você iniciar a partir da raiz, o AGENTS.md de uma pasta inferior é lido se a IA o abrir por conta própria, mas a documentação oficial não oferece nenhuma configuração que o carregue com certeza.
P. Em um monorepo, devo reunir os documentos de regras em um único arquivo na raiz?
R. A documentação das duas ferramentas recomenda colocar na raiz as regras de todo o repositório e na pasta de cada site as regras específicas dele. No entanto, as regras de um site podem não ser carregadas se você não iniciar a partir daquela pasta, então o que causaria problemas se fosse ignorado deve sair dos documentos e ir para a verificação da publicação ou para os bloqueios da ferramenta.
P. Como faço o Claude Code ler tanto o CLAUDE.md quanto o AGENTS.md?
R. Por padrão, se houver um CLAUDE.md, .claude/CLAUDE.md ou CLAUDE.local.md na pasta de inicialização ou acima dela, o AGENTS.md não é lido. Importe-o com uma única linha @AGENTS.md no CLAUDE.md, ou defina Project instructions em /config como claude-md-and-agents-md.