ClaudeCodeMod

All shelves / Marketplaces

CRangelP/codebase-cleanup

CRangelP/codebase-cleanup · 0 stars · 1 plugin

Marketplace

Install

In Claude Code
/plugin marketplace add CRangelP/codebase-cleanup

Run inside Claude Code, then install plugins from it. Check the repo's README before you run it.

Open the repo

Plugins 1

After adding the marketplace, install one with /plugin install <name>@codebase-cleanup.

  1. 1codebase-cleanupFour-phase codebase cleanup with a green gate before every commit./plugin install codebase-cleanup@codebase-cleanupcode-quality

Files

README.md

English · Português · ci

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 branch cleanup/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, e git init sozinho não dá nenhum.
  • Para projetos JS/TS: Node com npx (o knip roda via npx knip@6.32.0, versão pinada — nunca npx knip sem 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 install só 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/bin ou os runners uv run e poetry run (nessa ordem). Cada check roda sob um watchdog (GATE_TIMEOUT, 900s por padrão, 0 desliga): 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óprio chore: 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 -- …, nunca git 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 como reviewed ou skipped com motivo, e o coverage_rate vai 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.md diz 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.json gerado.
  • 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/.slnx na raiz o gate a passa explícita ao dotnet; 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/*.rs ou #[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: o git restore traz de volta o package.json e 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 em references/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.

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

More on this shelf

  1. 1obra/superpowersobra/superpowersAn agentic skills framework & software development methodology that works.297.9k
  2. 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
  3. 3anthropics/skillsanthropics/skillsPublic repository for Agent Skills180.6k
  4. 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
  5. 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
  6. 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