On this page
How to Find and Remove Dead Code Your AI Assistant Left Behind
AI assistants leave dead functions, unused imports, and abandoned abstractions everywhere. Here's how to find dead code with grep and IDE tools, delete it safely, and stop the AI from generating more.
Quick answer
- AI assistants leave dead code after “refactor” passes — functions with no callers, imports that go nowhere, abstractions built for features that changed.
- Find it: grep for function names to check callers. Use IDE “find references.” If nothing calls it, delete it.
- Dead code is dangerous because the AI reads it and assumes it’s important — generating new code that depends on dead code.
- Full guide: How to Work With AI Assistants Without Creating Tech Debt
Why AI leaves dead code everywhere
AI assistants generate code for feature A. You ask for a change. The AI rewrites the feature but doesn’t delete the old implementation. The old function has no callers. It lives forever.
Three scenarios create AI dead code:
1. The refactor that didn’t clean up
# Feature A: AI writes this
def calculate_total_old(items):
return sum(item.price for item in items)
# You: "Change it to exclude refunded items"
# AI writes:
def calculate_total(items):
return sum(item.price for item in items if item.status != "refunded")
# calculate_total_old has no callers. Dead code.2. The abstraction that was never used
# AI generated a base class for future use:
class PaymentProcessor:
def process(self, payment): raise NotImplementedError
class StripeProcessor(PaymentProcessor):
def process(self, payment): ...
class PayPalProcessor(PaymentProcessor):
def process(self, payment): ...
# PayPalProcessor is never instantiated. Dead code.3. The import that survived editing
# AI generated:
import json
import os
import sys
from datetime import datetime
from .models import User
def get_user(id):
return User.query.get(id)
# json, os, sys, datetime imported but never used. Dead imports.Find dead code: three methods
Method 1: grep for callers
# Is this function called anywhere?
grep -r "calculate_total_old" src/ tests/
# No results outside its own definition? Dead.Search both src/ and tests/ — a function only called by tests but not by production code is still dead (the tests are dead too).
Method 2: IDE “find references”
Most IDEs (VS Code, PyCharm, IntelliJ) let you right-click a function → “Find All References.” If the only reference is the definition, it’s dead.
Method 3: Automated dead code detection
# Python: vulture finds unused code
pip install vulture
vulture src/
# JavaScript: no-unused-vars ESLint rule
# .eslintrc.json: "no-unused-vars": "error"
# General: most linters have unused-code rules
ruff check --select F401 # Python unused importsThese tools aren’t perfect — they can flag code that’s used dynamically — but they find 80% of dead code instantly.
Delete safely
Before deleting:
- Check callers — grep the function name across the entire project
- Check tests — is it tested? If yes, delete the test too
- Check for dynamic usage —
getattr(obj, "method_name"), Flask route decorators, signal handlers, and config references won’t show up in grep
# Comprehensive check before deleting:
grep -r "function_name" . # all references
grep -r "from .module import func" . # import statements
grep -r "getattr.*function_name" . # dynamic accessIf no results in any of these, it’s safe to delete.
Commit the deletion separately
git add -p # review the deletion
git commit -m "chore: remove dead code (unused functions from refactor)"A separate commit makes it easy to revert if something breaks.
Prevent the AI from generating dead code
Instruction: clean up after yourself
# In .aidigest or .cursorrules:
When modifying or replacing a function, always:
1. Check if the old implementation has any remaining callers
2. If no callers remain, delete the old implementation
3. Remove imports that are no longer usedAfter every AI session: dead-code sweep
# Quick sweep after an AI session:
# Find functions defined today
git diff --name-only | xargs grep "^def " | grep -v "test_"
# For each new function, check callers
grep -r "function_name" src/ tests/Where this bites vibecoders
The vibecoder accumulates 40 dead functions over a month of AI-assisted coding. The AI opens a file, sees
calculate_total_oldandcalculate_total_v2alongsidecalculate_total, and generates code callingcalculate_total_v2— because it assumes the most recent version is correct. The bug:calculate_total_v2was dead code with a known off-by-one error that was fixed in the current version. Deleting dead code isn’t cleanup — it’s bug prevention.