Claude Code criou de novo uma função que já existia? Como evitar código duplicado no projeto

Claude Code código duplicado: como evitar reescrever funções já existentes no projeto
Resposta rápida

Claude Code código duplicado quase sempre é falta de visão, não falta de capacidade: se o arquivo original nunca entrou no contexto da sessão, o agente escreve do zero uma função que o projeto já tinha. A correção tem três camadas: abrir a tarefa em plan mode (Shift+Tab ou /plan), pedir exploração da base com o subagente Explore antes de qualquer escrita, e gravar a regra de reuso no CLAUDE.md da raiz para ela sobreviver à próxima sessão. Depois, /simplify ou /code-review no diff pegam o que passou.

Você abre o diff e lá está: uma função novinha, nome diferente, fazendo exatamente o que o utilitário do projeto já fazia há um bom tempo

A sensação é de que o agente ignorou seu código de propósito

Mas não é bug do seu projeto, e nem birra do modelo

É comportamento conhecido: quando o agente não enxerga o que já existe, ele resolve o problema do jeito mais barato que conhece, escrevendo do zero

O Nik Haldimann escreveu sobre isso na newsletter Next Generation Of, em 4 ways to combat Claude’s code duplication, separando a duplicação em dois eixos: a dificuldade de reusar código de biblioteca que já está lá, e a dificuldade de extrair uma biblioteca nova quando o padrão se repete

A boa notícia é que a correção mora em dois lugares bem concretos: no jeito que você monta o pedido, e na configuração do repositório

Bora destrinchar por sintoma? 🙂

Sintoma 1: o agente criou uma função que já existia em outro arquivo

O sintoma é fácil de reconhecer: formatCurrency nasce em src/checkout/, com a mesma lógica do formatMoney que mora em src/utils/ desde sempre

Mesma coisa, nome diferente, arquivo diferente

Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 116 aulas
  • 4 projetos
  • 9h 23min

A causa: o arquivo original nunca entrou na janela de contexto

O agente não tem raio-x do repositório

Ele enxerga o que foi carregado na sessão, e só

Se src/utils/ nunca apareceu, para efeitos práticos aquele utilitário não existe

É como pedir pra um dev novo implementar uma feature sem dar acesso ao repo inteiro: ele vai escrever o que sabe escrever

A solução: exploração antes da escrita

O Claude Code tem um subagente nativo chamado Explore, que serve exatamente pra isso: buscar e entender uma base de código sem fazer alteração nenhuma (ele é read-only)

E ele aceita um nível de profundidade informado na chamada: quick pra buscas pontuais, medium pra uma exploração equilibrada e very thorough pra análise abrangente

Esse subagente roda em janela de contexto própria e devolve só o resumo pra conversa principal, o que evita entupir sua sessão com dump de arquivo

Depois, confere o que de fato foi carregado com:

/context

O /context mostra o que está na janela de contexto da sessão atual

Se o arquivo que você jurava estar lá não aparece, achou a causa raiz da duplicação

Esse mesmo raciocínio de "primeiro entender, depois mexer" é o que separa um agente útil de um gerador de gambiarra, e vale muito além da duplicação: é o mesmo problema de dar contexto de projeto pra um dev novo, só que com IA no lugar

Como prevenir

Tarefa de feature não começa no modo escrita

Começa em plan mode, que é o assunto do próximo sintoma

Sintoma 2: ele já começou a editar antes de olhar o projeto

O sintoma aqui é a primeira ação da sessão

Você manda o pedido, e a primeira ferramenta que aparece é Write ou Edit

Zero busca antes

A causa: nada no fluxo obriga a busca prévia

No modo padrão, escrever é permitido desde o primeiro token

Se o pedido não exige pesquisa e o fluxo não impede a escrita, o caminho mais curto vence

A solução: plan mode

No plan mode o Claude Code usa apenas ferramentas de leitura

A pesquisa da base vai pro subagente Plan, que explora em uma janela de contexto separada, enquanto a conversa principal fica somente leitura

Pra entrar, duas opções:

Shift+Tab

O Shift+Tab cicla entre os modos nessa ordem: default → acceptEdits → plan

Ou prefixa o prompt:

/plan refatorar o fluxo de checkout

E se você entrou sem querer, ou mudou de ideia no meio, Shift+Tab de novo sai do plan mode sem aprovar plano nenhum

Como prevenir

Adota plan mode como padrão de entrada em qualquer tarefa não trivial

Custa uns segundos a mais no começo e economiza aquele diff gigante que reimplementa metade do utils

Sintoma 3: a duplicação volta toda sessão nova

Esse é o mais frustrante

Você explica na conversa, ele entende, corrige, usa o utilitário certo

Aí você fecha o terminal

Na próxima sessão, função duplicada de novo 😛

A causa: a instrução morreu junto com o contexto

Correção dita no chat vale pra aquele chat

Sessão nova é página em branco, e tudo que você combinou evaporou junto

Esse é o mesmo motivo pelo qual tanta gente corre atrás de memória persistente pra agentes de IA: sem isso, você fica repetindo a mesma instrução pra sempre

