Carregador de Páginas

Seu CLAUDE.md está sendo ignorado — e não é culpa sua

Seu CLAUDE.md está sendo ignorado — e não é culpa sua

Foto: Google DeepMind via Pexels

Quatorze correções. Numa única sessão. Três agentes disparados em paralelo sem permissão — a regra dizia explicitamente para nunca fazer isso. O usuário rejeitou dois; os três já tinham executado. Vinte e sete mil tokens queimados antes de qualquer clique.

Nenhum desses números é meu. Todos vêm de issues públicas do repositório do Claude Code, e eu deixo o número de cada uma no texto. E se você chegou aqui, provavelmente já viveu a cena: você escreve a regra em maiúsculo, com NEVER, com MUST. O agente lê o arquivo no começo da sessão. Ele até confirma que entendeu. E aí faz exatamente o que você proibiu.

A reação padrão da comunidade é escrever um CLAUDE.md melhor. Mais enfático. Mais estruturado. Com mais bullets em caixa alta.

Essa é a parte que eu quero derrubar.

Instrução em arquivo de contexto não é garantia. É sugestão. Ela entra numa disputa de prioridade que você não arbitra e não vê. Se uma regra precisa valer, ela não pode morar dentro do modelo.

O placar: não é impressão sua, está documentado

Vale ancorar a dor em relato verificável, porque o primeiro instinto de todo dev é achar que escreveu mal a regra.

Repare no padrão. Não é o modelo sendo burro. É o modelo sendo obediente — a outra coisa.

O diagnóstico: sua regra compete com o system prompt (e perde)

A issue mais importante desse conjunto não é a mais dramática, é a mais precisa: a #27032, a mesma dos três agentes em paralelo. Ela descreve o mecanismo. Vale ler devagar:

"the model's built-in system prompts took precedence over user-defined CLAUDE.md instructions, even though the CLAUDE.md was read first and its rules are supposed to override defaults."

Traduzindo o termo antes de seguir: system prompt é a instrução base que a ferramenta injeta no modelo antes de você falar qualquer coisa — as regras de fábrica do produto, que você não escreveu e não lê.

O caso concreto é quase didático. O plan mode tem um system prompt que diz ao modelo onde gravar o arquivo de plano. O CLAUDE.md do usuário dizia, com todas as letras, para nunca usar aquele local. O modelo seguiu o system prompt.

Entenda o que isso significa na prática: seu CLAUDE.md não é uma configuração. É um participante numa negociação de prioridade contra instruções de fábrica que você não controla, não vê e não pode sobrescrever. Quando as duas discordam, o resultado é probabilístico. Às vezes você ganha. Às vezes 27 mil tokens evaporam.

Ninguém escreve CLAUDE.md com essa moldura na cabeça. Todo mundo escreve como se fosse um arquivo de config. É aí que a expectativa quebra.

O segundo inimigo: contexto longo não é memória

Tem uma camada abaixo dessa. A pesquisa de context rot da Chroma — o termo que a comunidade usa para a degradação do modelo conforme o contexto cresce — testou 18 modelos e chegou a uma conclusão que desmonta a intuição de todo mundo:

"model performance varies significantly as input length changes, even on simple tasks."

Duas coisas importam aqui, e as duas são desconfortáveis.

Primeiro, o que o paper efetivamente diz, na formulação deles: "models do not use their context uniformly; instead, their performance grows increasingly unreliable as input length grows". A moldura que eles usam é boa — a gente presume que o modelo trata o token 10.000 com a mesma confiabilidade do token 100, e essa presunção não se sustenta.

Daí sai uma conclusão que é minha, não do paper, e eu marco isso de propósito: se a confiabilidade cai conforme a entrada cresce, então "ainda cabe" não quer dizer "ainda funciona". A janela não encolhe — ela é fixa. O que muda é o quanto você pode confiar no que está lá dentro. O paper não afirma um ponto a partir do qual degrada, e eu também não vou inventar um.

Essa distinção não é preciosismo, ela muda o remédio. Se o problema fosse espaço, janela maior resolveria — e é exatamente isso que o mercado te vende a cada anúncio de "agora com 1 milhão de tokens". Não resolve, porque o gargalo é atenção sendo disputada por coisa irrelevante, e uma janela maior só te dá mais lugar pra enfiar irrelevância. Não é sobre caber. É sobre não estar lá.

Segundo, e mais contraintuitivo: os modelos foram melhor com o contexto embaralhado do que com texto coerente. Coerência lógica no meio do contexto piorou o desempenho. A conclusão que interessa pra nós é simples e amarga — colocar sua regra num documento longo e bem escrito não a protege. Pode até enterrá-la melhor. (Tudo nesta seção sai da pesquisa Context Rot, da Chroma.)

Aqui preciso ser explícito sobre uma sujeira que circula em português. Você vai achar blogs citando esse paper com "queda de 30%+" e "orçamento seguro de 150K–400K tokens". Esses números não estão no paper. Eu abri e conferi. São invenção de conteúdo de SEO citando um estudo que não leu — o que é, ironicamente, exatamente o problema que o artigo descreve.

