CLI reference

One binary. Nine verbs.

Everything the MCP server exposes is also a command, so CI and humans see exactly what the agent sees. Plugins render --format table as a native markdown table.

deadpath scan      [PATH] [--mock] [--format json|md|sarif|table] [--lang LANG]
                         [--only-new] [--compact] [--min-confidence 0.25]
                         [--no-memory] [--no-judge]
deadpath judge     [PATH] [--format table|md|json]
deadpath plan      [PATH] [--format json|md|table]
deadpath workflow  [PATH] [--format json|md|table] [--max 12] [--no-triage] [--no-llm]
deadpath triage    [PATH] [--format json|md|table] [--max-items 8] [--no-llm]
deadpath explain   FINDING_ID [PATH]
deadpath remember  FINDING_ID --decision keep|false_positive|resolved [--note ...] [--path PATH]
deadpath memory    [PATH] [--clear] [--forget FINDING_ID]
deadpath languages
deadpath mcp

Flags that matter

FlagEffect
--lang LANGauto (default) or one of py ts go rust java kotlin scala csharp ruby php swift dart elixir c lua perl. See Languages.
--format sarifSARIF 2.1.0 for GitHub Code Scanning; confidence and signals travel in properties.
--only-newShow only findings not present in memory; exit 1 only for new block findings. This is the CI ratchet.
--compactJSON: full evidence for new findings, one-liners for persisting ones, trimmed profile and memory summary, plus tokens_saved_estimate.
--min-confidenceDrop findings below the threshold (default 0.25).
--no-memoryStateless run; do not read or write .deadpath/memory.json.
--no-judgeSkip the devil's advocate pass; report raw scan confidence.
--format tableGitHub-flavoured markdown table (the plugin-facing format). deadpath judge defaults to it.
--no-llmForce heuristic triage even if an API key is set.
--max-itemsCap on findings sent to the model per triage run (default 8). Extra findings receive heuristic verdicts and are deferred.

Exit codes

Finding schema

Finding(
  id: str,                  # kind:path[:symbol] — stable across runs
  kind: str,                # unused_export | orphan_file | unused_dep | unreachable
  severity: str,            # block | warn | note   (derived from confidence)
  path: str,
  symbol: str | None,
  why: str,
  evidence: list[str],
  confidence: float,        # 0..1, deterministic
  signals: dict[str, float],# named adjustments that produced the score
  critique: dict | None     # judge verdict, objections, identification, security, effort
)

block ≥ 0.85, warn ≥ 0.55, else note. See Confidence for every scan signal and Judge for the devil's advocate pass. The --min-confidence threshold applies to the scan score so a keep verdict cannot hide the finding.

Scan JSON envelope

{
  "tool": "deadpath", "version": "0.1.0", "auto_delete": false,
  "profile": { "languages": {"py": 6, "go": 3}, "primary": "py", "frameworks": ["fastapi"],
               "monorepo": false, "validate_commands": {...}, ... },
  "counts": { "block": 2, "warn": 1, "note": 0, "total": 3 },
  "findings": [ ...full Finding objects (new ones by default; all with --format json) ],
  "persisting_brief": [ { "id": "...", "severity": "block", "confidence": 0.92 } ],
  "delta": { "new": [...], "resolved": [...], "suppressed": [...], "counts": {...} },
  "suppressed": [ { "id": "...", "decision": "keep" } ],
  "memory": { "runs": 3, "cache_hits": 9, "cache_misses": 0, ... },
  "tokens_saved_estimate": 269
}

Workflow JSON

{
  "policy": { "block_threshold": 0.85, "warn_threshold": 0.55,
              "delete_requires": "explicit user approval after validation steps pass" },
  "llm": { "policy": "veto-only counsel on remove then verify; keep/note never sent; ...",
           "enabled": false, "called": false, "asked": 0, "cached": 0, "heuristic": 4,
           "skipped_keep": 1, "skipped_note": 0, "reviewed_remove": 3, "reviewed_verify": 1 },
  "selected_findings": [...], "kept_by_triage": [...], "omitted_findings": 0,
  "steps": [
    { "id": "verify-02", "phase": "verify", "finding_id": "...", "grep": "maybe_dead",
      "read": ["pkg/hooks.py"], "triage": "verify: dynamic or string reference signal present; ...",
      "budget_hint": "Triage flagged a dynamic/string reference: read the grep hits, not the whole file." },
    { "id": "validate-07", "phase": "validate", "command": "pytest -q", ... },
    { "id": "mem-09", "phase": "remember", "tool": "deadpath.remember", ... }
  ]
}

Triage JSON

{
  "verdicts": {
    "unused_export:pkg/hooks.py:maybe_dead": {
      "verdict": "verify", "reason": "...", "model": "heuristic", "digest": "9f2c…", "at": "2026-09-08T19:40:00Z" }
  },
  "llm": { "enabled": true, "called": true, "asked": 4, "cached": 5, "heuristic": 0,
           "skipped_keep": 1, "skipped_note": 0, "reviewed_remove": 3, "reviewed_verify": 1, "deferred": 0, "model": "gpt-4o-mini",
           "prompt_tokens_estimate": 612 }
}

Judge

deadpath judge prints the due-diligence table: prosecution vs devil's advocate, identification, security lens, effort. Default format is table; md adds case-file write-ups; json is the machine envelope. See Judge.

Plan

deadpath plan returns an ordered suggestion list ranked by judge verdict then confidence. Judge keep findings are omitted. Deadpath never deletes files and never writes a patch in v0.

Explain

Optional OpenAI-compatible HTTP if DEADPATH_API_KEY or OPENAI_API_KEY is set; otherwise a heuristic paragraph that names the signals that mattered. Pass --no-llm / MCP llm: false to force the heuristic. No vendor SDKs.