Claude Code em projeto antigo: como fazer o agente respeitar o padrão de código que só aquele projeto usa

Claude Code em projeto antigo tende a reescrever no padrão moderno porque a convenção daquele repositório vive só no código, e o que entra em toda sessão são os arquivos de memória. A saída é declarar a regra: rodar /init, corrigir o que ele detectou errado, escrever a precedência explícita no CLAUDE.md do projeto, distribuir convenção local em CLAUDE.md de subpasta e em .claude/rules com o campo paths. Quando instrução não basta, um hook PreToolUse nega a edição com exit code 2 e o plan mode deixa o agente propor sem tocar na fonte
Você abre um projeto de dois anos atrás, pede uma correção pequena pro Claude Code e ele devolve o arquivo inteiro reescrito no padrão que ELE considera certo
Sintaxe nova, helper novo, estrutura nova
E nada disso combina com o resto do repositório…
Isso não é bug, é falta de contexto declarado: a convenção daquele projeto existe só dentro dos arquivos, e ninguém nunca escreveu ela em lugar nenhum que o agente carregue no começo da sessão
Aqui a gente vai ancorar essa convenção antiga, camada por camada, e decidir com calma quando aceitar a modernização e quando barrar
Por que o agente escreve moderno em projeto antigo
O que o Claude Code lê em toda sessão são os arquivos de memória CLAUDE.md, e eles moram em quatro lugares:
- política gerenciada (enterprise):
C:\ProgramData\ClaudeCode\CLAUDE.mdno Windows,/Library/Application Support/ClaudeCode/CLAUDE.mdno macOS e/etc/claude-code/CLAUDE.mdno Linux - memória do projeto:
./CLAUDE.md - memória do usuário:
~/.claude/CLAUDE.md - memória local do projeto:
./CLAUDE.local.md
Se o padrão do seu projeto não está em nenhum desses arquivos, ele simplesmente não chega ao agente como instrução
E tem um detalhe que explica MUITA briga de estilo: o carregamento desses níveis é aditivo
Que aditivo? Todos entram juntos, empilhados, e não existe uma regra dura de precedência entre eles
Domine o Claude Code do básico ao avançado
Você vai aprender a criar sistemas completos com Claude Code, sem precisar ser programador. Inscreva-se para ter acesso a um desconto de lançamento e bônus especiais!
Então quando a sua preferência global de usuário diz uma coisa e o projeto antigo pede outra, o resultado depende da interpretação do modelo
A saída recomendada pela documentação de memória é escrever a precedência de forma explícita, no arquivo mais específico
Ou seja: quem manda é o texto que você escreveu, não uma hierarquia mágica
O que você precisa antes de começar
Antes de sair criando arquivo, junta o básico:
- o repositório do projeto antigo aberto no Claude Code
- clareza sobre quais convenções são DE VERDADE do projeto e quais são só código velho que sobrou (isso muda tudo lá na frente)
- saber o que está escrito no seu
~/.claude/CLAUDE.md, porque as preferências globais entram na sessão junto com as do projeto - disposição de versionar o
CLAUDE.mddo projeto, igual você versiona qualquer outra doc
Esse ponto do arquivo de usuário costuma ser o furo silencioso: você escreveu ali uma preferência de estilo pensando no seu projeto principal e ela viaja pra todo repositório que você abre
Se isso é dor recorrente pra você, vale ler também sobre trabalhar em dois projetos ao mesmo tempo sem misturar contexto
Passo a passo: ancorar a convenção do projeto antigo
- Rode o
/inite trate a saída como rascunho
O /init faz o Claude Code explorar o repositório e escrever um CLAUDE.md inicial com comandos de build, comandos de teste, uma visão da estrutura e as convenções que ele detectou
É um baita atalho, mas é leitura de fora: ele infere convenção olhando o código
O erro comum deste passo: aceitar o arquivo gerado como verdade
Leia linha por linha e corrija o que ele leu errado, principalmente onde ele descreveu como convenção algo que era só um canto do projeto que ninguém arrumou ainda
- Escreva a precedência explícita no
CLAUDE.mddo projeto
Como os níveis são aditivos e não têm precedência automática, a frase precisa estar lá, escrita, no arquivo do projeto:
# Convenções deste projeto
Estas instruções do projeto sobrepõem qualquer padrão de nível de usuário conflitante.
- O padrão de estilo válido aqui é o que já está no código, não o mais moderno.
- Ao editar um arquivo, siga a forma usada nos arquivos vizinhos.
- Mudança de padrão não entra junto com correção de bug: é PR separado.
O erro comum deste passo: escrever só "siga o padrão do projeto" e achar que resolveu
Diga QUAL é o padrão, ou aponte pro arquivo que serve de referência
- Distribua a convenção local em
CLAUDE.mdde subpasta
O arquivo da raiz e os que estão acima do diretório de trabalho entram no início da sessão
Já o CLAUDE.md de subpasta carrega sob demanda: um app/api/CLAUDE.md só entra em contexto quando o agente lê um arquivo dentro de app/api
Isso casa direitinho com a orientação oficial pra repositório grande: a raiz guarda a estrutura de mais alto nível e as armadilhas críticas, as subpastas guardam a convenção local
O erro comum deste passo: empurrar toda a convenção do mundo pra raiz
Cada linha da raiz custa orçamento de contexto em TODO turno, então o arquivo curto com ponteiros vence o manual completo
- Use
.claude/rules/compathspra regra que só vale em alguns arquivos
Dá pra organizar as instruções em arquivos separados dentro de .claude/rules/, com descoberta recursiva de todos os .md (aceita subpasta, tipo frontend/ e backend/)
E dá pra limitar uma regra a arquivos específicos com frontmatter YAML:
---
paths:
- "src/api/**"
- "**/*.handler.ts"
---
# Padrão dos handlers legados
Os handlers desta pasta usam o formato antigo de retorno.
Não converta para o formato novo ao corrigir um bug.
A regra com paths só entra em contexto quando o agente lê um arquivo que casa com o padrão
O erro comum deste passo: usar paths pra regra que precisa valer sempre
Regra com paths e CLAUDE.md aninhado não são reinjetados automaticamente depois da compactação de contexto: eles só voltam quando o agente lê de novo um arquivo que casa
Se a regra é inegociável, tira o paths ou move ela pro CLAUDE.md da raiz
- Importe os guias longos com
@caminho/do/arquivo
O CLAUDE.md aceita importar outro arquivo com a sintaxe @path/to/import, com caminho relativo ou absoluto:
# Projeto legado
Estas instruções do projeto sobrepõem qualquer padrão de nível de usuário conflitante.
Guia de estilo completo: @docs/estilo-legado.md
Assim o arquivo principal continua magro e legível por humano, e o detalhe pesado fica onde deve ficar
O erro comum deste passo: transformar o CLAUDE.md em manual de 400 linhas achando que quanto mais texto, mais obediência
- Tire do caminho o que nem deveria ser lido, com o
claudeMdExcludes
Existe a configuração claudeMdExcludes, que pula arquivos por caminho ou por padrão glob pra que nunca sejam carregados
Ela é citada como útil justamente pra diretório de código legado ou subárvore vendorizada, aquele canto que ninguém mantém mais
Pensa numa pasta de vendor gigante que ninguém toca: não faz sentido gastar contexto ali 🙂
O erro comum deste passo: excluir uma pasta que ainda é mantida só porque o código dela é feio
Se o time ainda mexe naquilo, a pasta merece convenção escrita, não exclusão
- Quando a regra não pegar, confira com o
/memory
O /memory mostra quais arquivos de instrução estão carregados na sessão, com caminhos e ordem
É a ferramenta de diagnóstico pra parar de adivinhar: ou a regra está lá e o agente interpretou diferente, ou ela nunca entrou
São coisas MUITO diferentes, e o conserto de cada uma também
Quando a instrução não basta: hook e plan mode
Instrução é convite, não trava
Pra convenção que precisa acontecer SEMPRE, o caminho é outro:
- Hook
PreToolUsepra negar a edição
Hooks rodam de forma determinística em torno das ferramentas
Um hook PreToolUse inspeciona a chamada antes dela acontecer e pode negar, saindo com exit code 2
É o lugar de validação de caminho e de convenção de nome, aquilo que não pode passar nunca
- Hook
PostToolUsepra linter e formatador
O PostToolUse roda depois da ferramenta já ter executado, então ele não bloqueia
Mas ele mostra a saída de erro pro Claude, e aí o agente conserta o que quebrou
Rodar linter e formatador depois das edições é justamente o uso recomendado
- Plan mode pra ele propor antes de escrever
O plan mode faz o Claude Code pesquisar e propor mudanças sem editar o código: ele lê arquivos e roda comandos de exploração, e a fonte fica intacta
Atalho: Shift+Tab, que cicla entre os modos na ordem default, acceptEdits e plan
Quando precisa entender o repositório ali, ele delega a pesquisa pro subagente Plan, que é embutido e mantém a saída da exploração numa janela de contexto separada
E tem o Explore, também embutido e somente leitura, voltado a busca no código: perfeito pra mapear qual é o padrão REAL do repositório antes de você escrever a regra
Se subagente ainda é território novo pra ti, dá uma olhada em quando usar subagentes no projeto
Quando aceitar a modernização (e quando barrar)
Aqui mora a parte que ninguém automatiza: a régua NÃO é a idade do código, é a intenção do time
| Situação | Decisão | Onde escrever |
|---|---|---|
| Convenção que é decisão viva do projeto | Barra a modernização | Regra dura no CLAUDE.md do projeto (ou .claude/rules/ com paths) |
| Código velho que ninguém mantém mais | Tira do caminho | claudeMdExcludes, que pula arquivos por caminho ou glob |
| Melhoria que o time já quer adotar | Aceita | Atualiza o CLAUDE.md junto com a mudança |
Quando barrar:
Barra quando a forma antiga é decisão viva, não descuido
Aquele retorno esquisito do handler que existe porque três serviços dependem dele, o helper caseiro que ninguém troca porque o substituto moderno muda comportamento, a estrutura de pasta que o deploy espera
A pergunta que resolve: se um dev humano abrisse um PR mudando isso hoje, o time aprovaria?
Se a resposta é não, isso é regra dura no CLAUDE.md do projeto, com o motivo escrito do lado
Motivo escrito importa MUITO: sem ele, daqui a seis meses alguém (ou o agente) vai achar que é só código velho e vai mexer de novo
Quando aceitar:
Aceita quando a modernização é justamente pra onde o time já decidiu ir
Os casos típicos: migração que já começou em parte do repositório e você quer que o resto siga, correção de algo que só era daquele jeito por limitação antiga, ou padrão que ninguém defende, só ninguém teve tempo de trocar
Aceitar não é dar carta branca no meio de um bugfix
O combinado que funciona é separar: correção vai num PR, mudança de padrão vai em outro, e o CLAUDE.md muda junto com o segundo
E quando aceitar, ATUALIZA o arquivo no mesmo movimento
Convenção que muda no código e não muda no CLAUDE.md vira instrução mentirosa em duas semanas
Aliás, esse é o momento certo pra revisitar o arquivo depois de troca de modelo também: instrução escrita pra contornar limitação de modelo antigo é candidata natural a sair
A regra existe mas o agente ignorou: o que checar
Ele obedeceu no começo e esqueceu depois:
Clássico de sessão longa
Regra com paths e CLAUDE.md aninhado não voltam sozinhos depois da compactação de contexto: eles só reaparecem quando o agente lê de novo um arquivo que casa com o padrão
Conserto: tira o frontmatter paths ou move a regra pro CLAUDE.md da raiz
A regra do projeto perdeu pra sua preferência global:
Lembra que os níveis são aditivos e sem precedência automática?
Então em caso de conflito o resultado depende da interpretação do modelo
Conserto: a frase de precedência explícita no arquivo do projeto, tipo "estas instruções do projeto sobrepõem qualquer padrão de nível de usuário conflitante"
A regra nunca entrou em contexto:
Se ela está num CLAUDE.md de subpasta, ela só carrega quando o agente lê um arquivo daquela pasta
Se ele mexeu em outra parte da árvore, a regra nunca esteve lá pra ser obedecida
Conserto: roda o /memory e olha o que está carregado de verdade, com caminho e ordem
E pra prevenir os três: arquivo conciso (cada linha custa contexto em todo turno), edição do CLAUDE.md revisada em pull request igual qualquer outra documentação, e uma revisita depois de troca de modelo
Esse último é sutil: instrução escrita pra contornar limitação de modelo antigo vira peso morto depois, ocupando espaço sem entregar nada
Conclusão
Convenção antiga só sobrevive se estiver ESCRITA e versionada junto do código
Enquanto ela viver só na cabeça de quem estava no projeto há dois anos, o agente vai continuar propondo o padrão que ele acha certo, e a culpa não é dele
Próximo passo concreto pra hoje: roda o /init no projeto antigo, corrige na mão o que ele detectou errado e adiciona a frase de precedência no CLAUDE.md do projeto
Depois disso, decide conscientemente sobre a memória automática, aquele recurso em que o Claude Code guarda notas próprias sobre o projeto entre sessões, com liga/desliga dentro do /memory
Em repositório antigo, nota automática pode ajudar bastante ou pode fossilizar um entendimento errado do padrão, então essa é uma escolha pra fazer olhando, não no automático
Bora ancorar essa convenção? 😀
até o próximo post!
Perguntas frequentes
Como faço o Claude Code parar de reescrever código antigo no padrão moderno?
Escreva a convenção explícita no CLAUDE.md do projeto, dizendo que o padrão válido é o que já está no código, não o mais recente. Como os níveis de memória são aditivos e não têm precedência automática, essa frase precisa estar no arquivo, do jeito que o texto exemplo do post mostra: ‘estas instruções do projeto sobrepõem qualquer padrão de nível de usuário conflitante’.
O CLAUDE.md do usuário (~/.claude/CLAUDE.md) atrapalha um projeto antigo?
Pode atrapalhar sim, porque o carregamento é aditivo: a memória do usuário entra na sessão junto com a do projeto, sem regra dura de qual vale mais. Se você tem uma preferência de estilo moderna escrita ali pensando no seu projeto principal, ela viaja pra todo repositório que abrir, inclusive o legado.
Dá pra ter uma regra que vale só pra uma pasta específica do projeto?
Dá, usando um arquivo dentro de .claude/rules/ com frontmatter YAML e o campo paths, por exemplo paths: – "src/api/**". Essa regra só entra em contexto quando o agente lê um arquivo que casa com o padrão declarado.
Pra que serve o comando /memory?
O /memory mostra quais arquivos de instrução estão carregados na sessão atual, com caminhos e ordem. É a ferramenta de diagnóstico pra usar quando uma convenção não está sendo obedecida e você precisa entender de onde (ou se) ela está vindo.
Como evito perder uma convenção depois que o contexto compacta?
Regras com paths em .claude/rules/ e CLAUDE.md de subpasta não são reinjetadas automaticamente após a compactação: elas só voltam quando o agente lê de novo um arquivo que casa com o padrão. Se a regra é inegociável, tira o paths ou move ela pro CLAUDE.md da raiz, que carrega no início da sessão.
Quando vale aceitar a modernização em vez de barrar?
Vale aceitar quando a mudança é pra onde o time já decidiu ir: migração que começou em parte do repositório, ou padrão que só continuava ali por falta de tempo. A régua não é a idade do código, é a intenção do time, e ao aceitar você atualiza o CLAUDE.md no mesmo movimento, senão a instrução vira mentira em pouco tempo.
Dá pra excluir uma pasta inteira de código legado do carregamento do CLAUDE.md?
Sim, com a configuração claudeMdExcludes, apresentada no passo 6 do post: ela pula arquivos por caminho ou padrão glob pra que nunca sejam carregados. É citada como útil justamente pra diretórios de código legado ou subárvores vendorizadas, onde você não quer nenhuma inferência automática de convenção.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
As diferenças de var, let e const
Como fazer redirecionamento com PHP
Neste artigo você vai aprender a como fazer redirecionamento com PHP, utilizaremos abordagens fáceis de entender e de aplicar Fala programador(a), beleza? Bora aprender mais […]
ChatGPT: o que é, como usar, dicas e como acessar login
ChatGPT é uma ferramenta de processamento de linguagem natural (NLP) baseada na arquitetura GPT-3.5, desenvolvida pela OpenAI. Sua criação representa um marco significativo no campo […]
