Remove Dead Code
Delete code that is provably unreferenced — without breaking anything. The rule
is simple: prove it's dead before you delete it. A confident-looking unused
symbol is often reached through a barrel export, a test, reflection, or a
framework entry point. Verify first. For behavior-preserving complexity
reduction (simplify without deleting), use the simplify skill.
Phase 1: Scan (parallel)
Fire independent detectors at once and collect candidates:
- Compiler / linter unused flags — e.g. TypeScript
tsc --noUnusedLocals --noUnusedParameters, ESLint no-unused-vars, Go deadcode/staticcheck,
Python vulture, Rust cargo +nightly udeps / dead-code warnings.
- Orphaned files — source files not imported by any other file.
- Unused exports — exported symbols never imported elsewhere.
- LSP references — "find all references" returning only the definition.
Delegate broad searches to explore subagents in parallel when the codebase is
large; keep each search scoped to one question.
Phase 2: Verify each candidate (before deleting)
For every candidate, confirm it is genuinely dead. Discard it (keep the code) if
any of these is true:
- It is re-exported through a barrel/index file that external code imports.
- It is referenced by tests, fixtures, or snapshots.
- It is a framework/tooling entry point (route handler, CLI command, migration,
plugin hook,
main, serializer) discovered by convention, not import.
- It is reached by reflection, dynamic import, string key, or DI container.
- It is part of a published public API (
@public, exported package surface).
Re-run "find references" (LSP) immediately before each edit — the graph may have
changed as you removed earlier items.
Phase 3: Delete in conflict-free batches
- Group removals by file: everything in the same file goes in the same batch,
so parallel edits never collide.
- Remove the symbol/file and its now-unused imports.
- Stage precisely:
git add <specific files> — never git add -A.
Phase 4: Prove the removal is safe
After each batch:
- Build / type-check the project.
- Run the test suite (or the affected subset).
- Re-run the unused-symbol detector — the count should drop, not grow.
If the build or tests break, revert that batch and re-verify Phase 2 for the
offending item.
Anti-patterns
- Deleting on a hunch without a references check.
- Bulk-deleting a whole directory because "it looks unused."
- Using
git add -A and sweeping up unrelated changes.
- Removing something only reachable from tests, then deleting the tests too to
make it look unused — that hides regressions.
Report
List what was removed and the evidence it was dead:
- removed <file/symbol> — <how it was proven unused: no importers / LSP 0 refs / linter>
End with the build + test result so the caller can trust the change.
1---2name: remove-deadcode3description: Safely find and delete dead code — unused files, exports, functions, variables, and imports — with verification before each removal. Use when the task mentions "dead code", "unused code", "remove slop", "clean up" (dead code cleanup), "prune", "delete unused", "orphaned files", or after a refactor leaves unused code behind. Verifies via toolchain/LSP before deleting.4---56# Remove Dead Code78Delete code that is provably unreferenced — without breaking anything. The rule9is simple: **prove it's dead before you delete it.** A confident-looking unused10symbol is often reached through a barrel export, a test, reflection, or a11framework entry point. Verify first. For behavior-preserving complexity12reduction (simplify without deleting), use the `simplify` skill.1314## Phase 1: Scan (parallel)1516Fire independent detectors at once and collect candidates:1718- **Compiler / linter unused flags** — e.g. TypeScript `tsc --noUnusedLocals19 --noUnusedParameters`, ESLint `no-unused-vars`, Go `deadcode`/`staticcheck`,20 Python `vulture`, Rust `cargo +nightly udeps` / dead-code warnings.21- **Orphaned files** — source files not imported by any other file.22- **Unused exports** — exported symbols never imported elsewhere.23- **LSP references** — "find all references" returning only the definition.2425Delegate broad searches to `explore` subagents in parallel when the codebase is26large; keep each search scoped to one question.2728## Phase 2: Verify each candidate (before deleting)2930For every candidate, confirm it is genuinely dead. Discard it (keep the code) if31**any** of these is true:3233- It is re-exported through a barrel/index file that external code imports.34- It is referenced by tests, fixtures, or snapshots.35- It is a framework/tooling entry point (route handler, CLI command, migration,36 plugin hook, `main`, serializer) discovered by convention, not import.37- It is reached by reflection, dynamic import, string key, or DI container.38- It is part of a published public API (`@public`, exported package surface).3940Re-run "find references" (LSP) immediately before each edit — the graph may have41changed as you removed earlier items.4243## Phase 3: Delete in conflict-free batches4445- Group removals **by file**: everything in the same file goes in the same batch,46 so parallel edits never collide.47- Remove the symbol/file **and** its now-unused imports.48- Stage precisely: `git add <specific files>` — never `git add -A`.4950## Phase 4: Prove the removal is safe5152After each batch:53541. Build / type-check the project.552. Run the test suite (or the affected subset).563. Re-run the unused-symbol detector — the count should drop, not grow.5758If the build or tests break, revert that batch and re-verify Phase 2 for the59offending item.6061## Anti-patterns6263- Deleting on a hunch without a references check.64- Bulk-deleting a whole directory because "it looks unused."65- Using `git add -A` and sweeping up unrelated changes.66- Removing something only reachable from tests, then deleting the tests too to67 make it look unused — that hides regressions.6869## Report7071List what was removed and the evidence it was dead:7273```74- removed <file/symbol> — <how it was proven unused: no importers / LSP 0 refs / linter>75```7677End with the build + test result so the caller can trust the change.