Como pedir ao Claude Code para apagar código sem quebrar o que ainda está em uso

como apagar código com Claude Code sem afetar trechos ainda em uso
Resposta rápida

Apagar código com Claude Code fica seguro quando o pedido separa investigar de executar. Entre em plan mode (Shift+Tab ou /plan), peça primeiro o inventário de quem ainda chama aquele trecho delegando a busca ao subagente Explore, que é somente leitura, defina por escrito o que conta como "em uso" e dê um critério de parada: se houver qualquer chamador, lista e não apaga. Leia o plano (Ctrl+G abre no editor padrão) antes de aprovar. Se der ruim, /rewind ou Esc duas vezes com o campo vazio restaura conversa, código ou os dois. E git continua sendo a rede de verdade.

Fala aí, beleza? Tem um pedido curtinho que já quebrou muito projeto por aí: "apaga esse arquivo, não é mais usado"

Aí o Claude apaga, você roda o build e três imports em outro canto do projeto viram erro vermelho na sua cara 😅

O ponto é que o problema não é o Claude Code desobedecer, é justamente o contrário: ele obedece MUITO bem

Um pedido mal formulado é uma ordem clara de fazer besteira, e ele executa a ordem clara

Então a solução não é "confiar mais" nem "confiar menos", é escrever o pedido de um jeito que force a checagem de quem ainda usa aquele código ANTES de qualquer exclusão

É isso que tu vai levar daqui: o formato do pedido, os prompts prontos, a rede de segurança e o caminho de volta quando mesmo assim der ruim

O que ter pronto antes de pedir a remoção

Antes de sair mandando apagar, deixa essas coisas no lugar:

  • Projeto versionado em git, com o que tu tem hoje já commitado. Essa é a rede real, o resto é conforto
  • Saber entrar em plan mode: Shift+Tab cicla os modos de permissão, e prefixar o prompt com /plan aplica plan mode àquele pedido
  • Saber que existe checkpoint: o Claude Code cria um checkpoint a cada prompt enviado
  • Saber abrir o menu de rewind: /rewind ou Esc duas vezes com o campo de prompt vazio
  • Opcional, mas ajuda demais: um detector de código morto instalado no projeto (falo do Knip lá embaixo)

E agora a ressalva dura, que é a parte que as pessoas descobrem tarde:

Checkpoints só rastreiam mudanças feitas pelas ferramentas de edição de arquivo do Claude

Mudanças feitas por comandos Bash ou por processo externo ficam de fora

Ou seja: não trate o checkpoint como "ctrl+z universal", ele é um conforto dentro da sessão, e o git é o seguro de verdade

Se tu chegou aqui recentemente migrando do Cursor pro Claude Code, vale reservar uns minutos só pra pegar o jeito dos modos de permissão antes de mexer em exclusão

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

Passo a passo: como formular o pedido de remoção no Claude Code

A lógica de tudo que vem abaixo é uma só: separar investigar de executar

O pedido ruim junta as duas coisas numa frase ("apaga isso que não é usado") e o Claude só tem um caminho: acreditar em você e apagar

O pedido bom quebra em duas etapas e coloca um critério de parada no meio

Bora ver na prática?

  1. Entre em plan mode ANTES de qualquer coisa

Aperta Shift+Tab até chegar no plan mode, ou prefixa o pedido com /plan

No plan mode o Claude pesquisa e propõe as mudanças sem executar: as edições ficam bloqueadas até você aprovar o plano

O erro comum deste passo: mandar o pedido no modo normal "só pra ver o que ele acha", e ele já sair editando arquivo

  1. Peça o inventário de referências primeiro, não a remoção

A primeira mensagem não pede exclusão nenhuma, ela pede a lista de quem chama aquilo

E delega a busca ao Explore, o subagente embutido do Claude Code que é somente leitura, feito pra descoberta de arquivos, busca de código e exploração da base

Como ele é read-only, não tem como a etapa de investigação apagar nada por acidente, e isso já é meio caminho

O Explore trabalha com um nível de profundidade de busca: quick (busca pontual), medium (equilibrada) e very thorough (análise abrangente). Em remoção, peça o nível abrangente e aceite esperar um pouco mais

NÃO apague nada ainda.

Use o subagente Explore com profundidade very thorough para mapear
todas as referências a `formatInvoiceLabel` neste repositório.

