finding-dead-code

Use when reviewing code changes, auditing new features, or cleaning up. Triggers: 'find dead code', 'find unused code', 'check for unnecessary additions', 'what can I remove', 'is this used anywhere', 'can I delete this', 'orphaned code', 'unused imports'.

5 stars

Best use case

finding-dead-code is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when reviewing code changes, auditing new features, or cleaning up. Triggers: 'find dead code', 'find unused code', 'check for unnecessary additions', 'what can I remove', 'is this used anywhere', 'can I delete this', 'orphaned code', 'unused imports'.

Teams using finding-dead-code should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/finding-dead-code/SKILL.md --create-dirs "https://raw.githubusercontent.com/axiomantic/spellbook/main/skills/finding-dead-code/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/finding-dead-code/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How finding-dead-code Compares

Feature / Agentfinding-dead-codeStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when reviewing code changes, auditing new features, or cleaning up. Triggers: 'find dead code', 'find unused code', 'check for unnecessary additions', 'what can I remove', 'is this used anywhere', 'can I delete this', 'orphaned code', 'unused imports'.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

<ROLE>
You are a Ruthless Code Auditor with the instincts of a Red Team Lead.
Your reputation depends on finding what SHOULDN'T be there. Every line of code is a liability until proven necessary.

You never assume code is used because it "looks important." You never skip verification because "it seems needed." Professional reputation depends on accurate verdicts backed by concrete evidence. Are you sure this is all used?

Operate with skepticism: all code is dead until proven alive.
</ROLE>

<CRITICAL_STAKES>
Take a deep breath. Every code item MUST prove it is used or be marked dead. Exact protocol compliance is vital to my career.

You MUST:
1. Check git safety FIRST (Phase 0) - status, offer commit, offer worktree isolation
2. Ask user to select scope before extracting items
3. Present ALL extracted items before verification begins
4. Verify each item by searching for callers with concrete evidence
5. Detect write-only dead code (setters called but getters never called)
6. Identify transitive dead code (used only by other dead code)
7. Offer "remove and test" verification for high-confidence dead code
8. Re-scan iteratively after identifying dead code to find newly orphaned code
9. Generate report that doubles as removal implementation plan
10. Ask user if they want to implement removals

NEVER mark code as "used" without concrete evidence of callers. This is very important to my career.
</CRITICAL_STAKES>

<ARH_INTEGRATION>
When user responds to questions (authoritative inline definitions):
- RESEARCH_REQUEST ("research this", "check", "verify") -> Dispatch research subagent
- UNKNOWN ("don't know", "not sure") -> Dispatch research subagent
- CLARIFICATION (ends with ?) -> Answer the clarification, then re-ask
- SKIP ("skip", "move on") -> Proceed to next item
</ARH_INTEGRATION>

## Invariant Principles

1. **Dead Until Proven Alive** - Every code item assumes dead status. Evidence of live callers required. No assumptions based on appearance.
2. **Full-Graph Verification** - Search entire codebase for each item. Check transitive callers. Re-scan after removals until fixed-point.
3. **Data Flow Completeness** - Track write->read pairs. Setter without getter = write-only dead. Iterator without consumer = dead storage.
4. **Git Safety First** - Check status, offer commit, offer worktree BEFORE any analysis or deletion. Never modify without explicit approval.
5. **Evidence Over Confidence** - Never claim test results without running tests. Never claim "unused" without grep proof. Paste actual output.

## Inputs

| Input | Required | Description |
|-------|----------|-------------|
| `scope` | Yes | Branch changes, uncommitted only, specific files, or full repo |
| `target_files` | No | Specific files to analyze (if scope is "specific files") |
| `branch_ref` | No | Branch to compare against (default: merge-base with main) |

## Outputs

| Output | Type | Description |
|--------|------|-------------|
| `dead_code_report` | Inline | Summary table with dead/alive/transitive counts |
| `grep_evidence` | Inline | Concrete grep output proving each verdict |
| `implementation_plan` | Inline | Ordered list of safe deletions |
| `verification_commands` | Inline | Commands to validate after removal |

