
Vulture Dead Code
- 77 installs
- 49 repo stars
- Updated August 4, 2026
- laurigates/claude-plugins
Helps with ai & agent building tasks.
About
vulture-dead-code is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- vulture-dead-code
- AI & Agent Building
- AI-coding skill
Vulture Dead Code by the numbers
- 77 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #5,358 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/laurigates/claude-plugins --skill vulture-dead-codeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 77 |
|---|---|
| repo stars | ★ 49 |
| Last updated | August 4, 2026 |
| Repository | laurigates/claude-plugins ↗ |
What it does
Helps with ai & agent building tasks.
Files
Vulture and deadcode - Dead Code Detection
Tools for finding unused Python code including functions, classes, variables, imports, and attributes.
When to Use This Skill
| Use this skill when... | Use another tool instead when... |
|---|---|
| Detecting unused functions, classes, variables | Finding unused imports only (use ruff --select F401) |
| Cleaning up dead code in a codebase | Checking type correctness (use basedpyright) |
| Enforcing code hygiene in CI | Formatting code (use ruff format) |
| Generating whitelists for false positives | Running general linting (use ruff check) |
Overview
Vulture (mature, confidence-based) and deadcode (newer, AST-based) both detect unused code but with different approaches:
| Feature | Vulture | deadcode |
|---|---|---|
| Approach | Static analysis + confidence scores | AST-based detection |
| Accuracy | Confidence scores (60-100%) | High accuracy, fewer false positives |
| Speed | Fast | Very fast |
| Configuration | Whitelist files | TOML configuration |
| Maturity | Mature (2012) | Newer (2023+) |
| Best For | Large codebases, gradual cleanup | New projects, strict enforcement |
Installation
# Install vulture
uv add --dev vulture
# Install deadcode (newer alternative)
uv add --dev deadcode
# Install both for comparison
uv add --dev vulture deadcodeVulture - Confidence-Based Detection
Basic Usage
# Check entire project
vulture .
# Check specific files/directories
vulture src/ tests/
# Minimum confidence threshold (60-100%)
vulture --min-confidence 80 .
# Exclude patterns
vulture . --exclude "**/migrations/*,**/tests/*"
# Sort by confidence
vulture --sort-by-size .
# Generate whitelist of current issues
vulture . --make-whitelist > vulture_whitelist.pyConfiguration (pyproject.toml)
[tool.vulture]
min_confidence = 80
paths = ["src", "tests"]
exclude = [
"**/migrations/*",
"**/__pycache__/*",
".venv/*"
]
ignore_decorators = [
"@app.route",
"@pytest.fixture",
"@property",
"@staticmethod",
"@classmethod"
]
ignore_names = [
"test_*",
"setUp*",
"tearDown*",
]deadcode - AST-Based Detection
Basic Usage
# Check entire project
deadcode .
# Check specific files/directories
deadcode src/
# Verbose output
deadcode --verbose .
# Dry run (show what would be removed)
deadcode --dry-run .
# Show unreachable code
deadcode --show-unreachable .
# Generate configuration
deadcode --initConfiguration (pyproject.toml)
[tool.deadcode]
paths = ["src"]
exclude = [
"tests/*",
"**/__pycache__/*",
"**/migrations/*",
]
ignore_names = [
"test_*",
"setUp",
"tearDown",
"main",
]
ignore_decorators = [
"app.route",
"pytest.fixture",
"property",
"staticmethod",
"classmethod",
"abstractmethod"
]
show_unreachable = falseChoosing Between Tools
| Choose Vulture when... | Choose deadcode when... |
|---|---|
| Large, mature codebases | New projects |
| Need confidence-based filtering | Want fewer false positives |
| Need whitelist file approach | Prefer TOML configuration |
| Dynamic code (getattr, exec) | Need unreachable code detection |
Hybrid Approach
# Run both for comprehensive detection
vulture --min-confidence 80 .
deadcode .Agentic Optimizations
| Context | Command |
|---|---|
| Quick vulture check | vulture --min-confidence 90 . |
| Quick deadcode check | deadcode . |
| Generate whitelist | vulture . --make-whitelist > vulture_whitelist.py |
| CI enforcement | vulture --min-confidence 80 . vulture_whitelist.py |
| Unreachable code | deadcode --show-unreachable . |
| Combined check | vulture --min-confidence 80 . && deadcode . |
Quick Reference
Vulture Flags
| Flag | Description |
|---|---|
--min-confidence N | Minimum confidence (60-100%) |
--exclude PATTERN | Exclude glob patterns |
--sort-by-size | Sort results by size |
--make-whitelist | Generate whitelist file |
deadcode Flags
| Flag | Description |
|---|---|
--verbose | Verbose output |
--dry-run | Show without modifying |
--show-unreachable | Detect unreachable code |
--init | Generate configuration |
--strict | Strict enforcement mode |
For detailed examples, advanced patterns, and best practices, see REFERENCE.md.
Vulture and deadcode - Reference
Detailed reference material for vulture and deadcode dead code detection tools.
Vulture Whitelist Pattern
# vulture_whitelist.py
# Whitelist for false positives
# Used by external code
_.used_by_external_lib # confidence: 60%
MyClass.called_dynamically # confidence: 60%
# Used in templates
def render_template_helper():
pass # confidence: 60%
# Used via __getattr__
dynamic_attribute = None # confidence: 60%
# Framework magic
class Meta: # Django/Flask metadata
pass
# Plugin system
def plugin_hook(): # Called by plugin system
passUnderstanding Confidence Scores
# 100% confidence (definitely unused)
def never_called():
"""This function is never called anywhere."""
pass
# 80% confidence (likely unused)
def maybe_called():
"""Called in commented code or string."""
pass
# 60% confidence (possibly unused)
def dynamic_call():
"""Might be called via getattr() or string."""
pass
# Set minimum confidence threshold
# --min-confidence 80 = Report only high-confidence issues
# --min-confidence 60 = Report all potential issues (more false positives)Common Vulture Patterns
Unused Imports
# FOUND: Unused import
import sys # confidence: 100%
import os # confidence: 100%
# USED: Import is used
import logging
logger = logging.getLogger(__name__)Unused Functions
# FOUND: Unused function
def unused_helper(): # confidence: 100%
return 42
# USED: Function is called
def used_helper():
return 42
result = used_helper()Unused Class Attributes
class MyClass:
# FOUND: Unused attribute
unused_attr = 42 # confidence: 100%
# USED: Attribute is accessed
used_attr = 42
def method(self):
return self.used_attrUnused Variables
def process():
# FOUND: Unused variable
unused = calculate() # confidence: 100%
# USED: Variable is used
result = calculate()
return resultFalse Positives (When to Whitelist)
# 1. Dynamic attribute access
class Config:
DEBUG = True # Accessed via getattr(config, 'DEBUG')
# 2. Framework magic
class Meta: # Used by Django ORM
db_table = 'users'
# 3. Decorators
@app.route('/api/data')
def api_endpoint(): # Route handler - appears unused
pass
# 4. Test fixtures
@pytest.fixture
def sample_data(): # Fixture - appears unused
return [1, 2, 3]
# 5. Plugin hooks
def plugin_initialize(): # Called by plugin system
pass
# 6. Serialization
class User:
def to_dict(self): # Called by serialization library
passGradual Cleanup Strategy
# Step 1: Generate baseline
vulture --make-whitelist > vulture_whitelist.py
# Step 2: Fix high-confidence issues
vulture --min-confidence 90 .
# Step 3: Lower threshold gradually
vulture --min-confidence 80 .
vulture --min-confidence 70 .
# Step 4: Update whitelist
vulture --make-whitelist > vulture_whitelist.py
# Step 5: Enforce in CI
vulture --min-confidence 80 .deadcode Common Patterns
Unused Code Detection
# FOUND: Unused function
def unused_function():
return 42
# FOUND: Unused class
class UnusedClass:
pass
# FOUND: Unused variable
UNUSED_CONSTANT = 42
# FOUND: Unused import
import unused_moduleUnreachable Code Detection
def example():
return 42
print("Unreachable") # FOUND: Code after return
def example2():
raise ValueError("Error")
cleanup() # FOUND: Code after raise
def example3():
if True:
return
else:
process() # FOUND: Unreachable branchdeadcode False Positives Configuration
# 1. Public API (keep even if unused internally)
# Add to ignore_names in pyproject.toml
[tool.deadcode]
ignore_names = ["PublicAPIClass", "public_function"]
# 2. Framework magic
[tool.deadcode]
ignore_decorators = ["app.route", "celery.task"]
# 3. Test infrastructure
[tool.deadcode]
ignore_names = ["test_*", "setUp*", "tearDown*"]
# 4. Entry points
[tool.deadcode]
ignore_names = ["main", "__main__"]Comparison: Vulture vs deadcode
When to Choose Vulture
Use Vulture for:
- Large, mature codebases with complex dynamics
- Gradual cleanup with confidence-based filtering
- Whitelisting false positives easily
- Handling dynamic code (getattr, exec, etc.)
Example workflow:
# Start with high confidence
vulture --min-confidence 90 .
# Generate whitelist for false positives
vulture --make-whitelist > vulture_whitelist.py
# Edit whitelist manually
vim vulture_whitelist.py
# Run with whitelist
vulture . vulture_whitelist.pyWhen to Choose deadcode
Use deadcode for:
- New projects with strict code hygiene
- Fewer false positives desired
- AST-based accuracy
- Unreachable code detection
Example workflow:
# Generate initial config
deadcode --init
# Configure in pyproject.toml
[tool.deadcode]
paths = ["src"]
ignore_decorators = ["app.route"]
# Run checks
deadcode .
# Enforce in CI
deadcode --strict .Hybrid Approach
Use both tools for comprehensive detection:
# Run vulture for broad detection
vulture --min-confidence 80 .
# Run deadcode for precise detection
deadcode .
# Compare results and whitelist false positivesCI Integration
GitHub Actions with Vulture
# .github/workflows/deadcode.yml
name: Dead Code Check
on: [push, pull_request]
jobs:
vulture:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v2
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras --dev
- name: Run vulture
run: |
uv run vulture . \
--min-confidence 80 \
vulture_whitelist.py
- name: Upload results
uses: actions/upload-artifact@v4
if: failure()
with:
name: vulture-results
path: vulture-output.txtGitHub Actions with deadcode
# .github/workflows/deadcode.yml
name: Dead Code Check
on: [push, pull_request]
jobs:
deadcode:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v2
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras --dev
- name: Run deadcode
run: uv run deadcode .
- name: Check for unreachable code
run: uv run deadcode --show-unreachable .Pre-commit Hook
# .pre-commit-config.yaml
repos:
# Vulture
- repo: https://github.com/jendrikseipp/vulture
rev: v2.11
hooks:
- id: vulture
args: ['--min-confidence', '80']
files: ^src/
# deadcode
- repo: https://github.com/albertas/deadcode
rev: v2.0.0
hooks:
- id: deadcode
args: ['.']
files: ^src/Best Practices
1. Start with High Confidence
# Begin with high confidence (fewer false positives)
vulture --min-confidence 90 .
# Gradually lower threshold
vulture --min-confidence 80 .
vulture --min-confidence 70 .2. Use Whitelists for False Positives
# vulture_whitelist.py
# Document WHY each item is whitelisted
# Framework routes (Flask/Django)
@app.route('/api/endpoint')
def api_handler(): # Called by framework
pass
# Pytest fixtures
@pytest.fixture
def sample_data(): # Used by test functions
return [1, 2, 3]
# Plugin hooks
def on_load(): # Called by plugin system
pass3. Integrate into Development Workflow
# Local development: Quick check
vulture src/ --min-confidence 90
# Pre-commit: Catch obvious issues
pre-commit run vulture --all-files
# CI: Strict enforcement
vulture . --min-confidence 80 vulture_whitelist.py4. Review and Clean Regularly
# Weekly: Review dead code
vulture --make-whitelist > current_issues.txt
# Compare with last week
diff current_issues.txt last_week_issues.txt
# Clean up incrementally
git grep "def unused_function" | xargs -I {} git rm {}5. Combine with Other Tools
# Dead code + unused imports
vulture . && ruff check --select F401 .
# Dead code + type checking
vulture . && basedpyright
# Dead code + coverage
pytest --cov=src && vulture src/Common Pitfalls
1. Dynamic Code
# Problem: vulture can't detect dynamic usage
def dynamic_call():
pass
# Called via getattr
func = getattr(module, "dynamic_call")
func()
# Solution: Whitelist or use ignore comment
def dynamic_call(): # noqa: vulture
pass2. Test Code
# Problem: Test fixtures appear unused
@pytest.fixture
def sample_data(): # Appears unused to vulture
return [1, 2, 3]
# Solution: Configure ignore_decorators
[tool.vulture]
ignore_decorators = ["pytest.fixture"]3. Public API
# Problem: Public API unused internally
class PublicAPI:
def public_method(self): # Not called in codebase
pass
# Solution: Whitelist or document
[tool.deadcode]
ignore_names = ["PublicAPI"]4. Framework Magic
# Problem: Framework calls code dynamically
class Meta: # Django ORM metadata
db_table = 'users'
@app.route('/api') # Flask route
def endpoint():
pass
# Solution: Configure ignore_decorators
[tool.vulture]
ignore_decorators = ["app.route"]
ignore_names = ["Meta"]IDE Integration
VS Code
// settings.json
{
"python.linting.enabled": true,
"python.linting.vulture.enabled": true,
"python.linting.vulture.args": [
"--min-confidence", "80"
]
}Neovim with LSP
-- Using null-ls
local null_ls = require("null-ls")
null_ls.setup({
sources = {
null_ls.builtins.diagnostics.vulture.with({
extra_args = { "--min-confidence", "80" }
}),
}
})