Me devolva:
1. a lista de arquivos e linhas onde o símbolo aparece
2. onde você procurou (diretórios, extensões e padrões de busca usados)
3. o que você NÃO conseguiu cobrir com a busca

Sem conclusão de "pode apagar" nesta mensagem.

O erro comum deste passo: aceitar um "não achei nenhuma referência" sem exigir a lista dos lugares onde ele procurou

"Não achei" e "não existe" são coisas MUITO diferentes, e a diferença entre as duas é exatamente o escopo da busca

  1. Defina por escrito o que conta como "em uso"

Esse é o passo que quase todo mundo pula

Se você não desenhar a fronteira, o Claude vai usar a fronteira mais óbvia: import estático

E aí a chamada dinâmica, a string no arquivo de config e a rota registrada em runtime passam batidas

Para este projeto, considere "em uso" qualquer um destes casos:

- import ou require estático
- chamada dinâmica (import(), require em variável, acesso por chave de objeto)
- nome citado como string em arquivo de configuração
- rota, comando ou job registrado por nome
- export consumido fora deste pacote (API pública)
- uso em teste, fixture, mock ou snapshot
- citação em documentação e em script do package.json

Se cair em QUALQUER um desses casos, trate como em uso.

O erro comum deste passo: assumir que o Claude adivinha a fronteira do seu projeto. Ele não adivinha, ele infere, e inferência em exclusão custa caro

  1. Exija um critério de parada explícito

Essa é a linha mais importante do pedido inteiro

Sem critério de parada, o modelo tende a entregar o que você pediu ("o código removido"), porque é isso que parece sucesso

Com critério de parada, entregar a lista de chamadores TAMBÉM é sucesso

Critério de parada: se existir ao menos um chamador em qualquer
uma das categorias acima, NÃO remova nada.

Nesse caso, responda apenas com a lista dos chamadores e pare.

Se não existir nenhum, proponha o plano de remoção detalhando
arquivo por arquivo o que sai, e o que precisa ser ajustado junto
(imports órfãos, exports do index, entradas de config).
  1. Leia e edite o plano antes de aprovar

Dentro do plan mode dá pra abrir o plano proposto no seu editor de texto padrão com Ctrl+G e editar antes de aprovar

Isso é ouro em remoção: dá pra riscar do plano os arquivos que você quer manter, em vez de aprovar tudo e depois pedir pra desfazer metade

O erro comum deste passo: aprovar no automático porque o plano "parece razoável". Leia a lista de arquivos, ela é curta, é literalmente o que vai sumir do seu projeto

  1. Aprove sabendo o que a aprovação faz

Aprovar o plano encerra o plan mode e coloca a sessão no modo de permissão descrito na opção de aprovação que você escolheu, e é a partir daí que o Claude passa a editar

Quer voltar a planejar depois? Shift+Tab de novo, ou /plan no próximo prompt

O erro comum deste passo: aprovar e seguir mandando pedidos novos achando que ainda está tudo em modo de proposta. Não está mais, a sessão saiu do plan mode

  1. Confira o resultado e saiba o caminho de volta

Rodou o build, rodou os testes, olhou o diff

Se precisar voltar: /rewind, ou Esc duas vezes com o campo de prompt vazio

Já que teste entrou na conversa, vale lembrar que pedir teste ao Claude Code tem o mesmo vício de forma: pedido vago gera teste que só confirma o que o código já faz, e teste assim não segura remoção nenhuma

Modelos de pedido para cada tipo de remoção

A espinha é sempre a mesma (investigar, definir "em uso", critério de parada)

O que muda de caso pra caso é a pergunta de checagem, ou seja: onde o uso pode estar escondido nesse tipo de alvo

Alvo da remoção Pergunta de checagem que entra no pedido
Função exportada Quem importa, e o export aparece no index ou na API pública do pacote?
Arquivo inteiro Além dos imports, o caminho do arquivo aparece em config, script ou build?
Dependência do package.json O pacote é usado em código, em config de ferramenta ou só em script?
Feature flag e o código atrás dela Onde a flag é lida, e o caminho "desligado" tem efeito colateral?
Pasta legada Alguma coisa de fora da pasta ainda entra nela, e alguma coisa de dentro é exportada?

Apagar uma função exportada