Junte as duas camadas e você tem a descrição do inferno: uma regra que já perde para o system prompt, e que ainda por cima apodrece conforme a sessão avança. Um comentarista do Hacker News descreveu a sensação melhor do que qualquer paper: "Some bad idea gets embedded into the context that you just can't argue away". É relato de fórum, não estudo — mas todo mundo que usa agente em projeto de verdade reconhece a cena.

A virada: pare de pedir, comece a injetar

Quando eu aceitei que instrução é sugestão, a pergunta mudou. Não era mais "como eu escrevo isso de um jeito que ele obedeça?". Era: "como eu tiro essa regra de dentro do modelo?"

A resposta que eu construí não é um prompt melhor. É arquitetura. Ela roda hoje no meu monorepo, que é fechado — então eu vou descrever cada peça com nome e função, não pra você conferir o meu código, e sim pra você conseguir remontar a ideia no seu próprio harness. São quatro peças, e nenhuma delas é esperta.

1. Fatiar o sistema até a regra caber

São 12 micro-projetos independentes declarados em roteador/routes.json — cada um com sua memória, seus agentes, suas decisões arquiteturais. Nenhum deles sabe da existência do outro. Isso não é organização de pastas; é uma resposta direta ao context rot. Se o modelo degrada com volume, a defesa é reduzir o volume, não escrever melhor dentro dele.

2. Um roteador na frente de tudo

roteador/route_projetos.py responde uma pergunta antes de qualquer tarefa começar: qual é o menor pedaço do sistema que essa IA realmente precisa conhecer agora? Só aquela memória é carregada. O resto deixa de existir para o modelo naquele turno. Não tem como o agente estourar o escopo de um contexto que ele nunca recebeu.

3. Hooks como forcing function — este é o ponto

Se você for levar uma coisa só deste artigo, leve esta. O harness é a ferramenta que embrulha o modelo — o Claude Code, o Cursor — e decide o que ele vê. E hook é o gancho que essa ferramenta te oferece: código seu, disparado por ela em momentos fixos do ciclo, fora do modelo e antes de ele ter chance de opinar.

roteador/session_start_hook.py dispara no evento SessionStart e injeta a trava de rota antes do primeiro prompt existir. roteador/route_hook.py roda no UserPromptSubmit e reforça a rota a cada pedido, anexando o contexto do projeto no turno.

A diferença é toda aqui, e é uma diferença de categoria, não de grau: a regra não é pedida ao modelo, é injetada pelo harness. Ela não precisa sobreviver a 200 mil tokens de sessão nem vencer uma disputa contra o system prompt — ela chega novinha, no turno, por código determinístico. Se a instrução do usuário perde a queda de braço lá dentro, a saída é parar de depender da boa vontade do modelo e mover a regra para um lugar onde não existe boa vontade.

4. Verificar por código, não por confiança

roteador/validate_routes.py retorna 0 quando a estrutura está íntegra: todo caminho declarado no manifesto existe de fato. A estrutura é checada por um processo, não pela minha memória nem pela do agente. Somam-se a isso uma guarda cross-projeto (roteador/route_guard.py), que avisa quando o arquivo que está sendo salvo não pertence ao projeto roteado, e uma trilha de auditoria que registra qual rota foi escolhida e por quê.

Escrevendo este artigo, eu achei um furo no meu próprio hook

Não era pra essa seção existir. Ela existe porque, ao reler session_start_hook.py para escrever a seção acima, eu percebi que a tese do artigo estava passando por cima do meu próprio código.

O hook recebe do harness um campo source, que diz por que a sessão começou: startup, clear, resume ou compact. A versão que eu tinha injetava a trava em startup e clear, e ignorava resume e compact — os dois juntos, no mesmo if.

E aqui está a parte que me interessa: não foi esquecimento. As linhas logo acima documentavam a exclusão como decisão deliberada — a rota já tinha sido definida antes, injetar de novo só gastaria contexto e re-perguntaria à toa. O raciocínio estava escrito, era coerente, e eu concordo com ele até hoje. Metade dele.

Porque resume e compact não são a mesma coisa, e a diferença é exatamente a tese deste artigo:

Eu passei o artigo inteiro dizendo que regra que mora só no contexto não é garantia, e tinha uma trava de rota dependendo de sobreviver a uma compactação. Não dá pra escrever isso e deixar como está.

O estado agora, conferível no arquivo: startup/clear/source ausente continuam recebendo a trava completa (o texto longo, que lista os 12 projetos e manda perguntar ao dono se estiver ambíguo). resume continua sem injetar nada. E compact passou a receber um bloco novo e curto — uma reâncora, não uma trava: ela não re-pergunta do zero, ela manda reconfirmar qual rota já estava travada olhando o que sobrou do contexto, e só recorrer ao dono se a rota não sobreviveu ao resumo. Cabe em poucas linhas de propósito: o custo de reancorar tem que ser menor que o custo de misturar projeto.

