Dead Code Hunter
Systematic scan of the dependency graph to surface orphan symbols and unreferenced files. Produces a ranked, safety-annotated deletion plan powered by Graph-It-Live.
Requires
Graph-It-Live CLI installed and indexed:
npm install -g @magic5644/graph-it-live
graph-it scanWhen to Use
- Before a major refactor — clean up before you restructure
- After removing a feature — confirm nothing is left dangling
- Periodic code hygiene pass on a growing codebase
- Before onboarding a new developer — reduce noise in the codebase
Critical Prerequisite — Reversed Index
Without--reversedIndex=true, every caller/reference lookup returns empty results → guaranteed false positives.get_symbol_callersandfind_referencing_filesboth query the reverse index. If the index was built without it, all symbols will appear orphaned, even live ones. Always build the index with--reversedIndex=truebefore running this skill.
Scope Caveat
find_unused_symbolsoperates per-file. There is no singlegraph-it deadcode --projectcommand (yet). This skill orchestrates multiple tool calls to achieve project-wide coverage. On very large projects (500+ files), prioritize high-risk folders (src/,lib/,core/) rather than scanning everything. For a fully automated single-pass solution, the right approach is a nativegraph-it deadcodeCLI command built into@magic5644/graph-it-live. That would have significantly higher impact than this skill alone, but requires development work on the CLI itself.
Workflow — Step by Step
Step 1 — Build/refresh the index
graph-it scan --reversedIndex=true--reversedIndex=true is mandatory. It instructs graph-it to build the reverse lookup index (who imports what, who calls what). Without it, Steps 4 and 5 have no data and every symbol will appear uncalled — producing false positives across the entire scan.Step 2 — Get the list of project files
graph-it tool get_index_statusParse the output to retrieve the list of indexed source files. Filter out:
node_modules/,dist/,build/,.cache/- Test files (
*.test.*,*.spec.*,__tests__/) — treat separately - Type declaration files (
*.d.ts) - Configuration files (
*.config.*,vite.config.*, etc.)
This is your scan target list.
Step 3 — Per-file unused symbol scan
For each file in the scan target list, run:
graph-it tool find_unused_symbols --filePath=<absolutePath>Collect results into a flat list:
[
{ file: "src/utils/format.ts", symbol: "formatCurrency", kind: "function" },
{ file: "src/services/legacyAuth.ts", symbol: "hashPasswordMD5", kind: "function" },
...
]Step 4 — Confirm with caller lookup (avoid false positives)
find_unused_symbols detects exports not imported by other files in the index. However a symbol may be called dynamically or from outside the indexed workspace (e.g. a published library). For every candidate, confirm with:
graph-it tool get_symbol_callers --filePath=<absolutePath> --symbolName=<symbol> --reversedIndex=truePassing --reversedIndex=true here ensures the tool queries the reverse call graph. Omitting it falls back to forward-only traversal, which will miss most callers.- 0 callers → confirmed dead code candidate
- 1+ callers → false positive, discard
- Only test-file callers → flag as "test-only symbol", handle separately
Step 5 — Detect fully orphaned files
A file is a ghost file if:
- It has 0 referencing files (nothing imports it)
- It is not a known entry point (index, main, cli, server, etc.)
Check with:
graph-it tool find_referencing_files --filePath=<absolutePath> --reversedIndex=trueWithout --reversedIndex=true, this tool cannot find reverse references and will incorrectly classify every file as unreferenced.A ghost file may contain multiple symbols — mark the entire file for deletion rather than symbol-by-symbol.
Step 6 — Rank candidates by deletion safety
Apply this risk classification:
| Risk Level | Criteria | Action |
|---|---|---|
| Safe | 0 callers, 0 referencing files, not a public API export | Delete freely |
| Likely safe | 0 callers confirmed, file has other live symbols | Remove symbol, keep file |
| Review first | Symbol is exported from a barrel (index.ts) | Check if barrel is consumed externally |
| Do not delete | Dynamic call patterns detected (eval, string-based dispatch) | Flag only |
| Test-only | Only called from test files | Evaluate — may be intentional |
Output Format
Produce a Deletion Plan in this format:
Dead Code Scan Report
Scanned: <N> files | Candidates found: <M> symbols + <K> ghost files
Ghost Files (entire file can be deleted)
| File | Last modified | Reason |
|---|---|---|
src/utils/oldMigration.ts | 2022-03-11 | 0 imports, 0 callers, not an entry point |
Suggested command:
# Review first, then:
rm src/utils/oldMigration.tsOrphan Symbols — Safe to Remove
| Symbol | File | Kind | Callers |
|---|---|---|---|
formatLegacyCurrency | src/utils/format.ts | function | 0 |
MD5Hash | src/services/auth.ts | function | 0 |
Orphan Symbols — Review First
| Symbol | File | Risk | Note |
|---|---|---|---|
createReport | src/api/index.ts | Barrel export | Check if consumed by external packages |
Test-Only Symbols
| Symbol | File | Test callers |
|---|---|---|
mockPaymentGateway | src/mocks/payment.ts | 3 test files |
Recommended Deletion Order
- Ghost files first — highest impact, no surgical precision needed
- Orphan symbols in non-barrel files — safe, isolated changes
- Barrel exports — requires checking external consumers
- Test-only symbols — discuss with the team
Safety Checklist Before Deleting
- Run
graph-it tool get_symbol_callers --reversedIndex=trueone more time after any refactor that modified imports - Check if the project is a published library — unused exports may be part of the public API
- Check
package.jsonexportsfield — symbols exported via package entry points are always live - Run the test suite after each deletion batch to catch dynamic usage not visible to static analysis
- Commit in small batches — one file or one symbol group per commit for easy revert
Quick Scan (Single File or Folder)
If you only want to scan one file:
graph-it scan --reversedIndex=true # rebuild if not already done with the flag
graph-it check src/utils/format.ts
graph-it tool find_unused_symbols --filePath=/abs/path/src/utils/format.tsIf you want a folder, use graph-it summary <folder> to get the file list, then iterate.
Limitations & Future Improvements
- Dynamic dispatch (
obj[methodName](),require(variable)) is invisible to static analysis — always review before deleting - Monorepos: scan per package, not at root, to avoid cross-package false positives
- Framework magic: decorators (
@Component,@Injectable) may make symbols appear unused but they're resolved at runtime — exclude framework entry files from the scan graph-it deadcodeCLI command (not yet available): a native single-pass project-wide dead code scanner would eliminate the per-file iteration overhead and provide a richer output with confidence scores. If this is a bottleneck, open an issue on@magic5644/graph-it-live.