NÃO apague ainda. Explore com profundidade very thorough:
quem consome `formatInvoiceLabel`, incluindo re-export em index,
chamada por string e uso em testes?

Se houver qualquer consumidor, liste e pare.

Apagar um arquivo inteiro

Aqui a busca por símbolo não basta, o que segura o arquivo pode ser o caminho dele

NÃO apague ainda. Explore com profundidade very thorough:
o caminho `src/legacy/report-builder.ts` aparece em algum import,
em config de build, em script do package.json ou em documentação?

Liste cada ocorrência com arquivo e linha. Se houver qualquer uma, pare.

Remover uma dependência do package.json

NÃO altere o package.json ainda. Explore com profundidade very thorough:
onde `date-fns` é usado neste repositório, separando
(a) uso em código, (b) uso em arquivo de configuração de ferramenta,
(c) uso apenas em script.

Se aparecer em qualquer uma das três, liste e pare.

Remover uma feature flag e o código atrás dela

Esse é o mais traiçoeiro, porque remover a flag muda comportamento mesmo quando ninguém "importa" nada

NÃO apague ainda. Explore com profundidade very thorough:
onde a flag `NEW_CHECKOUT` é lida (código, config, variável de ambiente,
testes) e qual caminho roda quando ela está desligada.

Me diga qual comportamento muda se eu remover a flag e manter só um dos
caminhos. Não proponha remoção nesta mensagem.

Apagar uma pasta legada

NÃO apague ainda. Explore com profundidade very thorough a pasta `src/old/`:

1. o que de FORA da pasta importa algo de DENTRO dela
2. o que de DENTRO da pasta importa algo de FORA (para eu saber o que fica órfão)
3. o caminho da pasta aparece em config, build ou script?

Se o item 1 tiver qualquer resultado, liste e pare.

Como transformar a regra em padrão do projeto (para não repetir o pedido)

Repetir esse pedido inteiro toda vez é chato, e o que é chato a gente pula

Então escreve uma vez e deixa fixado: o CLAUDE.md é um arquivo markdown na raiz do projeto que o Claude Code lê no início de toda sessão, e serve exatamente pra isso, padrões de código, decisões de arquitetura e checklist de revisão

Se você não lembra onde estão seus arquivos de memória, o comando /memory lista os arquivos (CLAUDE.md, CLAUDE.local.md e outros) nos escopos de usuário e de projeto

Um protocolo de remoção enxuto no CLAUDE.md:

## Protocolo de remoção de código

1. Toda remoção começa em plan mode, nunca no modo normal
2. Antes de propor exclusão, mapear referências e me mostrar onde a busca olhou
3. Conta como "em uso": import estático, chamada dinâmica, string em config,
   rota/job registrado por nome, export público, teste, fixture, script do package.json
4. Se houver qualquer chamador: listar e parar, sem apagar
5. Remoção e refactor não entram no mesmo plano

E aqui vai a ressalva que faz diferença de verdade:

Explore e Plan pulam os arquivos CLAUDE.md e o git status da sessão pai pra ficarem mais rápidos e mais baratos

Ou seja: aquela regra linda que você escreveu na raiz do projeto NÃO chega automaticamente no subagente que está fazendo a busca

Então continue colocando a fronteira de "em uso" e o critério de parada no texto do pedido quando delegar a investigação

O CLAUDE.md é o padrão da sessão, não é o briefing do subagente 😉

Rede de segurança: permissões e hooks que barram a exclusão errada

Prompt bom evita o erro, guarda-corpo evita o estrago

As duas coisas juntas é que dão sossego

  1. Entenda a ordem de avaliação das permissões

O Claude Code avalia as regras na ordem deny, depois ask, depois allow, e a primeira correspondência decide, independentemente de qual regra é mais específica

Isso muda a forma de pensar: não é "a regra mais detalhada ganha", é "quem casa primeiro na ordem ganha"

  1. **Saiba a diferença entre Bash(rm *) e Bash**

Regras de Bash casam com o texto inteiro do comando, e o * vale por qualquer texto

Uma regra escopada como Bash(rm *) mantém a ferramenta disponível e bloqueia as chamadas que casam

Já o nome puro Bash remove a ferramenta do contexto do Claude, o que é bem mais radical do que a maioria das pessoas quer

