
Dead Code Detector
- 134 installs
- 62 repo stars
- Updated August 3, 2026
- terrylica/cc-skills
Use dead-code-detector for development tasks
About
dead-code-detector: A skill for development. This provides functionality for development workflows.
- dead-code-detector
Dead Code Detector by the numbers
- 134 all-time installs (skills.sh)
- +1 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #2,673 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/terrylica/cc-skills --skill dead-code-detectorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 134 |
|---|---|
| repo stars | ★ 62 |
| Last updated | August 3, 2026 |
| Repository | terrylica/cc-skills ↗ |
What it does
Use dead-code-detector for development tasks
Files
Dead Code Detector
Find and remove unused code across Python, TypeScript, and Rust codebases.
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
Tools by Language
| Language | Tool | Detects |
|---|---|---|
| Python | vulture v2.14+ | Unused imports, functions, classes, variables |
| TypeScript | knip v5.0+ | Unused exports, dependencies, files |
| Rust | cargo clippy + rustc lints | Unused functions, imports, dead_code warnings |
Why these tools?
- vulture: AST-based, confidence scoring (60-100%), whitelist support
- knip: Successor to ts-prune (maintenance mode), monorepo-aware, auto-fix
- cargo clippy: Built-in to Rust toolchain, zero additional deps
---
When to Use This Skill
Use this skill when:
- Cleaning up a codebase before release
- Refactoring to reduce maintenance burden
- Investigating bundle size / compile time issues
- Onboarding to understand what code is actually used
NOT for: Code duplication (use quality-tools:code-clone-assistant)
---
Quick Start Workflow
Python (vulture)
# Step 1: Install
uv pip install vulture
# Step 2: Scan with 80% confidence threshold
vulture src/ --min-confidence 80
# Step 3: Generate whitelist for false positives
vulture src/ --make-whitelist > vulture_whitelist.py
# Step 4: Re-scan with whitelist
vulture src/ vulture_whitelist.py --min-confidence 80TypeScript (knip)
# Step 1: Install (project-local recommended)
bun add -d knip
# Step 2: Initialize config
bunx knip --init
# Step 3: Scan for dead code
bunx knip
# Step 4: Auto-fix (removes unused exports)
bunx knip --fixRust (cargo clippy)
# Step 1: Scan for dead code warnings
cargo clippy -- -W dead_code -W unused_imports -W unused_variables
# Step 2: For stricter enforcement
cargo clippy -- -D dead_code # Deny (error) instead of warn
# Step 3: Auto-fix what's possible
cargo clippy --fix --allow-dirty---
Confidence and False Positives
Python (vulture)
| Confidence | Meaning | Action |
|---|---|---|
| 100% | Guaranteed unused in analyzed files | Safe to remove |
| 80-99% | Very likely unused | Review before removing |
| 60-79% | Possibly unused (dynamic calls, frameworks) | Add to whitelist if intentional |
Common false positives (framework-invoked code):
- Route handlers / controller methods (invoked by web frameworks)
- Test fixtures and setup utilities (invoked by test runners)
- Public API surface exports (re-exported for consumers)
- Background job handlers (invoked by task queues / schedulers)
- Event listeners / hooks (invoked by event systems)
- Serialization callbacks (invoked during encode/decode)
TypeScript (knip)
Knip uses TypeScript's type system for accuracy. Configure in knip.json:
{
"entry": ["src/index.ts"],
"project": ["src/**/*.ts"],
"ignore": ["**/*.test.ts"],
"ignoreDependencies": ["@types/*"]
}Rust
Suppress false positives with attributes:
#[allow(dead_code)] // Single item
fn intentionally_unused() {}
// Or module-wide
#![allow(dead_code)]---
Integration with CI
Python (pyproject.toml)
[tool.vulture]
min_confidence = 80
paths = ["src"]
exclude = ["*_test.py", "conftest.py"]TypeScript (package.json)
{
"scripts": {
"dead-code": "knip",
"dead-code:fix": "knip --fix"
}
}Rust (Cargo.toml)
[lints.rust]
dead_code = "warn"
unused_imports = "warn"---
Reference Documentation
For detailed information, see:
- Python Workflow - vulture advanced usage
- TypeScript Workflow - knip configuration
- Rust Workflow - clippy lint categories
---
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Reports framework-invoked code | Framework magic / callbacks | Add to whitelist or exclusion config |
| Misses dynamically loaded code | Not in static entry points | Configure entry points to include plugin/extension directories |
| Warns about test-only helpers | Test code compiled separately | Use conditional compilation or test-specific exclusions |
| Too many false positives | Threshold too low | Increase confidence threshold or configure ignore patterns |
| Missing type-only references | Compile-time only usage | Most modern tools handle this; check tool version |
---
Multi-Perspective Validation (Critical)
IMPORTANT: Before removing any detected "dead code", spawn parallel subagents to validate findings from multiple perspectives. Dead code may actually be unimplemented features or incomplete integrations.
Classification Matrix
| Finding Type | True Dead Code | Unimplemented Feature | Incomplete Integration |
|---|---|---|---|
| Unused callable | No callers, no tests, no docs | Has TODO/FIXME, referenced in specs | Partial call chain exists |
| Unused export/public | Not imported anywhere | In public API, documented | Used in sibling module |
| Unused import/include | Typo, refactored away | Needed for side effects | Type-only or compile-time |
| Unused binding | Assigned but never read | Placeholder for future | Debug/instrumentation removed |
Validation Workflow
After running detection tools, spawn these parallel subagents:
┌─────────────────────────────────────────────────────────────────┐
│ Dead Code Findings │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Intent Agent │ │ Integration │ │ History Agent │
│ │ │ Agent │ │ │
│ - Check TODOs │ │ - Trace call │ │ - Git blame │
│ - Search specs │ │ chains │ │ - Commit msgs │
│ - Find issues │ │ - Check exports │ │ - PR context │
│ - Read ADRs │ │ - Test coverage │ │ - Author intent │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────┼───────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ AskUserQuestion: Confirm Classification │
│ [ ] True dead code - safe to remove │
│ [ ] Unimplemented - create GitHub Issue to track │
│ [ ] Incomplete - investigate integration gaps │
│ [ ] False positive - add to whitelist │
└─────────────────────────────────────────────────────────────────┘Agent Prompts
Intent Agent (searches for planned usage):
Search for references to [IDENTIFIER] in:
1. TODO/FIXME/HACK comments in codebase
2. Issue tracker (open and closed issues)
3. Design documents and architecture decision records
4. README and project documentation files
Report: Was this code planned but not yet integrated?Integration Agent (traces execution paths):
For [IDENTIFIER], analyze:
1. All module import/include/use statements
2. Runtime module loading mechanisms (lazy loading, plugins)
3. Framework-invoked patterns (metadata attributes, config bindings, annotations)
4. Test files that may exercise this code path
Report: Is there a partial or indirect call chain?History Agent (investigates provenance):
For [IDENTIFIER], check:
1. VCS blame/annotate - who wrote it and when
2. Commit message - what was the stated intent
3. Code review / merge request context - was it part of larger feature
4. Recent commits - was calling code removed or refactored
Report: Was this intentionally orphaned or accidentally broken?Example: Validating Findings
# Step 1: Run detection tool for your language
<tool> <source-path> --confidence-threshold 80 > findings.txt
# Step 2: For each high-confidence finding, spawn validation
# (Claude Code will use Task tool with Explore agents)Sample finding: unused function 'calculate_metrics' (src/analytics.py:45)
Multi-agent investigation results:
- Intent Agent: "Found TODO in src/dashboard.py:12 - 'integrate calculate_metrics here'"
- Integration Agent: "Function is imported in tests/test_analytics.py but test is marked skip/pending"
- History Agent: "Added in MR #234 'Add analytics foundation' - dashboard integration deferred"
Conclusion: NOT dead code - it's an unimplemented feature. Create tracking issue.
User Confirmation Flow
After agent analysis, use AskUserQuestion with multiSelect: true:
AskUserQuestion({
questions: [
{
question: "How should we handle these findings?",
header: "Action",
multiSelect: true,
options: [
{
label: "Remove confirmed dead code",
description: "Delete items verified as truly unused",
},
{
label: "Create issues for unimplemented",
description: "Track planned features in GitHub Issues",
},
{
label: "Investigate incomplete integrations",
description: "Spawn deeper analysis for partial implementations",
},
{
label: "Update whitelist",
description: "Add false positives to tool whitelist",
},
],
},
],
});Risk Classification
| Risk Level | Criteria | Action |
|---|---|---|
| Low | 100% confidence, no references anywhere, >6 months old | Auto-remove with VCS commit |
| Medium | 80-99% confidence, some indirect references | Validate with agents first |
| High | <80% confidence, recent code, has test coverage | Manual review required |
| Critical | Public API surface, documented, has external dependents | NEVER auto-remove |
---
Sources
- vulture GitHub
- knip documentation
- Effective TypeScript: Use knip
- Rust dead_code lint
- DCE-LLM research paper (emerging LLM-based approach)
Post-Execution Reflection
After this skill completes, check before closing:
1. Did the command succeed? — If not, fix the instruction or error table that caused the failure. 2. Did parameters or output change? — If the underlying tool's interface drifted, update Usage examples and Parameters table to match. 3. Was a workaround needed? — If you had to improvise (different flags, extra steps), update this SKILL.md so the next invocation doesn't need the same workaround.
Only update if the issue is real and reproducible — not speculative.
Evolution Log
Convention: Reverse chronological order (newest on top, oldest at bottom). Prepend new entries.
---
2026-02-26: Initial Evolution Log
Status: Skill is in use and maintained. Track improvements here.
Purpose
This evolution log tracks updates to the skill. Each entry should note:
- What changed (content, structure, tooling)
- Why it changed (bug fix, feature request, best practice)
- Files affected
How to Use
1. When updating SKILL.md or references, add an entry here with the date 2. Keep entries reverse-chronological (newest first) 3. Link to ADRs or GitHub issues when relevant 4. Reference specific line changes when helpful
---
Python Dead Code Detection with vulture
Advanced usage patterns for vulture in Python projects.
Installation
# Recommended: project-local with uv
uv pip install vulture
# Or globally
pipx install vultureCommand Reference
# Basic scan
vulture src/
# With confidence threshold (recommended: 80+)
vulture src/ --min-confidence 80
# Sort by size (prioritize large dead code blocks)
vulture src/ --sort-by-size
# Exclude patterns
vulture src/ --exclude "*_test.py,conftest.py,migrations/"
# Generate whitelist for false positives
vulture src/ --make-whitelist > vulture_whitelist.py
# Scan with whitelist
vulture src/ vulture_whitelist.pyWhitelist File Format
# vulture_whitelist.py
# Generated with: vulture src/ --make-whitelist
# Django views (called by URL routing)
handle_webhook # unused function (src/views.py:45)
# pytest fixtures
db_session # unused function (conftest.py:12)
# Celery tasks (called by broker)
process_queue # unused function (src/tasks.py:78)
# __all__ exports
_.some_function # unused attributeConfiguration (pyproject.toml)
[tool.vulture]
# Minimum confidence for reporting (60-100)
min_confidence = 80
# Paths to scan
paths = ["src", "tests"]
# Exclude patterns
exclude = [
"*_test.py",
"conftest.py",
"migrations/",
"__pycache__/",
]
# Whitelist files
whitelist = ["vulture_whitelist.py"]
# Sort output by code size
sort_by_size = trueIntegration with ruff
vulture complements ruff's F401 (unused imports) and F841 (unused variables):
| Tool | Scope | Confidence | Auto-fix |
|---|---|---|---|
| ruff | Imports, local variables | 100% | Yes |
| vulture | Functions, classes, attributes | 60-100% | No |
Recommended workflow:
1. Run ruff check --fix first (handles imports/variables) 2. Run vulture --min-confidence 80 for deeper analysis
Framework-Specific Whitelists
Django
# django_whitelist.py
from django.views import View
View.get
View.post
View.put
View.delete
View.patch
# Common patterns
urlpatterns
app_name
default_app_configFlask
# flask_whitelist.py
from flask import Blueprint
Blueprint.route
Blueprint.before_request
Blueprint.after_requestpytest
# pytest_whitelist.py
# Fixtures are discovered by name, not import
@pytest.fixture
def _():
passCI Integration
# .github/workflows/dead-code.yml (if using CI)
- name: Check for dead code
run: |
uv pip install vulture
vulture src/ vulture_whitelist.py --min-confidence 80Confidence Score Guide
| Score | Meaning | Example |
|---|---|---|
| 100% | Definitely unused in scanned files | Local variable never read |
| 90% | Very likely unused | Private function never called |
| 80% | Probably unused | Class attribute never accessed |
| 70% | Possibly unused (dynamic access possible) | Dict key, getattr target |
| 60% | Might be unused (framework magic likely) | Decorated function, __init__.py export |
Sources
Rust Dead Code Detection with cargo clippy
Advanced usage patterns for dead code detection in Rust projects.
Built-in Lints
Rust's compiler includes dead code detection by default:
# Standard build (warns on dead code)
cargo build
# Clippy with all warnings
cargo clippy
# Strict mode (errors instead of warnings)
cargo clippy -- -D dead_code -D unused_importsLint Categories
| Lint | Detects | Default |
|---|---|---|
dead_code | Unused functions, structs, enums, variants | Warn |
unused_imports | Imports not used in scope | Warn |
unused_variables | Variables assigned but never read | Warn |
unused_mut | Mutable bindings that don't need mut | Warn |
unused_assignments | Assignments that are never read | Warn |
unreachable_code | Code after return/panic/loop | Warn |
Command Reference
# Check for dead code only
cargo clippy -- -W dead_code
# Multiple lint categories
cargo clippy -- -W dead_code -W unused_imports -W unused_variables
# Deny (fail build) on dead code
cargo clippy -- -D dead_code
# Auto-fix what's possible
cargo clippy --fix --allow-dirty
# Check all targets (tests, examples, benches)
cargo clippy --all-targets -- -W dead_code
# JSON output for CI
cargo clippy --message-format=json -- -W dead_codeConfiguration (Cargo.toml)
[lints.rust]
dead_code = "warn"
unused_imports = "warn"
unused_variables = "warn"
unused_mut = "warn"
[lints.clippy]
# Additional clippy lints for unused code
needless_pass_by_value = "warn"
unused_self = "warn"Configuration (clippy.toml)
# Project-level clippy configuration
warn-on-all-wildcard-imports = trueSuppressing False Positives
Single Item
#[allow(dead_code)]
fn intentionally_unused_for_ffi() {
// Called from C code, Rust doesn't know
}Module-wide
#![allow(dead_code)]
// All items in this module can be unusedConditional Compilation
#[cfg(test)]
mod tests {
// Test helpers often appear "unused" to the compiler
#[allow(dead_code)]
fn test_helper() {}
}Feature-gated Code
#[cfg(feature = "unstable")]
#[allow(dead_code)]
pub fn experimental_api() {
// Only compiled with --features unstable
}Common False Positive Patterns
| Pattern | Why It's Flagged | Solution |
|---|---|---|
| FFI functions | Called from C/Python | #[allow(dead_code)] |
| Trait implementations | Methods required by trait | Usually not flagged |
| Derive macro outputs | Generated but not called | Usually not flagged |
| Test fixtures | Only used in test cfg | #[cfg(test)] module |
| Public API not used | Library exports | pub items are not flagged |
| Workspace crate | Used by other crates | Ensure proper extern crate |
Workspace Configuration
For monorepos, configure at workspace level:
# Workspace Cargo.toml
[workspace.lints.rust]
dead_code = "warn"
unused_imports = "warn"
# Per-crate Cargo.toml
[lints]
workspace = trueCI Integration
# Example CI step
- name: Check for dead code
run: |
cargo clippy --all-targets -- \
-D dead_code \
-D unused_imports \
-D unused_variablesComparison with Other Tools
| Tool | Scope | Integrated | Auto-fix |
|---|---|---|---|
rustc lints | Dead code, unused | Built-in | No |
cargo clippy | Style + dead code | Built-in | Some |
cargo-udeps | Unused dependencies | Addon | No |
cargo-machete | Unused dependencies | Addon | Yes |
Unused Dependencies
For detecting unused crate dependencies (not code):
# Install
cargo install cargo-udeps
# Run (requires nightly)
cargo +nightly udeps
# Alternative: cargo-machete (stable, faster)
cargo install cargo-machete
cargo macheteAnti-patterns
Don't Use #[deny(warnings)]
// BAD: Breaks on new compiler warnings
#![deny(warnings)]
// GOOD: Be explicit about what you deny
#![deny(dead_code)]
#![deny(unused_imports)]This is documented in Rust Design Patterns as an anti-pattern because new compiler versions may add warnings, breaking your build.
Sources
- Rust dead_code lint
- rustc warn-by-default lints
- cargo-clippy GitHub
- [#[deny(warnings)] anti-pattern](https://rust-unofficial.github.io/patterns/anti_patterns/deny-warnings.html)
TypeScript Dead Code Detection with knip
Advanced usage patterns for knip in TypeScript/JavaScript projects.
Installation
# Recommended: project-local
bun add -d knip
# Or with npm/pnpm
npm install -D knip
pnpm add -D knipCommand Reference
# Initialize configuration
bunx knip --init
# Basic scan
bunx knip
# Show only specific issue types
bunx knip --include files,exports,dependencies
# Auto-fix (removes unused exports)
bunx knip --fix
# Dry-run fix (preview changes)
bunx knip --fix-type exports --dry
# Verbose output
bunx knip --debug
# JSON output for CI
bunx knip --reporter jsonConfiguration (knip.json)
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"entry": ["src/index.ts", "src/cli.ts"],
"project": ["src/**/*.ts", "src/**/*.tsx"],
"ignore": ["**/*.test.ts", "**/*.spec.ts", "**/fixtures/**", "**/mocks/**"],
"ignoreDependencies": ["@types/*", "prettier", "eslint-*"],
"ignoreExportsUsedInFile": true
}Monorepo Configuration
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"workspaces": {
"packages/*": {
"entry": ["src/index.ts"],
"project": ["src/**/*.ts"]
},
"apps/web": {
"entry": ["src/main.tsx", "src/pages/**/*.tsx"],
"project": ["src/**/*.{ts,tsx}"]
}
}
}What knip Detects
| Category | Description | Auto-fix |
|---|---|---|
| Unused files | Files not imported anywhere | No |
| Unused exports | Exported but never imported | Yes |
| Unused dependencies | Listed in package.json but not imported | No |
| Unused devDeps | Dev dependencies not used in scripts | No |
| Unlisted deps | Imported but not in package.json | No |
| Duplicate exports | Same thing exported multiple times | Yes |
Framework Plugins
knip has built-in support for common frameworks:
{
"next": true,
"remix": true,
"astro": true,
"vite": true,
"vitest": true,
"jest": true,
"storybook": true
}These automatically configure entry points and ignore patterns.
Handling False Positives
Dynamic Imports
{
"entry": ["src/index.ts", "src/plugins/*.ts"]
}Re-exports (barrel files)
{
"ignoreExportsUsedInFile": true,
"ignore": ["**/index.ts"]
}Type-only Exports
knip v5+ handles type exports correctly. No special config needed.
Ignore Specific Exports
// Tells knip this export is intentionally unused
/** @internal */
export function _internalHelper() {}
// Or use comment
// knip-ignore
export const DEPRECATED_CONSTANT = 42;Migration from ts-prune
ts-prune is in maintenance mode. To migrate:
# Remove ts-prune
bun remove ts-prune
# Add knip
bun add -d knip
# Initialize
bunx knip --init
# ts-prune output format compatibility
bunx knip --reporter compactCI Integration
// package.json
{
"scripts": {
"dead-code": "knip",
"dead-code:fix": "knip --fix",
"dead-code:ci": "knip --reporter json --no-exit-code"
}
}Comparison: knip vs ts-prune
| Feature | knip | ts-prune |
|---|---|---|
| Maintained | Active | Maintenance |
| Unused dependencies | Yes | No |
| Unused files | Yes | No |
| Auto-fix | Yes | No |
| Monorepo support | Native | Limited |
| Framework plugins | 50+ | None |
| Performance | Fast | Fast |