Skip to content

CLI

necro [options] [command]

Until the npm package ships, invoke the built CLI as node dist/cli.js …. Examples below use necro for brevity.

OptionDescription
-V, --versionPrint the version and exit.
-h, --helpShow help and exit.

Scan a path for anti-pattern code.

necro scan [path] [options]
ArgumentDefaultDescription
[path].Directory or file to scan.
OptionDescription
--jsonEmit findings as JSON instead of the terminal report.
--sarif <file>Write a SARIF 2.1.0 report to <file> for GitHub code-scanning / CI tooling.
--fail-on <severity>Exit non-zero if a finding at or above high | medium | low exists (see severity mapping).
--top <n>Show only the worst N findings (after worst-first sort).
--coverage <path>Path to an lcov report. Defaults to coverage/lcov.info; overrides the coveragePath config key.
-h, --helpShow help for scan.

When an lcov report is present, scan folds runtime coverage into each finding’s evidence chain. necro reads an existing report only — it never runs your test suite. Discovery order: --coverage <path> → the coveragePath config key → the default coverage/lcov.info. A missing report is silently ignored; an unreadable one prints a warning and the scan proceeds without coverage.

Each finding then shows one of three coverage states:

StateEvidence lineEffect
Miss✓ 0 coverage hits (lcov)Strengthens the dead verdict; a private, untainted candidate stays certain.
Runtime hit✗ executed at runtime (N hits) despite 0 static refs — reached dynamicallyA 0-static-ref symbol that ran is downgraded to maybe and never auto-removed.
Not available• coverage: not availableThe symbol’s file or line isn’t in the report; tiers are unaffected.

With no report at all, every finding renders coverage: not available — coverage is purely additive and never changes behavior when absent.

By default, scan prints a summary line followed by one evidence chain per dead-code finding, sorted worst-first (certainlikelymaybetest-only), then a Complexity section listing over-complex functions, a Risk hotspots ranking, and a Duplication section of copy-paste clones (each omitted when empty). With --json, it prints an object with four arrays — findings (dead code), complexity, hotspots, and duplication — see CI integration for the shape. --top N caps the dead-code findings; the other sections follow their own limits.

scan exits 0 on a successful run regardless of findings, unless --fail-on is set. A non-zero exit is also returned on an internal error.

--fail-on <severity> exits 1 if any finding is at or above the threshold, using one unified scale across all four axes:

SeveritySARIF levelFindings
higherrordead-code certain
mediumwarningdead-code likely; complexity (all detectors)
lownotedead-code maybe, test-only; duplication; hotspots

--fail-on high fails only on certain-dead code; --fail-on medium adds likely-dead and complexity; --fail-on low fails on anything. --fail-on and --sarif compose with --json and the human report.

Explain why a symbol is alive, test-only, or dead — traces the reachability witness chain for an alive symbol, or annotated inbound referrers for a dead one. Read-only; never edits your files.

necro explain <symbol> [options]
ArgumentDescription
<symbol>Symbol to explain: name, file:name, or file:line:name.
OptionDescription
--jsonEmit the explanation as JSON.
--narrateAdd an LLM plain-English explanation of the verdict (needs ANTHROPIC_API_KEY). Additive — the deterministic trace still renders, and --json output carries narrative: null, if the key is missing.
-h, --helpShow help for explain.

explain exits 0 when the symbol resolves to a single match, 1 when the query is ambiguous or can’t be resolved.

Verify whether deleting each named symbol keeps the build green. For every symbol, verify-removal plans its removal and checks it independently in its own throwaway git worktree (your working tree is never touched) — the empirical backbone behind fix --write --verify.

necro verify-removal <symbols...> [options]
ArgumentDescription
<symbols...>One or more symbols to test-remove: name, file:name, or file:line:name.
OptionDescription
--jsonEmit the per-symbol verdicts as JSON.
--checks <cmd>Check command to run after the simulated removal (repeatable — pass --checks multiple times to run several commands; default: typecheck + tests). A command containing a comma runs verbatim, not split.
-h, --helpShow help for verify-removal.