O erro comum deste passo: querer barrar só o rm e acabar tirando o Bash inteiro da jogada

  1. Não conte com exceção por allowlist

Uma regra deny ampla bloqueia todas as chamadas que casam, inclusive as que também casam com uma regra allow mais estreita

Traduzindo: deny amplo tipo Bash(aws *) vence allow estreito tipo Bash(aws s3 ls), e não existe "deny em tudo, menos nisso aqui"

Se você precisa liberar um caso específico, o deny amplo não pode existir

  1. Use um hook PreToolUse quando a regra precisa de lógica

O hook PreToolUse pode bloquear uma chamada de ferramenta retornando permissionDecision igual a deny: o Claude Code cancela a chamada e devolve o permissionDecisionReason ao Claude

Isso é útil porque a razão volta como texto, então dá pra explicar pra ele o motivo em vez de só travar

{
  "hookSpecificOutput": {
    "permissionDecision": "deny",
    "permissionDecisionReason": "Remocao de arquivo exige plano aprovado com lista de chamadores"
  }
}

O hook aceita allow, deny ou ask em permissionDecision

  1. Lembre que as regras mandam mais que o hook

Regras deny e ask valem independentemente do que o hook retornar: um deny que casa bloqueia a chamada, e um ask que casa continua perguntando mesmo se o hook respondeu allow

Então não tente "liberar" pelo hook o que você bloqueou por regra, não é assim que funciona

  1. Rode cada sessão no seu próprio git worktree

Um worktree é um diretório de trabalho separado, com arquivos e branch próprios, compartilhando histórico e remoto do mesmo repositório

Com uma sessão por worktree, as edições de uma sessão não tocam os arquivos da outra

Se você é do time que deixa duas ou três sessões rodando ao mesmo tempo, isso deixa de ser luxo e vira requisito, principalmente em tarefa de exclusão

Confirmando que o código realmente está morto com uma ferramenta externa

Tem uma diferença enorme entre o Claude dizer "parece não usado" e uma ferramenta determinística cuspir a lista

A ideia aqui é tirar a verificação da conversa e transformar em evidência

O Knip encontra arquivos, dependências e exports não usados em projetos JavaScript e TypeScript, analisando o package.json, o código-fonte e os arquivos de configuração

Instalação:

npm i knip

Ele traz mais de 150 plugins pra ferramentas e frameworks (ESLint, Jest, Next.js, Vite, Vitest, Storybook, Webpack, e por aí vai), que é justamente o que evita o falso positivo besta de "esse arquivo não é importado por ninguém" quando na verdade quem usa ele é a config de uma ferramenta

Se você ia procurar pelo ts-prune, se liga: o repositório nadeesha/ts-prune foi arquivado em 17/12/2023, está em modo de manutenção, e o próprio projeto recomenda o Knip para projetos novos

E o pedido bom aqui é usar a saída da ferramenta como entrada do plano, não como veredito final:

Rode o detector de código morto do projeto e me traga a saída bruta.

Depois, para cada item apontado, verifique com o subagente Explore
(profundidade very thorough) se existe uso por string, config, rota
registrada por nome ou teste.

Monte a lista em dois grupos:
(a) confirmado morto, com a evidência de cada um
(b) apontado pela ferramenta mas com uso encontrado, com arquivo e linha

NÃO apague nada nesta mensagem.

Dois olhos diferentes olhando: ferramenta estática de um lado, busca semântica do outro

O que sobrevive aos dois, aí sim tem cara de código morto de verdade

Quando dá errado mesmo assim: como voltar atrás

Acontece, e é bom saber o caminho antes de precisar dele

Apagou e o build quebrou

Sintoma: import quebrado, símbolo não encontrado, teste vermelho logo depois da remoção

Causa: o inventário de referências foi feito com escopo estreito demais, ou nem foi feito

Solução: abre o menu de rewind com /rewind (ou Esc duas vezes com o campo de prompt vazio) e escolhe restaurar o código do checkpoint anterior à remoção. Depois refaz o pedido, agora exigindo a lista de onde a busca olhou

Apagou mais do que você pediu

Sintoma: o diff tem arquivos que não estavam no combinado

Causa: o pedido misturou remoção com "aproveita e limpa o resto", e o plano foi aprovado sem leitura