A solução: CLAUDE.md na raiz

O CLAUDE.md é o arquivo markdown de instruções persistentes do projeto, do seu fluxo pessoal ou da organização, e ele é lido no começo de cada sessão

É ali que a regra de reuso precisa morar, e é exatamente a recomendação do artigo do Nik Haldimann: uma seção de instruções de reuso no CLAUDE.md da raiz do projeto

Se você ainda não tem um, tem atalho:

/init

O /init explora a base de código (arquivos de pacote, documentação existente, arquivos de configuração e estrutura) e gera um CLAUDE.md inicial com comandos de build, comandos de teste, visão da estrutura e convenções detectadas

Depois disso, dá pra conferir o que existe de memória com:

/memory

Ele lista CLAUDE.md, CLAUDE.local.md e outros locais de memória nos escopos de usuário e de projeto, incluindo entradas de arquivos que ainda nem existem

Tome cuidado com um detalhe: um CLAUDE.md que só existe na sua máquina resolve o problema pra você e pra mais ninguém

Como prevenir

Commita o arquivo no repositório

Assim a regra vale pro time inteiro, e não só pra quem lembrou de escrever

Como montar o pedido que força a busca antes da escrita

Agora a parte prática

Esse é o esqueleto de pedido que inverte a ordem natural do agente (que é escrever primeiro, olhar depois)

  1. Entra em plan mode antes de descrever a tarefa. Shift+Tab até chegar em plan, ou prefixa com /plan

O erro comum deste passo: descrever a tarefa inteira e só depois lembrar do plan mode, quando o agente já mandou o primeiro Write

  1. Pede a exploração da base explicitamente, com nível de profundidade. O subagente Explore aceita quick, medium ou very thorough, e você escolhe conforme o espalhamento da lógica
Antes de propor qualquer código, explore a base com profundidade
very thorough e me diga se já existe algo que faça formatação de
valor monetário, em qualquer pasta, com qualquer nome

O erro comum deste passo: usar quick numa base onde a lógica pode estar espalhada em vários módulos com nomes diferentes

  1. Exige a lista do que já existe ANTES de qualquer proposta. Não é enfeite: é o que te dá o material pra decidir entre reusar, estender ou criar

O erro comum deste passo: aceitar um "não encontrei nada parecido" sem olhar o que ele realmente carregou (roda /context)

  1. Só então aprova a escrita. Com a lista na mão, você aponta o arquivo que deve ser reaproveitado em vez de deixar a decisão no automático

O erro comum deste passo: aprovar o plano por cansaço, sem ler a parte em que ele diz "vou criar um novo helper"

  1. Revisa o diff depois de escrever. O /simplify roda agentes em paralelo que revisam o código alterado quanto a reuso, qualidade, eficiência e aderência ao CLAUDE.md, tudo em uma única passada, e pode ser anexado ao prompt depois de você fazer as mudanças
/simplify

O erro comum deste passo: rodar no meio da implementação, quando ainda tem metade do trabalho pra sair

  1. Se quiser um segundo par de olhos no diff, usa o /code-review. Ele checa o diff atual em busca de bugs de correção e limpezas, e aceita --fix pra aplicar os achados
/code-review --fix

Passando um número de PR, ele revisa o pull request em vez do diff local

O erro comum deste passo: usar --fix sem olhar o que foi aplicado depois

Onde escrever a regra de reuso: CLAUDE.md, regras por caminho ou subagente

Aqui muita gente trava, porque tem mais de um lugar possível

A escolha depende do tamanho do projeto e do tipo de tarefa

Cenário Onde a regra vive
Projeto pequeno, uma convenção só Seção de reuso no CLAUDE.md da raiz
Monorepo ou área específica Regra em .claude/rules/ com o campo paths no frontmatter, ou um CLAUDE.md por diretório
Tarefa que precisa explorar E modificar Subagente general-purpose
Tarefa só de entendimento, sem tocar em nada Subagente Explore (read-only)

Por que regra escopada por caminho ajuda tanto:

