Find and report unused code across the codebase. Does NOT auto-delete — presents findings for human review.
Inspired by Claude-Command-Suite (qdhenry) /dev:remove-dead-code multi-agent scanning concept.
$ARGUMENTS — target: "backend", "frontend", or specific module path (e.g., "src/billing")
Default: scan the full project.
Parse $ARGUMENTS to decide what to scan. If a specific module is given, scope to that directory. Otherwise scan the entire project.
Use multiple detection strategies:
# ruff can detect unused imports (F401)
ruff check src/ --select F401 --output-format concise 2>/dev/null# ruff F841 (unused variables), F811 (redefined unused)
ruff check src/ --select F841,F811 --output-format concise 2>/dev/null# vulture for dead code detection (if installed)
vulture src/ --min-confidence 80 2>/dev/null | head -30 || echo "vulture not installed — using ruff only"Cross-reference:
- URL patterns / route definitions
- View functions / handler classes
- Any handler not referenced in any route is potentially dead
# ts-prune detects unused exports
npx ts-prune 2>/dev/null | head -30 || echo "ts-prune not available"Search for components that are defined but never imported elsewhere:
# Find all exported components
grep -rn "export.*function\|export.*const.*=.*=>" src/ --include="*.tsx" --include="*.ts" -lThen for each exported name, check if it's imported anywhere else. Flag components with zero imports outside their own file.
pnpm lint 2>/dev/null | grep -i "unused\|no-unused" | head -20
# or: npx eslint src/ --rule '{"no-unused-vars":"warn"}' 2>/dev/nullFor each finding, check if the "dead" code is only used in tests:
grep -rn "<function_name>" tests/ __tests__/ spec/ 2>/dev/nullCode used only in tests might still be needed (test helpers, fixtures).
| Category | Risk | Action |
|---|---|---|
| Unused imports | Low | Safe to remove |
| Unused variables | Low | Safe to remove |
| Unreachable code | Low | Safe to remove |
| Unused private functions | Medium | Verify no dynamic calls |
| Unused exported functions | Medium | Check for external consumers |
| Unused views/endpoints | High | May be called by frontend or external services |
| Unused components | Medium | Check for lazy/dynamic imports |
# Dead Code Report — {date}
**Scope**: {what was scanned}
**Tools used**: {ruff, vulture, ts-prune, eslint — whichever were available}
## Summary
| Category | Count | Risk | Side |
|----------|-------|------|------|
| Unused imports | N | Low | BE |
| Unused variables | N | Low | BE |
| Unused functions | N | Medium | BE |
| Unused components | N | Medium | FE |
| Unused exports | N | Medium | FE |
## Findings
### Low Risk (safe to remove)
| File | Line | Type | Name |
|------|------|------|------|
| src/billing/views.py | 42 | unused import | `json` |
### Medium Risk (verify before removing)
| File | Line | Type | Name | Used in Tests? |
|------|------|------|------|----------------|
| src/billing/utils.py | 88 | unused function | `calc_old` | No |
### High Risk (may have external consumers)
| File | Line | Type | Name | Notes |
|------|------|------|------|-------|
| src/billing/views.py | 120 | unused view | `LegacyView` | Check frontend routes |If the user wants to proceed with removal:
I found N items to clean up.
- Low risk items: can remove directly (safe)
- Medium/High risk: recommend a separate branch for review
| If you need... | Use instead |
|---|---|
| Broader lint/quality check | /health-check (general repo health, not dead-code specific) |
| Bulk cleanup | /delegate (dispatch removal tasks to subagents) |
| Verify removal didn't break anything | /investigate if tests fail after cleanup |
- Read-only by default — never delete code without explicit user approval
- False positives are expected — dynamic dispatch, reflection, lazy imports can fool static analysis
- Cross-module awareness — a function unused in its own module may be imported elsewhere
- Don't flag test utilities — helpers in
conftest.pyortest_utilsare used by test discovery - Don't flag init.py re-exports — these are public API surface
- Prioritize by risk — present low-risk items first to build confidence