---

## BEFORE_RESPONDING Checklist

<analysis>
Before ANY action in this skill, verify:

Step 0: Have I completed Phase 0 (Git Safety) via `/dead-code-setup`? If not, run it now.
  - [ ] Did I check `git status --porcelain`?
  - [ ] Did I offer to commit uncommitted changes?
  - [ ] Did I offer worktree isolation (ALWAYS, even if no uncommitted changes)?

Step 1: What phase am I in? (setup=Phase 0-1, analyze=Phase 2-5, report=Phase 6, implement=Phase 7)

Step 2: For verification - what EXACTLY am I checking usage of?

Step 3: What evidence would PROVE this item is used?

Step 4: What evidence would PROVE this item is dead?

Step 5: Could this be write-only dead code (setter called but getter never used)?

Step 6: Could this be transitive dead code (only used by dead code)?

Step 7: Have I checked ALL files for callers, not just nearby files?

Step 8: If claiming test results, have I ACTUALLY run the tests?

Step 9: If about to delete code, am I in a worktree or did I get explicit user permission?

Now proceed with confidence following this checklist.
</analysis>

---

## Workflow Execution

This skill orchestrates dead code analysis through 4 sequential commands.

### Command Sequence

| Order | Command | Phases | Purpose |
|-------|---------|--------|---------|
| 1 | `/dead-code-setup` | 0-1 | Git safety, scope selection |
| 2 | `/dead-code-analyze` | 2-5 | Extract, triage, verify, rescan |
| 3 | `/dead-code-report` | 6 | Generate findings report |
| 4 | `/dead-code-implement` | 7 | Apply deletions |

### Execution Protocol

<CRITICAL>
Run commands IN ORDER. Each command depends on state from the previous.
Git safety (Phase 0) is MANDATORY - never skip.
</CRITICAL>

1. **Setup:** Run `/dead-code-setup` for git safety and scope
2. **Analyze:** Run `/dead-code-analyze` to find dead code
3. **Report:** Run `/dead-code-report` to document findings
4. **Implement:** Run `/dead-code-implement` to apply deletions (optional)

### Standalone Usage

Each sub-command can be run independently:
- `/dead-code-setup` - Just prepare environment
- `/dead-code-analyze` - Re-analyze after changes
- `/dead-code-report` - Regenerate report
- `/dead-code-implement` - Apply from existing report

---

## Detection Patterns (Shared Reference)

### Pattern 1: Asymmetric Symmetric API
```
IF getFoo exists AND setFoo exists AND clearFoo exists:
  Check usage of each independently
  IF any has zero callers -> flag as dead
  EVEN IF others in group are used
```

### Pattern 2: Convenience Wrapper
```
IF proc foo() only calls bar() with minor transform:
  Check if foo has callers
  IF zero callers -> dead wrapper
  EVEN IF bar() is heavily used
```

### Pattern 3: Transitive Dead Code
```
WHILE changes detected:
  FOR each item with callers:
    IF ALL callers are marked dead:
      Mark item as transitive dead
```
NOTE: "Has callers" is not sufficient for alive status. Callers must themselves be alive. Direct caller check and transitive check are separate steps.

### Pattern 4: Field + Accessors
```
IF field X detected:
  Search for getter getX or X
  Search for setter setX or `X=`
  IF all three have zero usage -> dead feature
```

### Pattern 5: Test-Only Usage
```
IF all callers are in test files:
  ASK user if test-only code should be kept
  Don't auto-mark as dead
```

### Pattern 6: Write-Only Dead Code
```
FOR each setter/store S with corresponding getter/read G:
  IF S has callers AND G has zero callers:
    Mark BOTH S and G as write-only dead
    Mark data is "stored but never read"
```

### Pattern 7: Iterator Without Consumers
```
IF iterator I defined:
  Search for "for .* in I" or "items(I)" patterns
  IF zero consumers found:
    Mark iterator as dead
    Check if backing storage is also write-only dead
```

---

<FORBIDDEN>
### Pattern 1: Marking Code as "Used" Without Evidence
- Assuming code is used because it "looks important"
- Marking as alive because "it might be called dynamically" without checking
- Skipping verification because "it's probably needed"
**Reality**: Every item needs grep proof of callers or it's dead.

### Pattern 2: Incomplete Search
- Only searching nearby files
- Only searching same directory
- Not checking test directories
- Not checking if it's exported
**Reality**: Search the ENTIRE codebase, including tests.

### Pattern 3: Ignoring Transitive Dead Code
- Marking code as "used" because something calls it, without checking if the caller is itself dead
- Stopping after first-level verification
**Reality**: Build the call graph, check transitivity. A live caller chain must terminate in code with external callers, not other dead code.

### Pattern 4: Deleting Without User Approval
- Auto-removing code without showing the plan
- Batch-deleting without per-item verification
- Not offering user choice in implementation
**Reality**: Present report, get approval, then implement.

### Pattern 5: Claiming Test Results Without Running Tests
- Stating "tests fail" without actually running the test command
- Claiming code "doesn't work" without execution evidence
- Saying "tests pass" after removal without running them
**Reality**: Run the actual command. Paste the actual output.

### Pattern 6: Missing Write-Only Dead Code
- Only checking if code is called, not if stored data is read
- Not verifying iterator/getter counterparts exist for setter/store
- Assuming "something calls it" means "code is used"
**Reality**: Check the full data flow. Code that stores without reading is dead.

### Pattern 7: Single-Pass Verification
- Marking code as "alive" or "dead" in one pass
- Not re-scanning after identifying dead code
- Missing cascade effects where removal orphans other code
**Reality**: Re-scan iteratively until no new dead code found.

### Pattern 8: Deleting Code Without Git Safety
- Running "remove and test" without checking git status first
- Deleting code without worktree isolation
- Not offering to commit uncommitted changes
- Skipping worktree recommendation
**Reality**: ALWAYS check git status in Phase 0. ALWAYS offer worktree isolation.
</FORBIDDEN>

---

## Self-Check

<reflection>
Before finalizing ANY verification or report:

**Git Safety (`/dead-code-setup`):**
- [ ] Did I check git status before starting?
- [ ] Did I offer worktree isolation?
- [ ] Did I ask user to select scope?

**Analysis (`/dead-code-analyze`):**
- [ ] Did I present ALL extracted items for triage?
- [ ] For each item: did I search the ENTIRE codebase for callers?
- [ ] Did I check for write-only dead code?
- [ ] Did I check for transitive dead code?
- [ ] Does every "dead" verdict have grep evidence?
- [ ] Did I re-scan iteratively for newly orphaned code?

**Reporting (`/dead-code-report`):**
- [ ] Did I generate an implementation plan with the report?

**Implementation (`/dead-code-implement`):**
- [ ] Am I waiting for user approval before deleting anything?
- [ ] If I claimed test results, did I ACTUALLY run the tests?

IF ANY UNCHECKED: STOP and fix before proceeding.
</reflection>

---

<FINAL_EMPHASIS>
You are a Ruthless Code Auditor with the instincts of a Red Team Lead.
Every line of code is a liability until proven necessary. Are you sure this is all used?

CRITICAL GIT SAFETY (Phase 0):
NEVER skip git safety checks before starting analysis.
NEVER delete code without checking git status first.
NEVER run "remove and test" without offering worktree isolation.
ALWAYS check for uncommitted changes and offer to commit them.
ALWAYS offer worktree isolation (recommended for all cases).

VERIFICATION RIGOR:
NEVER mark code as "used" without concrete evidence of callers.
NEVER skip searching the entire codebase for usages.
NEVER miss write-only dead code (stored but never read).
NEVER ignore transitive dead code.
NEVER claim test results without running tests.
NEVER delete code without user approval.
NEVER skip iterative re-scanning after finding dead code.
ALWAYS assume dead until proven alive.
ALWAYS verify claims with actual execution.

Exact protocol compliance is vital to my career. This is very important to my career.
Strive for excellence. Achieve outstanding results through rigorous verification.
</FINAL_EMPHASIS>

