CRangelP/codebase-cleanup
CRangelP/codebase-cleanup · 0 stars · 1 plugin
Marketplace
Install
/plugin marketplace add CRangelP/codebase-cleanupRun inside Claude Code, then install plugins from it. Check the repo's README before you run it.
Plugins 1
After adding the marketplace, install one with /plugin install <name>@codebase-cleanup.
- 1codebase-cleanupFour-phase codebase cleanup with a green gate before every commit.
/plugin install codebase-cleanup@codebase-cleanup
Files
English · Português ·
codebase-cleanup
Skill de limpeza de codebase para Claude Code. Trabalha em quatro fases, nessa ordem: remove código morto, consolida módulos rasos, reorganiza a estrutura de pastas e remodela o interior das funções que sobraram. Entre a primeira e a segunda entra a fase 1.5, que procura arquivos e funções duplicados — a mesma ideia implementada duas vezes com nomes diferentes — e entrega os pares como candidatos à consolidação. A ordem importa — organizar pastas antes de apagar o que está morto é arrumar lixo em gaveta bonita, e remodelar função dentro de módulo que a fase 2 vai consolidar é trabalho feito duas vezes.
A skill executa sozinha o que dá para executar com segurança. Ela para e
pergunta em quatro casos: na escolha do candidato de consolidação da fase 2,
porque fronteira de módulo é decisão de domínio, não de código; na confirmação
do plano de pastas da fase 3, antes de qualquer git mv; na fase 4, se a fila
tiver operação de tier B, que escolhe uma abstração ou um nome de domínio; e
logo no começo, se a árvore de trabalho estiver suja — aí você decide entre
git stash, commitar o que está pendente ou abortar, e nada acontece antes da
sua resposta.
Requisitos
- Claude Code com suporte a skills.
git— todo o trabalho acontece numa branchcleanup/YYYYMMDD, nunca na main. Sem repositório git — ou num repositório onde o primeiro commit ainda não foi feito — a skill só diagnostica: o rollback dela depende de ter um commit bom para onde voltar, egit initsozinho não dá nenhum.- Para projetos JS/TS: Node com
npx(o knip roda vianpx knip@6.32.0, versão pinada — nuncanpx knipsem versão). - Outros stacks usam as ferramentas de cada ecossistema (vulture, deadcode,
cargo-udeps, ReferenceTrimmer). O que faltar, a skill aponta em vez de
instalar por conta;
pip installsó com confirmação. - O gate (
scripts/gate.sh) detecta o stack pelo manifesto e roda typecheck + testes em JS/TS, Go, Rust, Python, JVM, Ruby e .NET. O toolchain precisa estar alcançável: no PATH na maioria dos stacks e, em Python, também vale$VIRTUAL_ENV/bin,.venv/bin,venv/binou os runnersuv runepoetry run(nessa ordem). Cada check roda sob um watchdog (GATE_TIMEOUT, 900s por padrão,0desliga): estourou o tempo, o gate sai 4 e vale como não conclusivo. Em JS/TS a saída da suíte é bufferizada e só aparece quando o comando termina — um teste que deixa um neto de processo segurando o pipe travaria o gate até esse neto morrer, e aí o watchdog não teria como agir. O gate avisa antes de começar; numa suíte longa ele fica mudo, e ficar mudo é o esperado, não sintoma de travamento. É script bash (o 3.2 do macOS serve); no Windows, use WSL.
Instalação
Como plugin, que é o caminho recomendado — dá versão, atualização e os guardas
do PreToolUse:
/plugin marketplace add CRangelP/codebase-cleanup /plugin install codebase-cleanup@codebase-cleanup
Atualizar depois é /plugin update codebase-cleanup@codebase-cleanup.
O escopo da instalação decide onde a skill existe, e o list não deixa isso
óbvio. Instalado de dentro de um projeto, o plugin fica com escopo local e
amarrado àquele diretório — em qualquer outro, claude plugin list continua
dizendo enabled, claude plugin details continua contando Skills (1), e o
modelo não vê skill nenhuma. Para valer em todos os projetos, instale com
--scope user; para conferir onde ele está de fato ativo, o que responde é o
projectPath em ~/.claude/plugins/installed_plugins.json.
Para um
time, declare no .claude/settings.json do repositório:
{
"extraKnownMarketplaces": {
"codebase-cleanup": {
"source": { "source": "github", "repo": "CRangelP/codebase-cleanup" }
}
},
"enabledPlugins": { "codebase-cleanup@codebase-cleanup": true }
}
Isso não instala nada na máquina de ninguém: cada pessoa é perguntada uma vez se confia e instala.
Copiar a pasta continua funcionando, e continua sendo uma skill:
# global (vale para todos os projetos) cp -R codebase-cleanup ~/.claude/skills/ # ou por projeto cp -R codebase-cleanup .claude/skills/
Copiada assim ela também carrega como plugin, porque .claude-plugin/ viaja
junto — o que muda é só de onde vem a atualização. Se você tem o pacote
codebase-cleanup.skill (um zip), descompacte direto no destino:
unzip codebase-cleanup.skill -d ~/.claude/skills/
Se você está migrando da cópia para o plugin, apague a cópia. As duas formas
carregam ao mesmo tempo e as duas trazem "dá uma faxina" na description. A
invocação explícita desambigua pelo namespace
(/codebase-cleanup:codebase-cleanup é sempre o plugin), mas o gatilho
automático fica em cima do muro e pode cair na cópia — que é a versão que você
instalou naquele dia, sem as fases e as correções que vieram depois:
rm -rf ~/.claude/skills/codebase-cleanup
A estrutura instalada:
codebase-cleanup/
├── SKILL.md instruções principais
├── AGENTS.md mapa de roteamento para agentes
├── README.md este arquivo
├── README.en.md versão em inglês
├── LICENSE MIT
├── CHANGELOG.md o que mudou em cada versão
├── .claude-plugin/
│ ├── plugin.json manifesto do plugin (nome, versão, licença)
│ └── marketplace.json catálogo, para instalar por /plugin install
├── agents/
│ ├── cleanup-phase-1.md fases 1 e 1.5
│ ├── cleanup-phase-2-survey.md candidatos de consolidação (só leitura)
│ ├── cleanup-phase-2-impl.md implementa o candidato escolhido
│ ├── cleanup-phase-3-survey.md plano de estrutura (só leitura)
│ ├── cleanup-phase-3-impl.md executa os movimentos aprovados
│ ├── cleanup-phase-4-survey.md fila de remodelagem (só leitura)
│ └── cleanup-phase-4-impl.md aplica tier A e o tier B aprovado
├── docs/
│ ├── plugin-spec-research.md o que é limite do host, conselho e hábito
│ ├── attribution-frontier.md o que a skill compra e o que o modelo já traz
│ ├── open-code-review-comparison-research.md complementaridade com OpenCodeReview
│ └── archify-folder-reorg-research.md Archify como mapa, não como Fase 3
├── hooks/
│ └── hooks.json registra o guarda no evento PreToolUse
├── references/
│ ├── gate.md o contrato do gate: exit codes, watchdog, scripts
│ ├── audit.md protocolo de auditoria da fase 1.4
│ ├── complementarity-opencodereview.md OCR opcional na branch cleanup/
│ ├── final-report.md o modelo do relatório e como preenchê-lo
│ ├── knip-config.md configuração do knip sem armadilhas
│ ├── duplication.md funções duplicadas e a regra do churn
│ ├── phase-2-consolidation.md protocolo de consolidação de módulos
│ ├── phase-3-structure.md padrões de organização de pastas
│ ├── phase-4-refactor.md protocolo da fase 4 e a rede por alvo
│ ├── refactoring-catalog.md as 11 operações, em dois tiers
│ └── other-stacks.md Python, Go, Rust, JVM, Ruby, .NET
└── scripts/
├── gate.sh typecheck + testes multi-stack, exit 0/1/2/3/4
├── guard.sh bloqueia os cinco comandos que o protocolo proíbe
├── test.sh roda as seis suítes em sequência
├── metrics.sh métricas de qualidade, exit 0/2/3
├── gate_test.sh testes de contrato do gate (stubs de toolchain)
├── guard_test.sh o que o guarda bloqueia e o que ele deixa passar
├── rollback_test.sh prova executável do protocolo de rollback
├── eval.sh o que o modelo faz lendo a skill (fora do test.sh)
├── metrics_test.sh casos do medidor, em repos sintéticos
├── coherence_test.sh invariantes de coerência entre doc e código
├── mutate.sh aplica uma mutação e prova que ela aplicou (STALE aborta)
└── mutation_test.sh muta regras de autoridade destrutiva; cada uma tem de reprovar
Para conferir a instalação, abra uma sessão nova (ou rode /reload-skills) e
veja se codebase-cleanup aparece na lista de skills disponíveis.
Testes
Seis suítes, sem dependência além de bash e git:
bash scripts/test.sh # roda as seis, para na primeira que falhar bash scripts/gate_test.sh # contrato do gate: exit codes, linha checks=, PARTIAL bash scripts/guard_test.sh # o que o guarda bloqueia, e o que ele deixa passar bash scripts/rollback_test.sh # o que `git restore` recupera e o que ele destrói bash scripts/metrics_test.sh # o medidor de qualidade, em repos sintéticos # fora do test.sh: roda o modelo de verdade, custa minutos e dinheiro bash scripts/eval.sh # o que o modelo faz lendo a skill bash scripts/coherence_test.sh # doc e código dizendo a mesma coisa bash scripts/mutation_test.sh # a suíte acima reprovaria se a regra sumisse?
A primeira execução do eval.sh baixa o knip@6.32.0 uma vez, para dentro de
~/.cache/codebase-cleanup-eval/.vendor/, e copia essa árvore para cada
fixture. É de propósito: a fase 1 roda npx knip@6.32.0, e sem cópia local
esse comando precisa do registry — um download dentro de uma run limitada por
--max-turns é tempo morto ou um vermelho que nada tem a ver com a skill. Sem
rede e sem a árvore, a suíte para antes de gastar o primeiro minuto de modelo,
em vez de descobrir isso no meio do caso.
Toda mutação feita à mão — para provar que um invariante morde, ou que um caso de
eval reprova quando a regra some — passa pelo mutate.sh, que aborta quando a
edição não mudou nada. A razão é assimétrica: a mutação cara é a que roda o
modelo contra a cópia mutada, e o modo de falha dela é silencioso na pior
direção — uma expressão que não casa faz a run acontecer contra o texto
original, o verde volta, e ele se lê como "o caso não morde" quando nada foi
mutado. O mutation_test.sh roda os pisos dessa guarda antes de tudo e para se
eles falharem.
Do lado do eval a mutação deixou de ser à mão:
EVAL_MUTATE='s/\Q<a frase>\E/<a troca>/' bash scripts/eval.sh yellow-run
A expressão é aplicada à cópia instalada dentro do fixture, nunca a este
repositório, e passa pelo mesmo mutate.sh. Uma expressão que não casa para a
suíte antes do primeiro minuto de modelo, em vez de devolver um verde sobre
uma mutação que nunca existiu. O procedimento antigo — copiar o repositório
inteiro, editar, conferir por grep, rodar a cópia — tinha os dois modos de
falha: a edição que não aplica e o SKILL_ROOT da cópia resolvendo para /.
14/14 mutações pegas afirma que a suíte percebe a edição — não que o
comportamento do modelo mudaria. São perguntas diferentes, e quando as duas
foram medidas no mesmo contrato deram respostas opostas: reescrever sozinha a
célula do RED na tabela de níveis não mudou nada (51/51 — a run recusou citando
um parágrafo três seções abaixo que a edição não tocou), e só reescrevendo as
quatro sedes juntas o comportamento se moveu (47/51, com três commits
assentados num repositório cujo portão dissera RED). A redundância que aquelas
runs revelaram está escrita na seção 16.7 do coherence_test.sh, porque
redundância que nenhuma suíte afirma é redundância que uma limpeza futura
remove.
Cada uma sai 0 quando tudo passou e imprime o caso que falhou quando não; o
test.sh só encadeia as seis e para na primeira vermelha.
Nenhuma das quatro toca o repositório em que você a rodou: o gate usa stubs de
toolchain, o guarda e o rollback criam repositórios descartáveis dentro de um
mktemp -d, com HOME redirecionado e identidade de commit passada por -c
— sua config do git não é lida nem escrita —, e a de coerência só lê arquivos.
A CI roda as seis suítes a cada push e PR: ubuntu (GNU timeout real,
procps) e macOS com o /bin/bash 3.2 de fábrica. As duas pernas são
necessárias, e não redundantes: no macOS os dois casos de timeout -k são
pulados e contados, então o total não se mexe e uma regressão no ramo 137 do
watchdog passa verde ali com o mesmo NN/NN. Por isso o resumo do
gate_test.sh nomeia o que a máquina não rodou — validação completa é nas duas
plataformas.
As suítes também rodam fora do macOS. Num container Linux, o caso de hang
exercita o GNU timeout real em vez do backend perl:
docker run --rm -v "$PWD":/repo:ro node:22-bookworm bash -c \ 'apt-get update -qq && apt-get install -y -qq procps && cd /repo && bash scripts/test.sh' # validado em 08/2026: 145/145 casos, 47/47 casos do guarda, 5/5 propriedades, # 37/37 casos de métrica, 525/525 invariantes, 14/14 mutações pegas
A heurística .NET foi validada contra o SDK real (mcr.microsoft.com/dotnet/sdk:8.0
e :10.0, 08/2026): dotnet test sem projeto de teste é mesmo no-op com exit 0
nas duas versões, e os templates xunit, nunit e mstest casam com os
marcadores — no 10.0 o mstest casa só pelo token MSTest.
A terceira transforma em teste o que antes dependia de reler tudo: o comando de rollback escrito igual em todo lugar, o contrato de exit codes do gate batendo com os READMEs, instrução velha que ficou para trás e árvore de arquivos que combina com o que existe no disco.
Nenhuma outra skill é obrigatória
A codebase-cleanup é autossuficiente por design. O pipeline chama
ferramentas (knip, similarity-ts, jscpd, gate.sh), não outras skills — e o
conhecimento que veio de skills de terceiros foi absorvido nos arquivos
desta: o protocolo de auditoria da fase 1.4 vive em references/audit.md, e
o vocabulário de consolidação da fase 2 em
references/phase-2-consolidation.md. Instalar as skills citadas nos
créditos não muda o comportamento em runtime; elas são fonte, não
dependência.
Vizinho opcional: OpenCodeReview
Esta skill e o OpenCodeReview
(OCR) da Alibaba resolvem trabalhos diferentes — são vizinhos, não
substitutos. A cleanup mexe na árvore (código morto, módulos rasos, pastas,
remodelagem local) atrás de gate e branch cleanup/. O OCR comenta risco e
defeito em diff/PR, linha a linha; não é o caminho para apagar o que o knip
ou o vulture marcam como inalcançável.
A skill não instala, chama nem embute o binário Go do OCR, nem copia
prompts ou regras dele. Quem quiser review de QA depois da faxina instala o
CLI por conta (Apache-2.0; requisitos como Git ≥ 2.41 e endpoint de LLM são
do OCR). A receita opcional — ocr review / ocr delegate contra a branch
cleanup/ — está em references/complementarity-opencodereview.md. O
relatório final pode citar esse passo sob "Optional next step"; nunca como
obrigação do protocolo.
O que o SKILL.md carrega, e o que ele adia
Todo byte do SKILL.md é pago em toda invocação: ele entra inteiro no
contexto quando a skill dispara, inclusive nas invocações que nunca chegam na
fase que aquele texto descreve. Os references/*.md só são lidos quando o
modelo decide abrir um. É a única alavanca que existe, e ela tem um preço: o
que desce para uma reference pode não ser lido.
Por isso o critério não é tamanho, é momento de leitura. Fica no SKILL.md
tudo que decide uma ação — os níveis, os checkpoints, o rollback, e cada regra
sobre o que a skill pode destruir. Desce o que só se consulta depois de um
resultado surpreender: a mecânica interna do gate, o modelo do relatório final,
o procedimento para um knip-report.json que uma run anterior deixou
rastreado.
A extração da v0.4.0 tirou 4.431 bytes: 45.672 → 41.241 (851 → 770 linhas).
Em tokens, que é a unidade que se paga, medido pelo host com
claude plugin details codebase-cleanup:
v0.3.5 44.801 bytes ~15,7k on-invoke (~370 always-on)
v0.4.0 41.241 bytes ~14,3k on-invoke (~370 always-on)
~1.400 tokens a menos em cada invocação naquela extração. As duas medições
têm bases de bytes diferentes de propósito: entre uma e outra o arquivo
cresceu com os consertos da #55, e esconder isso deixaria a extração parecer
maior do que foi. Desde então o SKILL.md voltou a crescer com as fases e as
regras medidas (hoje ~48 KB / ~880 linhas na v0.10.0): o critério continua sendo
momento de leitura, não um teto de bytes.
Vale registrar o erro da conta que antecedeu a medição. Estimando pela taxa média do arquivo (2,85 bytes/token) o ganho projetado era ~1.550 tokens, 11% acima do real. O texto extraído — comandos, tabelas, blocos de código — custa cerca de 2,54 bytes por token, bem mais denso que a prosa que ficou. Taxa média não estima corte específico, e a régua que vale é a do host.
O número sozinho não diz nada — o par diz, e a redução é resultado, não meta. Nada saiu "para ficar menor": bloco cuja pergunta de leitura não tinha resposta clara ficou onde estava.
Duas coisas garantem que a conta não seja uma mentira. A seção 21 do
coherence_test.sh percorre o grafo de referências a partir do SKILL.md e
reprova qualquer arquivo que ninguém aponta — uma reference órfã não é conteúdo
adiado, é conteúdo apagado com passos extras. E cada extração é asserida dos
dois lados: a regra que decide continua no SKILL.md, o procedimento chegou
inteiro no destino. Afirmar só um dos lados é como uma extração vira deleção
silenciosa.
Uso
Não existe comando obrigatório. A skill dispara quando o pedido soa como
limpeza: "dá uma faxina nesse projeto", "dá uma limpada", "tem coisa aqui que
ninguém usa", "remove as dependências mortas", "reorganiza essas pastas".
Também dá para invocar direto: /codebase-cleanup:codebase-cleanup instalada
como plugin (skills de plugin sempre levam o nome do plugin na frente), ou
/codebase-cleanup na instalação por cópia.
Pedidos parciais funcionam — "remove só as dependências não usadas" executa a categoria pedida e registra o resto como fora de escopo.
O que acontece ao rodar
Antes de qualquer coisa ela confere o terreno: se a árvore de trabalho tem
alteração não commitada, ela para e pergunta o que fazer (stash, commitar ou
abortar) em vez de arriscar o seu trabalho em progresso no primeiro rollback.
Com a árvore limpa, mede a rede de segurança do projeto com scripts/gate.sh
e se classifica em um de três níveis:
| Nível | Condição | O que ela faz |
|---|---|---|
| GREEN | typecheck e testes passam | executa a fase 1 sem perguntar; fase 2 e fase 3 param no checkpoint humano; a fase 4 aplica o tier A por alvo coberto e para no checkpoint do tier B |
| YELLOW | rede parcial, ou nenhum arquivo de teste no stack | só deps e arquivos órfãos, sem mexer em exports; não roda fase 2, fase 3 nem fase 4 |
| RED | sem testes e sem typecheck, ou baseline já vermelho | só diagnostica; nada é deletado; não commit de CLEANUP_PROGRESS |
Os caps por stack em references/other-stacks.md sobrescrevem a coluna GREEN
(Python confirma antes de deletar; JVM/Ruby/.NET código ficam em YELLOW ou só
diagnóstico por padrão).
Projeto que já chega com a suíte vermelha cai em RED, não em YELLOW: com o baseline quebrado não dá para separar o que a limpeza quebrou do que já estava quebrado, e como todo commit exige gate verde, nenhum deles aconteceria. A skill diz qual check falhou e para por aí.
Stack sem nenhum arquivo de teste não conta como testado: o gate não conta
suíte vazia, seja porque não a rodou, seja porque rodou e não voltou nada, e o
nível fica em YELLOW. Vale para JS/TS cujo runner sai com suíte vazia
("No test files found") — inclusive quando ele sai 0 porque mandaram, como em
--passWithNoTests, já que exit 0 não é prova de que uma suíte rodou —,
Go e .NET sem arquivo de teste, crate Rust sem
tests/*.rs nem #[test], build Maven ou Gradle sem nenhum src/test, Ruby
cujo spec/ ou test/ não guarda nenhum *_spec.rb, *_test.rb nem
test_*.rb (o padrão do Rake::TestTask), e pytest
que sai 5 sem coletar nada. Manifesto que está ali só por ferramenta —
um requirements.txt do build da documentação, um Gemfile do fastlane —
não é stack sem suíte: sem código daquela linguagem no repositório, o gate
não fala dele. Se a sua suíte mora fora do lugar padrão, a promoção é sua —
o gate não se promove sozinho.
Em JS/TS o placeholder exato do npm init (echo "Error: no test specified" && exit 1) também cai em YELLOW com a linha 'test' not counted e o marcador
npm init placeholder — não é RED de suíte quebrada. O mesmo cap pega a suíte
fatiada: sem script test, com test:unit e test:e2e no manifesto, nenhuma
fatia responde pela suíte inteira e o gate não conta nenhuma delas. Promover
à mão aqui é o caminho errado, porque a suíte não está fora do lugar, está
dividida; rode as fatias todas. Uma fatia
sozinha vale como a suíte, com uma exceção: modo watch nunca termina, então o
gate não o executa. watch, ui e debug são lidos como segmentos inteiros
do nome, o que pega test:watch:all e deixa test:watchdog em paz. Só que não
executar e não contar são coisas diferentes: watch e debug são um modo da
suíte, então test:watch ao lado de um test:unit sozinho deixa essa fatia
valendo como a suíte; test:ui pode muito bem ser uma suíte à parte, então ele
não roda e mesmo assim conta, e aí test:unit ao lado dele já é uma divisão.
Em repositório poliglota o cap sobrevive aos outros stacks. Go com testes ao
lado de uma metade JS que ninguém contou ainda imprime checks=typecheck,test,
porque cada palavra veio de um manifesto diferente — e aí o gate se recusa a
dizer GREEN, e nomeia o stack que ficou sem suíte.
Com o nível anunciado, ela cria a branch de limpeza e segue:
- Fase 1 — código morto. Configura o knip até os hints zerarem, roda em
modo produção e deleta em commits atômicos, um por categoria: deps não
usadas, arquivos órfãos, exports mortos. Antes da primeira mutação da
fase 1.3, grava um preview em
CLEANUP_PROGRESS.md(lista concreta por categoria, commit própriochore: preview phase 1 deletions) — no GREEN segue sozinha depois desse registro; no YELLOW (ou sob cap de stack) o preview omite o que o nível já proíbe e o que o usuário tirou de escopo — categorias fora do escopo do usuário ainda entram em Decisions. Cada passo faz stage só com pathspecs dos artefatos daquele passo (git add -- …, nuncagit add -A), e só entra com gate verde. No fim, produz uma auditoria do que sobrou (fase 1.4), com coverage mandate: cada unidade da varredura fecha comoreviewedouskippedcom motivo, e ocoverage_ratevai no log — taxa abaixo de 100% sem gap registrado em Decisions deixa o passo incompleto. - Fase 1.5 — funções duplicadas (fecha a fase 1). Varre funções com nomes diferentes fazendo a mesma coisa (similarity-ts ou fallow em JS/TS, jscpd nos demais stacks) e aplica a regra do churn: par que muda junto no git é duplicação real e vira candidato da fase 2; par que evolui separado é coincidência estrutural e fica em paz. O mesmo mandate de cobertura vale para cada par que o detector emitiu. Só relatório — nada é deletado aqui.
- Fase 2 — consolidação. Levanta até 5 candidatos de módulos rasos (começando pelos pares da fase 1.5), recomenda um e faz uma única pergunta. Respondeu "vai", ela implementa.
- Fase 3 — estrutura. Diagnóstico da árvore de pastas, plano, e movimentos
com
git mv, uma pasta por commit. - Fase 4 — remodelagem local. Herda alvos da auditoria 1.4 e dos pares da
1.5 que a fase 2 não consumiu, filtrados por churn. A rede de segurança é
por alvo (a função está coberta?), não pelo repositório inteiro. Tier A
corre sozinho — até 5 operações por sessão; tier B para no checkpoint e
aplica no máximo 1. Um
refactor(<operation-id>)por commit. Alvo sem cobertura: pula e registra, ou escreve um characterization test num commit próprio e segue — não há terceira saída.
O relatório final traz Residual risks: achados abertos da auditoria 1.4
que a limpeza não fechou, cada um com a severidade do audit (Critical /
High / Medium / Low) — não é uma segunda auditoria, é o que ficou
pendente. Quando a run deixou branch cleanup/, o sumário pode apontar um
passo opcional de review com OCR (seção Vizinho opcional);
nunca como etapa obrigatória.
Entre as fases a skill pede /clear — contexto acumulado de uma fase piora o
julgamento da seguinte. O progresso fica em CLEANUP_PROGRESS.md na raiz do
repo (incluindo Preview e Coverage), então a sessão seguinte retoma de onde
parou sem você reexplicar nada.
Em ambientes com subagentes, a skill roda como orquestrador e despacha cada
fase para um contexto descartável. Instalada como plugin, esses subagentes
vêm declarados em agents/: cleanup-phase-1 (fases 1 e 1.5), e um par de
survey e implementação para cada uma das fases 2, 3 e 4. Os de survey não
conseguem escrever — é assim que o checkpoint deixa de depender de boa
vontade: a pergunta chega até você antes de qualquer mudança, e a
implementação só começa depois da sua resposta. O protocolo está na seção
"Step 0.2" da SKILL.md.
Como reverter
Cada categoria vive num commit próprio. Se algo quebrar depois:
git log --oneline # na branch cleanup/YYYYMMDD git revert <sha> # desfaz só aquela categoria
O merge da branch é decisão sua, no seu tempo. A skill nunca faz push, nunca
commita na main e nunca usa git reset --hard — o rollback dela é
git restore --staged --worktree ., que joga fora tudo o que ainda não foi
commitado. Se um hook de segurança bloquear esse restore, a skill aborta
o pipeline (não contorna o hook): reporta a branch, a árvore suja e o comando
manual, e para.
Note o "tudo": alteração sua que estava no diretório antes de a skill começar
entraria nessa conta. É por isso que ela exige árvore limpa no início e
interrompe para perguntar quando não está — com a árvore limpa, o que o
rollback joga fora foi ela mesma que criou. O stage por pathspec (em vez de
git add -A) evita engolir rascunhos e .env locais no commit da categoria.
Os guardas
Instalada como plugin, essas proibições deixam de ser texto que o modelo pode
esquecer. hooks/hooks.json registra scripts/guard.sh no evento
PreToolUse, e ele barra cinco comandos antes de rodarem:
| Comando | Por quê |
|---|---|
git reset --hard |
levaria junto trabalho que estava na árvore antes da limpeza |
git clean |
apagaria arquivos não rastreados que precisam sobreviver: saída de ferramenta, caches, .env locais |
git push |
a skill nunca publica; o merge é decisão sua |
git commit na main |
todo o trabalho vive na branch de limpeza |
git add -A |
staging de árvore inteira engole no commit o que não é da categoria |
O guarda só acorda dentro de uma run: HEAD numa branch cleanup/, ou um
CLEANUP_PROGRESS.md não rastreado — que é o que uma run RED deixa, e o
que existe antes do primeiro commit. Log rastreado numa branch normal é
limpeza já mergeada, não run em curso, e aí ele volta a dormir; sem isso ele
ficaria ativo na main para sempre depois do primeiro merge. Fora disso esses
comandos são trabalho normal, e ele não diz nada.
Na dúvida ele libera. Sem repo, sem JSON, sem comando: sai 0 e cala. Um guarda
que bloqueia por engano é pior que guarda nenhum, porque a skill aborta o
pipeline quando um comando do protocolo é barrado — um falso positivo derruba
uma run legítima. O que ele bloqueia e o que ele deixa passar está em
scripts/guard_test.sh, incluindo git restore --staged --worktree .,
git revert, git mv, git stash push -u e o git add -- por pathspec.
Uma coisa esses 47 casos não alcançam, e vale saber qual: eles montam o JSON do
hook à mão e chamam o script, então provam o comportamento do guarda — não a
entrega. Que o matcher do hooks.json realmente encaminhe a chamada, e que o
exit 2 chegue ao modelo com o stderr junto, foi conferido à mão com o plugin
instalado, e não por suíte.
Como isso é a única perna do contrato que nenhuma suíte cobre, aqui está a
medição, feita num repositório descartável, dentro de uma branch cleanup/,
pedindo ao modelo exatamente o comando proibido:
Bloqueado pelo hook […] do codebase-cleanup:
git add -A(staging de árvore inteira) é proibido durante cleanup, para não engolir arquivo alheio no commit da categoria. Não vou contornar por outro caminho — bloqueio que disparou é decisão final. […] Para stage por pathspec:git add -- novo.ts
As três coisas que importam estão ali: o bloqueio chegou, a razão chegou junto, e o modelo ofereceu a forma correta em vez de procurar um contorno. É o que a distinção protege — um guarda que bloqueia sem entregar a razão vira um erro opaco, e um modelo que não lê a razão reformula o comando até passar.
Limites conhecidos
- O knip só cobre JS/TS. Nos outros stacks a confiança da deleção automática
cai junto com a qualidade do grafo da ferramenta — a tabela em
references/other-stacks.mddiz quando deletar e quando só diagnosticar. - Import dinâmico com string montada em runtime é invisível ao grafo. A skill
trata isso ensinando o knip (entry explícito) em vez de deletar, mas vale
revisar o
knip.jsongerado. - Nível RED devolve relatório, não limpeza. Cai aí quem não tem teste nem typecheck, e também quem chega com a suíte vermelha. Sem teste, o primeiro passo é criar uma verificação mínima; com a suíte quebrada, é consertar o check que o relatório nomeia.
- Exit 124 é reservado ao watchdog, igual ao GNU
timeout: um check que legitimamente sai 124 sob watchdog ativo é lido como TIMEOUT. Exit 137 vale o mesmo enquanto o watchdog roda com-k, porque é o código que a escalada kill-after produz contra um check que ignora TERM. - Com uma única
.sln/.slnxna raiz o gate a passa explícita aodotnet; com duas ou mais ele se abstém e invoca sem argumento, e a ambiguidade volta a ser do MSBuild. Falha fechada: rode o gate manual apontando a solução. - Crate Rust cujos testes existem só como doc-tests (ou gerados por macro)
cai no cap YELLOW — a evidência procurada é
tests/*.rsou#[test]no fonte. Promova à mão se a suíte vive em outro lugar. - Pasta sem git também cai em RED, mesmo com typecheck e testes passando. Sem commit não existe rollback, e é o rollback que sustenta a autonomia do resto do pipeline.
- A categoria de deps roda o install simples do gerenciador depois de podar o
manifesto, então o lockfile é reescrito e o
node_modulesé resolvido de novo. Essa parte fica fora do rollback: ogit restoretraz de volta opackage.jsone o lockfile, nunca a árvore instalada. Se for essa categoria que falhar, rode o install outra vez; as outras duas não mexem no manifesto e não precisam.
Créditos
Skills e materiais usados na construção desta:
- tech-debt-audit, de ksimback
(MIT) — o protocolo de auditoria da fase 1.4 (
references/audit.md) é destilado dela: as nove dimensões, o template do relatório e a seção obrigatória "parece ruim mas está ok". - codebase-design e improve-codebase-architecture, de Matt Pocock — o vocabulário de análise da fase 2 (module, interface, implementation, depth, seam, adapter, locality), o teste da deleção e a definição de módulo raso vêm dessas skills. Os conceitos de seam e profundidade de módulo remontam a Michael Feathers e a John Ousterhout (A Philosophy of Software Design).
- skill-creator, plugin oficial da Anthropic — conduziu a revisão de boas práticas, os evals comparativos e a otimização da description desta skill.
- Signs of AI writing,
do WikiProject AI Cleanup da Wikipedia — base da adaptação local
humanizer-pt-br, usada na escrita deste README.
Ferramenta complementar (opcional, sem vendoring):
- OpenCodeReview (Alibaba,
Apache-2.0) — não embutido aqui; a disciplina de review dele (preview
antes do gasto, checklists de cobertura, severidade nos achados) informou
as seções nomeadas de preview, coverage mandate e residual-risks deste
protocolo. A documentação pode citar o CLI como passo opcional depois da
branch
cleanup/; a receita fica emreferences/complementarity-opencodereview.md.
Nenhuma delas é dependência de runtime: são fontes e ferramentas de desenvolvimento — nada além desta pasta precisa estar instalado para usar a codebase-cleanup. O OCR permanece opcional e externo se você quiser rodá-lo.
Licença
MIT — use, copie, modifique e redistribua à vontade. Texto completo em LICENSE.
O CLI OpenCodeReview, quando você o instala à parte, é Apache-2.0 e permanece ferramenta externa: este repositório não o vende, não o embute e não o exige. Usá-lo não relicencia o código desta skill; o notice correspondente está no final do LICENSE.
{
"name": "codebase-cleanup",
"owner": {
"name": "CRangelP",
"url": "https://github.com/CRangelP"
},
"metadata": {
"description": "Cleanup tooling for Claude Code."
},
"plugins": [
{
"name": "codebase-cleanup",
"source": ".",
"category": "code-quality",
"description": "Four-phase codebase cleanup with a green gate before every commit.",
"keywords": [
"cleanup",
"dead-code",
"duplication",
"refactor",
"knip",
"tech-debt"
]
}
]
}Facts
- Kind
- Marketplace
- Repo
- CRangelP/codebase-cleanup
- Group
- Uncategorized
- Stars
- 0
- Marketplace name
- codebase-cleanup
- Owner
- CRangelP
- Language
- Shell
- Created
- 2026-08-08
- Last push
- 2026-09-06
- Topics
- claude-code, claude-skills, code-cleanup, dead-code, refactoring, duplicate-code
- Plugins
- 1
- 1obra/superpowersobra/superpowersAn agentic skills framework & software development methodology that works.297.9k
- 2affaan-m/everything-claude-codeaffaan-m/ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.277.5k
- 3anthropics/skillsanthropics/skillsPublic repository for Agent Skills180.6k
- 4f/prompts.chatf/prompts.chatf.k.a. Awesome ChatGPT Prompts. Share, discover, and collect prompts from the community. Free and open source — self-host for your organization with complete privacy.172.7k
- 5anthropics/claude-codeanthropics/claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.150.3k
- 6nextlevelbuilder/ui-ux-pro-max-skillnextlevelbuilder/ui-ux-pro-max-skillAn AI skill that provides design intelligence for building professional UI/UX across multiple platforms.135k