Dead Code Cleaner: If It Serves No Purpose, It Must Go
AI agents leave debris. Unused imports, orphaned functions, commented-out blocks, duplicate utilities -- dead code that inflates churn to 41%. This skill runs a cleanup pass after every task.
The Iron Law
Code that serves no purpose is not neutral -- it is a lie that the next reader must investigate.
Every dead line forces the next developer to ask: "Is this important? Is it used somewhere I can't see? Was it left here intentionally?" That wasted investigation multiplies across every future reader.
The Process
Step 1 -- Scan for the Five Categories
After completing a task, sweep all modified and newly created files for:
- Unused imports -- Modules imported but never referenced in the file
- Unreferenced functions/variables -- Declared but never called or accessed
- Commented-out code -- Not comments explaining why, but old code preserved "just in case"
- Orphaned files -- Files created during development (scratch files, old versions, temp utilities) that are not imported or referenced anywhere
- Duplicate utilities -- Functions that do the same thing as an existing utility, often created because the agent did not discover the original
Step 2 -- Verify Before Removing
For each candidate, confirm it is truly dead:
- Unused imports: Search the file for any reference to the imported name. Check for side-effect imports (CSS modules, polyfills, init scripts) that are intentionally reference-free.
- Unreferenced functions: Search the entire project, not just the current file. Check for dynamic references (
getattr, bracket notation, reflection). Check for exports consumed elsewhere.
- Commented-out code: Distinguish code from documentation.
// Calculate the hash using SHA-256 is a comment. // const result = oldApi.fetch(url) is dead code.
- Orphaned files: Verify no imports, requires, or references point to the file. Check build configs, test configs, and scripts.
- Duplicates: Confirm identical behavior before removing. Keep the version with better naming, tests, or documentation. Update all callers to use the surviving version.
Step 3 -- Remove With Precision
- Remove one category at a time. Verify the build and tests still pass after each category.
- Do NOT remove code that is outside the scope of your current task unless it was created or modified as part of this task.
- If unsure whether something is dead, leave it and flag it for the user.
Step 4 -- Report What Was Cleaned
After cleanup, summarize:
- What was removed and why
- What was flagged as suspicious but left (with reasoning)
- Any duplicates found that may warrant consolidation in a future task
Red Flags -- Common Dead Code Patterns
| Pattern |
Category |
import { helper } from './utils' but helper never appears below |
Unused import |
function oldHandler() { ... } with zero call sites |
Unreferenced function |
// const config = loadLegacyConfig() |
Commented-out code |
temp_solution.ts or utils_backup.js in project |
Orphaned file |
formatDate() in helpers.ts AND formatDateString() in utils.ts doing the same thing |
Duplicate utility |
TODO: remove after migration still present months later |
Stale dead code |
| Variable assigned but never read |
Unreferenced variable |
Entire else branch that returns the same value as the if branch |
Redundant logic |
Flowchart
digraph dead_code_cleaner {
rankdir=TB
node [shape=box style=rounded]
done [label="Task completed"]
scan [label="Step 1: Scan modified/created files\nfor 5 dead code categories"]
found [label="Dead code\ncandidates found?" shape=diamond]
verify [label="Step 2: Verify each candidate\nis truly dead\n(search project-wide)"]
confirmed [label="Confirmed dead?" shape=diamond]
flag [label="Flag as suspicious\nfor user review"]
remove [label="Step 3: Remove one\ncategory at a time"]
test [label="Build + tests\nstill pass?" shape=diamond]
revert [label="Revert removal.\nFlag for user."]
more [label="More categories\nto clean?" shape=diamond]
report [label="Step 4: Report\nwhat was cleaned\nand what was flagged"]
finish [label="Present clean work"]
done -> scan
scan -> found
found -> finish [label="None"]
found -> verify [label="Yes"]
verify -> confirmed
confirmed -> remove [label="Yes"]
confirmed -> flag [label="Unsure"]
remove -> test
test -> more [label="Yes"]
test -> revert [label="No"]
revert -> more
more -> verify [label="Yes"]
more -> report [label="No"]
flag -> more
report -> finish
}
1---2name: dead-code-cleaner3description: Use when finishing a task, after completing edits, or when code feels cluttered with unused imports, unreferenced functions, commented-out blocks, orphaned files, or duplicate utilities. Reduces the 41% code churn rate caused by AI agents leaving obsolete artifacts behind.4---56# Dead Code Cleaner: If It Serves No Purpose, It Must Go78AI agents leave debris. Unused imports, orphaned functions, commented-out blocks, duplicate utilities -- dead code that inflates churn to 41%. This skill runs a cleanup pass after every task.910## The Iron Law1112> **Code that serves no purpose is not neutral -- it is a lie that the next reader must investigate.**1314Every dead line forces the next developer to ask: "Is this important? Is it used somewhere I can't see? Was it left here intentionally?" That wasted investigation multiplies across every future reader.1516## The Process1718### Step 1 -- Scan for the Five Categories1920After completing a task, sweep all modified and newly created files for:21221. **Unused imports** -- Modules imported but never referenced in the file232. **Unreferenced functions/variables** -- Declared but never called or accessed243. **Commented-out code** -- Not comments explaining why, but old code preserved "just in case"254. **Orphaned files** -- Files created during development (scratch files, old versions, temp utilities) that are not imported or referenced anywhere265. **Duplicate utilities** -- Functions that do the same thing as an existing utility, often created because the agent did not discover the original2728### Step 2 -- Verify Before Removing2930For each candidate, confirm it is truly dead:3132- **Unused imports**: Search the file for any reference to the imported name. Check for side-effect imports (CSS modules, polyfills, init scripts) that are intentionally reference-free.33- **Unreferenced functions**: Search the entire project, not just the current file. Check for dynamic references (`getattr`, bracket notation, reflection). Check for exports consumed elsewhere.34- **Commented-out code**: Distinguish code from documentation. `// Calculate the hash using SHA-256` is a comment. `// const result = oldApi.fetch(url)` is dead code.35- **Orphaned files**: Verify no imports, requires, or references point to the file. Check build configs, test configs, and scripts.36- **Duplicates**: Confirm identical behavior before removing. Keep the version with better naming, tests, or documentation. Update all callers to use the surviving version.3738### Step 3 -- Remove With Precision3940- Remove one category at a time. Verify the build and tests still pass after each category.41- Do NOT remove code that is outside the scope of your current task unless it was created or modified as part of this task.42- If unsure whether something is dead, leave it and flag it for the user.4344### Step 4 -- Report What Was Cleaned4546After cleanup, summarize:4748- What was removed and why49- What was flagged as suspicious but left (with reasoning)50- Any duplicates found that may warrant consolidation in a future task5152## Red Flags -- Common Dead Code Patterns5354| Pattern | Category |55|---|---|56| `import { helper } from './utils'` but `helper` never appears below | Unused import |57| `function oldHandler() { ... }` with zero call sites | Unreferenced function |58| `// const config = loadLegacyConfig()` | Commented-out code |59| `temp_solution.ts` or `utils_backup.js` in project | Orphaned file |60| `formatDate()` in `helpers.ts` AND `formatDateString()` in `utils.ts` doing the same thing | Duplicate utility |61| `TODO: remove after migration` still present months later | Stale dead code |62| Variable assigned but never read | Unreferenced variable |63| Entire `else` branch that returns the same value as the `if` branch | Redundant logic |6465## Flowchart6667```dot68digraph dead_code_cleaner {69 rankdir=TB70 node [shape=box style=rounded]7172 done [label="Task completed"]73 scan [label="Step 1: Scan modified/created files\nfor 5 dead code categories"]74 found [label="Dead code\ncandidates found?" shape=diamond]75 verify [label="Step 2: Verify each candidate\nis truly dead\n(search project-wide)"]76 confirmed [label="Confirmed dead?" shape=diamond]77 flag [label="Flag as suspicious\nfor user review"]78 remove [label="Step 3: Remove one\ncategory at a time"]79 test [label="Build + tests\nstill pass?" shape=diamond]80 revert [label="Revert removal.\nFlag for user."]81 more [label="More categories\nto clean?" shape=diamond]82 report [label="Step 4: Report\nwhat was cleaned\nand what was flagged"]83 finish [label="Present clean work"]8485 done -> scan86 scan -> found87 found -> finish [label="None"]88 found -> verify [label="Yes"]89 verify -> confirmed90 confirmed -> remove [label="Yes"]91 confirmed -> flag [label="Unsure"]92 remove -> test93 test -> more [label="Yes"]94 test -> revert [label="No"]95 revert -> more96 more -> verify [label="Yes"]97 more -> report [label="No"]98 flag -> more99 report -> finish100}101```