find_dead_code β
Finds symbols no one references, files with zero live symbols, exports that are never imported, and scaffolding comments (TODO/FIXME/HACK) left behind during development. Each dead symbol comes with a confidence score and a human-readable reason.
When to use
Cleanup sprints, pre-release housekeeping, and whenever get_changed_symbols surfaces files you suspect nothing consumes anymore.
Parameters β
| Name | Type | Required | Description |
|---|---|---|---|
includeTests | boolean | no | Count test files as normal reachable code. Default false |
intent | string | no | Filter deadSymbols by keyword (e.g. "adapter", "core", "function") |
Example β
json
{ "includeTests": false }Narrow to adapters only:
json
{ "intent": "adapters" }Response β
json
{
"totalSymbols": 1847,
"reachableSymbols": 1792,
"deadSymbols": [
{
"symbolId": "packages/cli/src/adapters/storage/legacy.ts::oldSerialize::function",
"name": "oldSerialize",
"kind": "function",
"file": "packages/cli/src/adapters/storage/legacy.ts",
"confidence": 1.0,
"reason": "Zero importers -- no code references this symbol"
}
],
"unusedExports": [ /* exports nothing else imports */ ],
"deadFiles": [
"packages/cli/src/adapters/storage/legacy.ts"
],
"scaffolding": [
{ "file": "packages/cli/src/core/foo.ts", "line": 42, "kind": "TODO", "text": "handle empty case" }
],
"deadCodePercentage": 3.0,
"_meta": { "totalItems": 55, "returnedItems": 55, "truncated": false }
}Confidence tiers β
| Score | Meaning |
|---|---|
1.0 | Zero importers -- no code references this symbol |
0.9 | Only referenced from test/config files |
0.7 | All importers are themselves dead (cascading dead code) |
When to use β
- Cleanup PRs -- start with
confidence: 1.0symbols. - Scaffolding audit -- the
scaffolding[]field surfaces every TODO/FIXME/HACK with file+line for triage. - Unused exports -- the
unusedExports[]field is subtler thandeadSymbols; an unused export may still be an entry point, so review before deleting.
Pitfalls β
Dynamic dispatch is invisible
Reflection, string-based lookups, and framework auto-registration (e.g. dependency injection by name) look like "no importers" to the graph. Verify with find_importers plus a quick grep before deleting anything even at confidence: 1.0.
- Framework entry points are filtered by heuristic patterns. If your framework is unusual, expect false positives.
includeTests: false(default) means a symbol used only by tests counts as dead. Flip totrueif test-only utilities should stay.- Requires
ctxo index.
Related tools β
find_importers-- double-check before deletingget_blast_radius-- confirm nothing transitive breaksget_change_intelligence-- dead + churny = the easiest wins