Dead-code detection that's fast (under 10 seconds for any repo size,
no LLM involvement) and conservative by design. Findings are
classified into confidence tiers; safe_to_delete requires
confidence ≥ 0.70 and excludes dynamically-loaded patterns
(*Plugin, *Handler, *Adapter, *Middleware). Framework-aware:
Flask, FastAPI, Django, Rails, Laravel, and TYPO3 routes and
convention files don't get flagged as unused. How findings are scored is on
Dead code; which kinds are shown by default is
on Findings and triage. The other tools are on
MCP tools.
When to call
- Before refactor sprints:
min_confidence=0.7to prioritize safe deletions. - Library API audits:
kind="unused_export"to find unused public symbols. - Monorepo cleanup:
include_zombie_packages=Trueto find packages no other package depends on. - Aggressive cleanup:
include_internals=Trueasks for unused private symbols. That kind is currently hidden by the finding-type registry, so the call returns none and reports the held-back count insummary.withheld_types. The CLI'srepowise dead-code --include-internalsstill lists them.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
repo | string | — | Repository alias. Pass "all" for a workspace-wide scan. |
kind | string | — | Filter by finding kind: "unreachable_file", "unused_export", "unused_internal", "zombie_package". |
min_confidence | number | 0.4 | Confidence threshold. 0.7 is a good default for actionable cleanups. |
safe_only | boolean | false | Return only findings marked safe_to_delete. |
limit | number | 20 | Max findings per tier. Clamped to 25 by the MCP transport budget. |
tier | string | — | Focus on one tier: "high" (≥0.7), "medium" (0.4 to 0.7), "low" (<0.4). |
directory | string | — | Filter to a path prefix (e.g. "src/"). |
owner | string | — | Filter by primary owner name. |
group_by | string | — | "directory" for per-dir rollup, "owner" for ownership hotspots. |
include_internals | boolean | false | Ask for unused private/internal symbols. The kind is hidden today, so they are counted in summary.withheld_types, not listed. |
include_zombie_packages | boolean | true | Include monorepo packages with no importers. |
no_unreachable | boolean | false | Skip file-level reachability findings. |
no_unused_exports | boolean | false | Skip public-export findings. |
finding_id | string | — | Expand one finding by the stable id a previous response emitted. |
Returns
| Field | Description |
|---|---|
summary | total_findings, filtered_findings, deletable_lines, safe_to_delete_count, by_kind, and withheld_types: finding types held back on every surface, each with a count and reason |
tiers.{high,medium,low} | Each: description, count, lines, safe_count, findings, truncated |
by_directory | (if group_by="directory") per-dir rollup sorted by lines |
by_owner | (if group_by="owner") ownership hotspots sorted by lines |
impact | total_lines_reclaimable, safe_lines_reclaimable, recommendation |
limit_note | Present if the requested limit was clamped to 25 |
Each finding contains kind, file_path, symbol_name, confidence,
reason, safe_to_delete, lines, last_commit_at, primary_owner,
age_days, and last_meaningful_change.
Example
get_dead_code(min_confidence=0.7) # safe cleanups only
get_dead_code(kind="unused_export", group_by="owner")
get_dead_code(directory="src/legacy/", include_internals=True)
get_dead_code(repo="all") # workspace-wideThings worth knowing
- Confidence tiers:
- High (≥ 0.7): no references found. Strong cleanup candidates.
- Medium (0.4 to 0.7): likely unused, may have indirect references.
- Low (< 0.4): possibly used via dynamic dispatch / reflection.
- Safe-to-delete heuristic: zero references and stable age (not modified in months). The threshold isn't just confidence. A whole unreachable file is never marked safe: it always needs a review.
- Workspace-wide (
repo="all"): repos are scanned concurrently; a repo that fails is named inrepos_failed, and one whose index is behind inrepos_stale. - Preview languages: dead code on Java, C#, C, C++, Kotlin and Swift
is served with a preview label in
_meta.previewthat carries its latest hand-judged measurement. - Cross-repo adjustment (workspace mode): if a file has cross-repo
consumers, confidence is reduced by 50%; if other repos depend on
this repo's package,
unused_exportconfidence drops to 30% with a verification note. - Zombie package detection: monorepo packages flagged when no other package depends on them.
- Last meaningful change: derived from significant commits (feature/fix/refactor only, style/chore filtered out).
- Withheld types: a finding kind the registry hides is left out of
every tier and total, even when named with
kind. When one had rows,summary.withheld_typesgives its count, state and reason. - Limit clamping: requests over 25 are clamped due to the MCP
transport budget.
limit_notewill suggest tier/directory/owner filters to paginate.
Repowise surfaces candidates. Engineers decide. Keep the team in the
loop on big deletions. group_by="owner" makes it easy to route a
cleanup PR to the right reviewer.