Solução: rewind pra antes daquele prompt e refaz em plan mode, usando Ctrl+G pra abrir o plano no editor e riscar o que não deve sair. Uma remoção por plano, sempre

Restaurou o código e a conversa ficou fora de sincronia

Sintoma: os arquivos voltaram, mas o Claude segue falando como se a remoção tivesse acontecido

Causa: você restaurou só o código, e o histórico da conversa continuou como estava

Solução: o menu de rewind permite restaurar só a conversa, só o código, ou os dois. Quando o descompasso incomoda, restaurar ambos é o que alinha as duas pontas

Detalhe importante: as opções de restaurar código só aparecem quando o checkpoint selecionado tem alterações de arquivo rastreadas

Prevenção, que é o que realmente importa

Checkpoints ficam salvos junto com a conversa e são apagados junto com as sessões depois de 30 dias

E eles não capturam mudanças feitas por comandos Bash ou processo externo, nem, normalmente, edições manuais feitas fora do Claude Code ou vindas de outras sessões rodando ao mesmo tempo

Juntando tudo: o rewind é conforto de curto prazo dentro da sessão

O git é a rede de verdade, e commit antes de limpeza é barato demais pra você não fazer

Conclusão

O pedido de remoção bom não é o mais educado nem o mais detalhado, é o que faz duas coisas simples:

separa investigar de executar, e dá ao Claude um critério de parada que aceita "não dá pra apagar" como resposta de sucesso

O resto é encaixe: plan mode na entrada, Explore read-only pra levantar as referências, fronteira de "em uso" escrita por você, plano lido antes de aprovar, detector externo confirmando, permissões e hook como guarda-corpo, git por baixo de tudo

Próximo passo prático? Escreve o protocolo de remoção no CLAUDE.md do teu projeto hoje, e testa esse formato na próxima limpeza que aparecer

Sempre entrando por plan mode, beleza?

até o próximo post! 😀

Perguntas frequentes

Como saber se o Claude Code apagou um arquivo que ainda estava em uso?

O jeito mais rápido é rodar o build ou os testes logo depois da exclusão, já que import quebrado aparece na hora. Se você usou o passo a passo com Explore e critério de parada antes de aprovar o plano, esse cenário fica raro, porque a checagem acontece antes da remoção, não depois.

Dá para desfazer uma exclusão que o Claude Code fez fora do plan mode?

Depende de como o arquivo foi apagado. Se foi pela ferramenta de edição do próprio Claude, o checkpoint criado naquele prompt entra no menu de rewind, acessível por /rewind ou Esc duas vezes com o campo de prompt vazio. Se a exclusão veio de um comando Bash ou de um processo externo, ela fica fora do checkpoint, e aí o git commitado é a única rede real.

O subagente Explore consegue apagar algum arquivo durante a investigação?

Não. O Explore é um subagente embutido do Claude Code somente leitura, feito para descoberta de arquivos, busca de código e exploração da base. Por ser read-only, ele pode mapear todas as referências a um símbolo sem risco de tocar em nada durante essa etapa.

Qual a diferença entre pedir a remoção manualmente e usar uma ferramenta como o Knip?

O pedido manual com Explore e critério de parada serve para casos pontuais, um símbolo ou arquivo específico que você quer avaliar antes de tirar. O Knip é uma ferramenta separada que varre o projeto inteiro (package.json, código-fonte e configuração) atrás de dependências e exports não usados, com plugins para ferramentas e frameworks como Next.js e Vite. As duas coisas se complementam: o Knip aponta candidatos, e o pedido bem formulado confirma se algum deles ainda tem uso não óbvio.

O checkpoint do Claude Code serve como backup de longo prazo?

Não, ele é conforto durante o trabalho da sessão, e não um backup. Os checkpoints ficam salvos junto com a conversa e vão embora quando a sessão vai, então quem garante a volta em qualquer prazo é o commit em git feito antes da limpeza.

Vale a pena usar plan mode toda vez que for pedir para apagar código?

Para exclusão, sim, porque o plan mode faz o Claude pesquisar e propor as mudanças sem executá-las, com as edições bloqueadas até você aprovar. Isso te dá a chance de abrir o plano no editor com Ctrl+G e riscar arquivos antes de qualquer coisa sair do lugar, o que é bem mais barato do que desfazer uma remoção já aplicada.



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