Uma regra com paths apontando pra algo como src/api/** fica fora do contexto quando você está trabalhando em outra parte da árvore

Ou seja: você não paga contexto por instrução que não tem nada a ver com a tarefa do momento

A doc recomenda commitar esses arquivos no repositório, pelo mesmo motivo do CLAUDE.md: regra que só existe local não é convenção de time

E onde esses arquivos ficam?

Dois escopos

Escopo de projeto: arquivos em .claude/ dentro do repo, e na raiz no caso de CLAUDE.md, .mcp.json e .worktreeinclude

Escopo global: ~/.claude/, valendo pra todos os seus projetos

No Windows, ~/.claude resolve pra %USERPROFILE%\.claude

E na hora de escolher o subagente:

Até aqui você viu dois: o Explore e o Plan

Mas tem um terceiro que entra justo quando a tarefa passa do entendimento

Se o pedido é "me diga se isso já existe", é Explore, que busca e entende sem alterar

Se é "acha e refatora", aí sim general-purpose, que cobre exploração mais modificação, raciocínio complexo e múltiplos passos dependentes

Cada subagente roda em janela de contexto própria e devolve só o resumo, o que é ótimo: a busca pesada não polui a conversa principal

Quando vale barrar a escrita com hook em vez de confiar no prompt

Tem uma diferença importante que vale internalizar

Prompt e CLAUDE.md orientam

Hook impede

Se o seu problema é "às vezes ele ignora a convenção", orientação resolve na maioria dos casos

Se o seu problema é "não pode, em hipótese alguma, criar arquivo novo nessa pasta", orientação não é garantia

Como o PreToolUse se encaixa nisso:

O hook PreToolUse roda depois que o Claude monta os parâmetros da ferramenta e antes do processamento da chamada

Ele casa com ferramentas nativas como Bash, Edit, Write, Read, Glob, Grep, Agent e WebSearch

Ou seja: ele está no lugar certo pra ver um Write chegando e reagir antes de qualquer coisa acontecer no disco

A decisão vai dentro de um objeto hookSpecificOutput, com quatro saídas possíveis: allow, deny, ask e defer, além da possibilidade de modificar o input

E tem precedência definida entre hooks: deny > defer > ask > allow

Na prática, o deny ganha de todo mundo, o que é exatamente o que você quer numa trava dura

O trade-off é honesto: hook é mais trabalho de configuração e mais atrito no dia a dia

Começa pelo CLAUDE.md

Se a duplicação insistir mesmo com a regra escrita e commitada, aí sim vale escalar pro mecanismo de bloqueio

O que fazer na próxima sessão

Se tem uma ideia pra levar deste post, é essa: duplicação é falta de visão, não falta de capacidade

O agente não reusa o que não enxerga

Então o roteiro pra sua próxima sessão é curtinho:

  1. Se o projeto ainda não tem CLAUDE.md, roda /init
  2. Adiciona a seção de instruções de reuso e commita o arquivo
  3. Abre a próxima tarefa em plan mode, com pedido explícito de exploração antes de qualquer proposta
  4. Passa /simplify no diff antes de abrir o PR

E se você não lembra o que tem disponível na sua instalação, tem um truque bobo que resolve: digita / no prompt vazio

Ele lista todos os comandos disponíveis, incluindo os customizados, os de plugin e os que vieram de MCP

É bem provável que você tenha coisa boa instalada e nem saiba 😀

Até o próximo post!

Perguntas frequentes

Por que o Claude Code cria uma função que já existe em outro arquivo do projeto?

Porque ele só enxerga o que foi carregado na janela de contexto daquela sessão, não o repositório inteiro. Se o arquivo com a função original nunca entrou em jogo, para efeitos práticos ela não existe, e o agente resolve escrevendo do zero. O Nik Haldimann descreve isso como um dos dois eixos de duplicação: dificuldade de reusar código de biblioteca que já está lá.

Como confirmar se o Claude Code realmente carregou um arquivo específico na sessão?

Digitando /context, que mostra o que está de fato na janela de contexto da sessão atual. Se o arquivo que deveria ter sido lido não aparece na lista, essa é a causa raiz de uma duplicação. É o comando certo pra checar antes de desconfiar do modelo.

O plan mode do Claude Code bloqueia qualquer edição de arquivo?

Sim, no plan mode o Claude Code usa apenas ferramentas de leitura, e a pesquisa da base de código fica a cargo do subagente Plan, em janela de contexto própria. Pra entrar, o atalho é Shift+Tab, que cicla entre default, acceptEdits e plan, ou prefixar o prompt com /plan. Apertar Shift+Tab de novo sai do plan mode sem aprovar plano nenhum.

Em qual pasta o CLAUDE.md precisa ficar para valer no projeto inteiro?

O CLAUDE.md fica na raiz do repositório, mesmo escopo de arquivos como .mcp.json e .worktreeinclude. Já as regras específicas ficam dentro de .claude/rules/ com escopo de caminho definido no campo paths. Existe ainda o escopo global em ~/.claude, que vale pra todos os projetos (no Windows isso resolve pra %USERPROFILE%\.claude).

Qual a diferença entre o subagente Explore e o subagente Plan no Claude Code?

O Explore é read-only e serve pra buscar ou entender código sem alterar nada, com três níveis de profundidade: quick, medium e very thorough. O Plan também é read-only, mas atua especificamente dentro do plan mode, pesquisando a base em uma janela de contexto separada enquanto a conversa principal permanece somente leitura. Já o general-purpose é o único dos três que também modifica arquivos, usado em tarefas com múltiplos passos dependentes.

Dá pra usar /simplify ou /code-review depois que o código duplicado já foi gerado?

Dá sim, os dois atuam sobre o que já foi escrito. O /simplify roda agentes em paralelo revisando o código alterado quanto a reuso, qualidade, eficiência e aderência ao CLAUDE.md numa única passada. Já o /code-review checa o diff atual atrás de bugs de correção e limpezas, podendo aplicar os achados direto com a flag –fix.



Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

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