verify-removal exits 1 if any symbol’s removal breaks the build (a red verdict) — the headline CI-gating use case. An all-unresolved or all-green result exits 0; “couldn’t determine” is not treated as unsafe.

Safely remove certain-dead code. fix reuses the same detection as scan, then removes only certain-tier (auto-fix-eligible) symbols — likely, maybe, and test-only findings are never touched. Removals go through the TS compiler API (ts-morph), not text editing, so the edited file stays valid.

necro fix [path] [options]
ArgumentDefaultDescription
[path].Directory or file to fix.
OptionDescription
--writeApply the removals to disk. Without it, fix only previews a unified diff and changes nothing.
--forceBypass the dirty git-tree guard.
--coverage <path>Path to an lcov report, same as scan — keeps tiers consistent between the two.
-h, --helpShow help for fix.
  • Preview by default. necro fix prints the diff of what would be removed and writes nothing until you add --write.
  • Dirty-tree guard. With --write, fix refuses if the git working tree has uncommitted changes (git is your undo) — commit/stash first, or pass --force. If the target isn’t a git repo, it warns that there’s no undo and proceeds.
  • Single pass. fix removes what’s certain-dead in one scan; it does not re-analyze to chase code that becomes dead after a removal. Re-run fix to catch the next layer. Cascading re-analysis is planned.

fix exits 0 on every successful run (preview, write, or nothing-to-fix).

LLM-resolve the quarantined maybe findings — advisory and opt-in. triage scans (or reads a prior scan --json document), then asks the Anthropic API to adjudicate each maybe with a recommendation and rationale. It never edits your code; it only annotates findings. Requires ANTHROPIC_API_KEY.

necro triage [path] [options]
OptionDescription
--input <file>Triage a prior necro scan --json document instead of re-scanning.
--jsonEmit triaged findings as JSON.
-h, --helpShow help for triage.

Suggest LLM-assisted refactors — advisory and opt-in. refactor prints proposals and never edits your files. Each proposal is verified (typecheck + tests) in a throwaway git worktree before you see it, so a badged-green proposal is known to compile and pass tests. necro computes the diff itself (the model returns code, not a patch). Requires ANTHROPIC_API_KEY.

necro refactor [path] [options]
OptionDescription
--type <type>god-function (split an over-complex function) or extract-duplicate (lift a shared function out of a clone). Default god-function.
--limit <n>Max findings to propose refactors for (default 1).
--no-verifySkip scratch-worktree verification (typecheck + tests).
--jsonEmit proposals as JSON.
-h, --helpShow help for refactor.

Run necro as a read-only MCP server over stdio, so an AI agent (Claude Code, Cursor, Codex, Windsurf) can call necro’s verdicts and verify its own edits. necro never edits your files and never wraps an LLM on this path.

necro mcp

Four read-only tools are exposed:

ToolInputReturns
necro_scan{ path?, top?, coverage? }The same JSON as necro scan --json — dead-code tiers + evidence chains, complexity, hotspots, duplication.
necro_verify{ edits: {file, content}[], checks? }Applies the full-file edits in a throwaway git worktree, runs the checks (default: typecheck + tests), and returns { ok, output }. Your working tree is never touched.
necro_verify_removal{ symbols: string[], path?, checks? }For each symbol, plans its removal and verifies it in its own throwaway git worktree. Returns a per-symbol verdict — green (safe to delete), red (breaks the build), or unresolved.
necro_explain{ symbol, path?, narrate? }The same JSON as necro explain --json — the reachability witness chain for a symbol. Set narrate: true for an additive LLM plain-English explanation (needs an API key, degrades gracefully without one).

Register it with your agent (Claude Code example):

{
"mcpServers": {
"necro": { "command": "npx", "args": ["-y", "@manehorizons/necro", "mcp"] }
}
}