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 seguindo o padrão de código do repositório
Resposta rápida

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.md no Windows, /Library/Application Support/ClaudeCode/CLAUDE.md no macOS e /etc/claude-code/CLAUDE.md no 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
Pré-inscrição Formação Claude Code

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.md do 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

  1. Rode o /init e 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

  1. Escreva a precedência explícita no CLAUDE.md do 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

  1. Distribua a convenção local em CLAUDE.md de 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

  1. Use .claude/rules/ com paths pra 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

  1. 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

  1. 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

  1. 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:

  1. Hook PreToolUse pra 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

  1. Hook PostToolUse pra 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

  1. 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.



Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares