Skip to content
Back to skills

Find Dead Code

BSecurity

Find unused functions, classes, variables, exports, feature flags, and config keys across the codebase and produce a prioritized removal list.

  • 10 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
developmentjavascripttypescriptpythongojavabashapi

Works with

  • cli
  • api

Security analysis

B80/100
  • criticalSends environment variables or credentials to an external URL
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 6, 2026

npx -y skills add tomzx/agents --skill find-dead-code --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Find Dead Code?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Find Dead Code
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/tomzx-find-dead-code/badge)](https://www.skillsdirectory.com/skills/tomzx-find-dead-code)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: find-dead-code
description: Find unused functions, classes, variables, exports, feature flags, and config keys across the codebase and produce a prioritized removal list.
allowed-tools: Bash, Read, Glob, Grep
argument-hint: "[path]"
---

TODAY=!`date +%Y-%m-%d`

# Dead Code Scan

Identifies code that is defined but never used — functions, classes, variables, exports, feature flags, and config keys — and produces a prioritized list of safe removals. Dead code increases cognitive load, slows onboarding, and enlarges the codebase that future changes must account for.

## Prerequisites

- Working directory is the root of the repository (or a subdirectory)
- Optional: `$1` — path to limit the scan (defaults to `.`)
- Language-specific tools installed as available (degrades to heuristics):
  - Python: `vulture` (`uv tool install vulture` or `pip install vulture`)
  - JavaScript/TypeScript: `ts-prune` (`npx ts-prune`) or `knip` (`npx knip`)
  - Go: `deadcode` (`go install golang.org/x/tools/cmd/deadcode@latest`)

## Categories of Dead Code

| Category | Examples |
|----------|---------|
| Unused functions / methods | Defined but never called anywhere in the codebase |
| Unused classes / types | Defined but never instantiated or referenced |
| Unused variables / constants | Assigned but never read |
| Unused imports | Imported but not used in the file |
| Unreachable code | Code after a `return`/`raise`/`exit`, or in a branch that can never be true |
| Stale feature flags | Flags that are always-true or always-false in all environments |
| Orphaned config keys | Keys present in config files but never read by the application |
| Unused exports | Symbols exported from a module but not imported anywhere |

## Steps

### 1. Detect Language and Available Tools

```
find ${1:-.} -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -10
command -v vulture
command -v ts-prune || npx --yes ts-prune --version 2>/dev/null
command -v deadcode
```

### 2. Run Language-Specific Dead Code Detection

**Python — vulture:**
```
vulture ${1:-.} --min-confidence 80 --sort-by-size
```
`--min-confidence 80` reduces false positives from dynamic attribute access.

**JavaScript/TypeScript — knip (preferred) or ts-prune:**
```
npx knip --reporter compact 2>/dev/null || npx ts-prune ${1:-.}
```

**Go — deadcode:**
```
deadcode -test ./...
```

**Generic heuristics (any language):**

Unused imports:
```
rg -n "^import |^from .* import" -g '*.py' ${1:-.} | \
  awk '{print $NF, FILENAME}' | sort | uniq > /tmp/imported.txt
# Cross-reference with actual usage — report imports that appear only once (the import line itself)
```

Functions defined but never called (rough signal):
```
rg -n "^def |^    def " -g '*.py' ${1:-.} | \
  sed 's/.*def \([a-zA-Z_][a-zA-Z0-9_]*\).*/\1/' | \
  while read fn; do
    count=$(rg "$fn" ${1:-.} | wc -l)
    [ "$count" -le 1 ] && echo "$count $fn"
  done | sort -n | head -30
```

Always-true/false feature flags:
```
rg -n "(if|when|enabled)\s*\(?\s*(True|true|False|false)\s*\)?" \
  -g '*.{py,js,ts}' ${1:-.} | head -20
```

### 3. Find Unreachable Code

```
rg -n -A1 "^\s*(return|raise|exit|panic|os\.Exit)" \
  -g '*.{py,go,js,ts}' ${1:-.} | \
  rg -v "^--$" | rg -v "(return|raise|exit|panic)" | \
  rg -v "^\s*$" | head -30
```

### 4. Scan Config Files for Orphaned Keys

Find all config keys:
```
rg -n --hidden "^[a-zA-Z_][a-zA-Z0-9_]*\s*[:=]" \
  -g '*.yaml' -g '*.yml' -g '*.toml' -g '*.env*' ${1:-.} | \
  sed 's/.*:\s*\([a-zA-Z_][a-zA-Z0-9_]*\)\s*[:=].*/\1/' | sort -u > /tmp/config_keys.txt
```

Cross-reference against source reads:
```
while read key; do
  count=$(rg "\"$key\"|'$key'|\b$key\b" -g '*.py' -g '*.js' -g '*.ts' -g '*.go' ${1:-.} | wc -l)
  [ "$count" -eq 0 ] && echo "$key"
done < /tmp/config_keys.txt
```

### 5. Filter False Positives

Before reporting, filter out:
- Functions whose names start with `_` in Python (may be intentionally semi-private but called via `getattr`)
- Functions matching test framework patterns (`test_*`, `setUp`, `tearDown`)
- Names referenced only in strings (dynamic dispatch, `getattr`, `eval`)
- Symbols marked with `# noqa`, `//nolint`, or similar suppression comments
- Entry points (`main`, `__main__`, CLI commands, route handlers)

### 6. Rank by Removal Safety

| Safety | Criteria |
|--------|---------|
| 🟢 Safe to remove | Zero references anywhere, not an entry point, not dynamic |
| 🟡 Verify first | One or two references, or used in tests only |
| 🔴 Needs investigation | Dynamic access patterns, plugin/hook systems, public API |

### 7. Inspect Top Candidates

For the top 20 findings, read the defining file and the call sites to confirm the finding is genuine before including it in the report.

### 8. Print the Report

```
# Dead Code Scan — {TODAY}

## Summary

- Files scanned: N
- Dead code candidates: N
- Confirmed safe removals: N

## By Category

### Unused Functions / Methods (N)
| Safety | Symbol | File | Line | Notes |
|--------|--------|------|------|-------|
| 🟢 | `foo()` | `src/utils.py` | 42 | Zero references |

### Unused Imports (N)
…

### Unreachable Code (N)
…

### Stale Feature Flags (N)
…

### Orphaned Config Keys (N)
…

## Recommended Removal Order

1. <highest-confidence, lowest-risk removals first>
2. …

## Items Needing Manual Review

- `<symbol>`: <why it needs a human look before removing>
```

## Example Usage

**Scenario 1: Full project scan**
```
/find-dead-code
```
Finds 12 unused Python functions, 3 always-true feature flags, and 7 orphaned config keys. Recommends removing the flags first as they also simplify surrounding logic.

**Scenario 2: Targeted scan before a refactor**
```
/find-dead-code src/payments
```
Confirms that two helper functions in the payments module are no longer called after a recent refactor; safe to delete.

## Useful Commands Reference

| Command | Description |
|---------|-------------|
| `vulture . --min-confidence 80 --sort-by-size` | Python dead code, sorted by size of dead symbol |
| `npx knip` | JS/TS unused exports, dependencies, and files |
| `deadcode -test ./...` | Go unreachable functions |
| `rg -n "def " . \| wc -l` | Count total function definitions |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…