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

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+Tabcicla os modos de permissão, e prefixar o prompt com/planaplica plan mode àquele pedido - Saber que existe checkpoint: o Claude Code cria um checkpoint a cada prompt enviado
- Saber abrir o menu de rewind:
/rewindouEscduas 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
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?
- 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
- 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
- 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
- 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).
- 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
- 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
- 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
- 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"
- **Saiba a diferença entre
Bash(rm *)eBash**
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
- 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
- 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
- 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
- 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.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
Bateu o limite de uso do Claude Code? Como retomar a tarefa sem refazer tudo
Bateu o limite de uso do Claude Code? Veja como retomar a tarefa de onde parou com /usage, CLAUDE.md e --continue, sem refazer nada.
Como pagar o Claude Code no Brasil: cartão, dólar, IOF e quanto fica em reais
Claude Code preço Brasil na prática: câmbio, IOF de 3,5% e quanto fica na fatura. Planos Pro e Max convertidos em reais e como pagar com cartão.
Como instalar uma skill no Claude Code: passo a passo
Saiba como instalar skill no Claude Code: use a pasta pessoal para todas as sessões ou a pasta de projeto para versionar. Frontmatter YAML é obrigatório.