Testado nos quatro source. O fail-open segue intacto — stdin com lixo, JSON quebrado, routes.json ilegível: o hook sai com exit 0 e sem output, porque um hook de contexto que derruba a sessão é pior que o problema que ele resolve. validate_routes.py: 0 erros.

Conto isso porque esconder seria mais fácil e bem menos útil. O furo não é um contraexemplo da tese — é a tese acontecendo comigo, num código que eu escrevi de propósito, com o raciocínio documentado, e que mesmo assim deixou passar exatamente a janela onde a regra evapora.

O que isso NÃO resolve (a parte que eu não vou vender)

Preciso ser direto sobre o limite, senão este artigo vira o mesmo hype que eu critiquei lá em cima, nos blogs que inventam número.

Eu não tenho benchmark. Não medi "redução de X% de alucinação". Não tenho antes-e-depois numérico. O que eu tenho é o comportamento: decisões mais consistentes, menos deriva de escopo, menos aquele momento de "por que você mexeu nesse arquivo?". E tenho as peças descritas com nome e função aqui em cima, pra você reproduzir a ideia no seu próprio harness — não pra você acreditar na minha. Se eu te desse um percentual aqui, ele seria inventado — e você deveria fechar a aba.

E eu não tenho tempo de estrada. Essa arquitetura macro/micro nasceu em 14/07/2026 — a mesma data em que escrevo isto. O repositório inteiro tem umas três semanas. Então não me leia como quem "provou" nada: o que está aqui é uma decisão arquitetural e o raciocínio por trás dela, não um resultado. Qualquer um que te venda vitória com dias de uso está fazendo o hype que este artigo tenta atacar, e eu não vou ser esse cara na minha própria série. O experimento completo é daqui a alguns meses, e ele vale mesmo que a resposta seja "não funcionou".

E hook não é milagre: o que ele injeta continua sendo texto, sujeito às mesmas leis probabilísticas de todo o resto. Ele muda as chances de forma estrutural. Não vira garantia de compilador.

Determinismo de verdade só existe onde você tem determinismo de verdade: permissões, validador, CI, teste. Se uma regra é inegociável, ela não é regra de prompt nem de hook — é gate.

Como aplicar isso amanhã, sem reescrever seu mundo

Você não precisa de 12 micro-projetos. Precisa da inversão. Na prática:

Perguntas frequentes

Então CLAUDE.md é inútil? Não. Ele é ótimo como default: encurta explicação repetida, alinha estilo, dá contexto de projeto. O erro é de expectativa — tratá-lo como config quando ele é sugestão de alta prioridade. Use pra preferência. Nunca pra o que dói.

Isso é bug do Claude Code? Não vão corrigir? As issues estão públicas e podem melhorar — a #27032 descreve uma precedência que parece corrigível. Mas o princípio arquitetural sobrevive ao patch: enquanto sua instrução for texto competindo com outro texto dentro de um sistema probabilístico, ela é sugestão. Isso vale pra Cursor, Copilot e pro que vier depois.

Hook não é só mais texto no contexto? Não sofre do mesmo problema? A pergunta certa, e a resposta honesta é: em parte, sim. O que o hook injeta continua sendo texto sujeito às mesmas leis. O que muda é o que deixou de ser probabilístico: a injeção. Não depende de o modelo lembrar, nem de a regra sobreviver à compaction — ela chega no turno, sempre, por código. Você troca "espero que ele lembre" por "o harness garante que chegou". O resto ainda é aposta, só que uma aposta com odds bem melhores.

Janela de contexto maior não resolve isso? Não, e essa é a confusão mais cara do nicho. A janela não encolhe nem "enche" — ela é fixa. O que muda é o quanto você pode confiar no que está lá dentro, e a pesquisa mostra que a confiabilidade cai conforme a entrada cresce (sem um ponto de corte conhecido — nem eu nem o paper temos esse número). O gargalo é atenção disputada por informação irrelevante, não espaço. Janela maior te dá mais lugar pra guardar irrelevância, não mais capacidade de ignorá-la. Por isso a defesa é subtrair contexto, não comprar contexto.

Vale a complexidade pra um projeto solo? Roteador e 12 projetos, provavelmente não. Um hook de SessionStart que injeta suas três regras inegociáveis: são poucas linhas e resolve a classe de erro mais cara, que é a deriva silenciosa. Comece pelo hook. Fatie quando a dor de escopo aparecer.

O placar, revisitado

Quatorze correções numa sessão. Três agentes que não deviam ter rodado. Uma tarefa de dez minutos que levou mais de uma hora. E, na minha própria casa, uma trava de rota que sumia justamente quando o contexto era reescrito.

Nada disso aconteceu porque as pessoas escreveram regras ruins. Aconteceu porque todas escreveram regras — quando o que precisavam era de restrições. Regra é texto pedindo licença dentro de um sistema probabilístico. Restrição é código, e código não tem opinião sobre a sua regra.

Seu CLAUDE.md está sendo ignorado. Não é culpa sua, e provavelmente também não é culpa dele: você está pedindo garantia a um arquivo que nunca teve poder de dar garantia nenhuma.

Pare de escrever melhor. Comece a construir pra fora.