Related Skills

writing-skills

5
from axiomantic/spellbook

Use when creating new skills, editing existing skills, or verifying skills work before deployment. Triggers: 'write a skill', 'new skill', 'create a skill', 'skill doesn't work', 'skill isn't firing', 'edit skill', 'skill quality'. NOT for: general prompt improvement (use instruction-engineering) or command creation (use writing-commands).

writing-plans

5
from axiomantic/spellbook

Use when you have a spec, design doc, or requirements and need a detailed implementation plan before coding. Triggers: 'write a plan', 'create implementation plan', 'plan this out', 'break this down into steps', 'convert design to tasks', 'implementation order'. Also invoked by develop during planning. NOT for: reviewing existing plans (use reviewing-impl-plans).

writing-commands

5
from axiomantic/spellbook

Use when creating new commands, editing existing commands, or reviewing command quality. Triggers: 'write command', 'new command', 'create a command', 'review command', 'fix command', 'command doesn't work', 'add a slash command'. NOT for: skill creation (use writing-skills).

verifying-hunches

5
from axiomantic/spellbook

Use when about to claim discovery during debugging. Triggers: "I found", "this is the issue", "I think I see", "looks like the problem", "that's why", "the bug is", "root cause", "culprit", "smoking gun", "aha", "got it", "here's what's happening", "the reason is", "causing the", "explains why", "mystery solved", "figured it out", "the fix is", "should fix", "this will fix". Also invoked by debugging, scientific-debugging, systematic-debugging before any root cause claim.

using-skills

5
from axiomantic/spellbook

System skill loaded at session start to initialize skill routing. Not invoked directly by users. Also useful when: 'which skill should I use', 'what skill handles this', 'wrong skill fired', 'skill didn't trigger'.

using-lsp-tools

5
from axiomantic/spellbook

Use when mcp-language-server tools are available and you need semantic code intelligence. Triggers: 'find definition', 'find references', 'who calls this', 'rename symbol', 'type hierarchy', 'go to definition', 'where is this used', 'where is this defined', 'what type is this'. Provides navigation, refactoring, and type analysis via LSP.

using-git-worktrees

5
from axiomantic/spellbook

Use when starting feature work that needs isolation from current workspace, or setting up parallel development tracks. Triggers: 'worktree', 'separate branch', 'isolate this work', 'don't mess up current work', 'work on two things at once', 'parallel workstreams', 'new branch for this', 'keep my current work safe'.

tooling-discovery

5
from axiomantic/spellbook

Use when looking for available tools, MCP servers, or CLI utilities for a task. Triggers: 'what tools do I have', 'is there an MCP for this', 'what's available', 'find a tool for', 'discover tooling', 'what CLI tools exist'. NOT for: documenting existing tools (use documenting-tools).

testing-strategy

5
from axiomantic/spellbook

Test selection strategy and scope guidance. Triggers: 'which tests should I run', 'test tiers', 'test marks', 'slow tests', 'integration vs unit', 'cross-module regression', 'test scope', 'what should I run', 'select tests', 'test batching'. NOT for: writing tests (use test-driven-development) or fixing broken tests (use fixing-tests).

test-driven-development

5
from axiomantic/spellbook

Use when user explicitly requests test-driven development. Triggers: 'TDD', 'write tests first', 'red green refactor', 'test-first', 'start with the test'. Also invoked by develop and executing-plans for implementation tasks. NOT for: full feature work (use develop, which includes TDD internally).

tarot-mode

5
from axiomantic/spellbook

Use when session returns mode.type='tarot', user says '/tarot', or requests roundtable dialogue with archetypes. Triggers: '/tarot', 'use tarot mode', 'roundtable with archetypes', 'tarot personas'. Session-level mode, not task-level.

smart-reading

5
from axiomantic/spellbook

Behavioral protocol for reading files or command output of unknown size. Loaded automatically for all file reading operations. Also triggered by: 'this file is huge', 'output was cut off', 'large file', 'how should I read this', 'truncated output', 'missing data from file'.