Skip to content

About

Local code intelligence and a pre-submit verification gate for AI coding agents: dead code, hallucinated dependencies, weakened tests. CLI + MCP.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Plumbgraph logo: a plumb line through a small code graph

Plumbgraph

Know your code. Verify the change.
Local code intelligence and a pre-submit gate for AI coding agents, over CLI and MCP.

CI License: Apache-2.0 Latest release Rust 1.85+ MCP over stdio

Terminal recording of `plumb verify --run --online` on the demo app: a hallucinated import, an unused function, an eval() and a print() are reported; verdict FAIL

Real output of plumb verify on examples/demo-app (captured by scripts/render-demo.py; raw text in docs/demo/verify.txt).

Why

AI agents write code fast and check it badly. Plumbgraph answers the questions an agent should ask before it says "done", and says how sure it is:

  • Is this code used? dead-code, with reachability evidence and false-positive risks.
  • Is this dependency real? check-deps compares imports with your manifests and, optionally, PyPI / npm / crates.io, so a hallucinated package is caught.
  • Did the tests get weaker? weakening reads git diff for deleted tests, new skips and loosened assertions.
  • What breaks if I change this? impact lists transitive callers and the tests to run; map gives a token-budgeted overview.
  • One verdict. verify merges all of that with diagnostics, semgrep and ast-grep, diffs against a baseline, and distinguishes enforcing findings from incomplete checks. Dead-code findings are advisory by default; trusted gate and migration.

It indexes with tree-sitter into a local SQLite file, executes none of your code by default, and every finding carries a source and a confidence.

Quickstart

Source releases are on GitHub (no crates.io package and no prebuilt binaries yet). Build from source with Rust 1.85+:

git clone https://github.com/grloper/plumbgraph && cd plumbgraph
git checkout v1.1.0                           # latest release
cargo install --path crates/cli --locked      # installs `plumb` (and `plumbgraph`)

plumb map . --tokens 1500         # ranked overview under a hard token budget (--budget is an alias)
plumb dead-code .                 # add --lib for libraries (exports = public API)
plumb check-deps . --online       # sends package names only to the registries
plumb verify .                    # selected-check gate (exit 0 only on verdict `pass`; needs a Git base)
plumb verify . --run --online     # also run diagnostics, semgrep, ast-grep (trusted code only)
plumb init --dry-run              # preview: AGENTS.md block, MCP config, .gitignore lines
plumb init                        # write them

In a git work tree plumb init adds .plumbgraph/* and !.plumbgraph/allow.toml to <project>/.gitignore (the index is a local cache; the allow-list is meant to be committed). An existing .plumbgraph entry is left alone, a .gitignore that is not UTF-8 is never rewritten, and --no-gitignore skips this step.

--json on any command gives machine-readable output.

The verify gate (on main, CHANGELOG Unreleased)

plumb verify --json reports schema_version: 2 with one verdict. It is a gate over the checks you selected, not proof that the change is correct or that code is safe to delete.

Verdict Meaning Exit
pass Selected checks completed; no new enforcing finding 0
fail New enforcing findings (including diff-based test weakening) 1
incomplete A required check failed, timed out or could not run, or the Git base is missing or invalid 1
baseline-updated --update-baseline succeeded; it does not certify the change 1
  • Fail-closed: an incomplete required check or an invalid Git base never passes. Invalid arguments and unreadable or malformed baselines are request errors (CLI exit 2, MCP isError: true), not reports.
  • Dead code is advisory unless you opt in with --enforce-dead-code (CLI) or policy.enforce_dead_code (MCP). --fail-on low|medium|high then sets the threshold for that dead code only, and --fail-on none is rejected. Dependencies, weakening, diagnostics and rules have their own thresholds (--dependencies, --weakening, --diagnostics, --rules; default medium).
  • Baselines: --update-baseline writes plumb-baseline.json only after a complete analysis and always exits 1. For release or CI review, --trusted-baseline <full commit id> reads the baseline from that commit and uses it as the weakening diff base. It rejects short hashes and branch names, and it does not sandbox hostile repository content.
  • MCP: baseline writes need the operator flag plumb mcp --allow-baseline-update, which is separate from --allow-exec; an agent cannot grant either. An MCP tool response with isError: false is not a pass: check data.verdict == "pass".

Details and migration notes: docs/VERIFY.md.

Windows

cargo install --path crates/cli --locked works from PowerShell and installs plumb.exe into %USERPROFILE%\.cargo\bin. If plumb is not found, add that folder to your user PATH and open a new terminal (rustup does this for you; Chocolatey Rust installs do not).

Updating on Windows: a running plumb mcp keeps %USERPROFILE%\.cargo\bin\plumb.exe open, so cargo install fails with "Access is denied" while Claude, Cursor or another MCP host is running it. Stop the MCP server (close or restart the hosts) before cargo install, or install to another place with cargo install --path crates/cli --locked --root C:\tools\plumb and point the host at C:\tools\plumb\bin\plumb.exe. plumb doctor warns when it cannot overwrite its own executable.

Tested on one Windows 11 machine only (Rust 1.91.1, GNU target): install, doctor, map, dead-code, check-deps, verify, weakening, init --dry-run and plumb mcp driven by an MCP host. 10 tests fail there (they need a real python3 and a POSIX closed-pipe behavior) and also fail on unmodified main. CI is Linux only. Details in docs/VALIDATION.md.

Use with an agent (MCP)

claude mcp add plumbgraph -- plumb mcp --root /path/to/project

--root is the only tree the tools may read and defaults to the current directory. Point it at the workspace repository you are working on, not at another checkout; an MCP host started in a different directory otherwise answers about the wrong code. The server logs plumbgraph MCP server v<version> pid=<pid> ... to stderr and reports its version as serverInfo.version.

Or in .cursor/mcp.json, Claude Desktop and other mcpServers clients:

{ "mcpServers": { "plumbgraph": { "command": "plumb", "args": ["mcp", "--root", "/path/to/project"] } } }

13 tools and 3 resources; running external tools is refused unless you start the server with --allow-exec, and baseline writes unless you also pass --allow-baseline-update. Details and the clients it was tested with: docs/MCP.md.

See it work

Map and impact plumb map and plumb impact on the demo app
SCIP makes it precise plumb enrich runs scip-python; dead-code then reports the finding from SCIP

All images are renderings of real runs; regenerate them with scripts/render-demo.py.

How it works

flowchart LR
  SRC[Source files] -->|tree-sitter packs| DB[(SQLite graph<br/>edges carry source + confidence)]
  SCIP[SCIP indexes<br/>optional] -->|overlay| DB
  DB --> ENG[dead-code · map · impact]
  MAN[Manifests + registries] --> DEPS[check-deps]
  GIT[git diff] --> WK[weakening]
  TOOLS[clippy · tsc · ruff · pyright · LSP<br/>semgrep · ast-grep<br/>opt-in subprocesses] --> V
  ENG --> V[verify<br/>baseline diff]
  DEPS --> V
  WK --> V
  V --> OUT[plumb CLI / MCP server]
Loading

More in docs/ARCHITECTURE.md.

What works

Capability Languages Notes
index, find, refs Python, JavaScript, TypeScript/TSX, Rust, Go, Java, C# Tier-0 (tree-sitter, name-based). Import resolution varies by language; C# imports are not resolved to files.
dead-code same Reachability from entry points and tests; confidence 0-1; --lib, allow-list (.plumbgraph/allow.toml), plumb:keep comments; evidence and false-positive risks per finding.
check-deps Python, JS/TS, Rust Imports vs manifests; registry existence checks are opt-in (--online), and registry errors are never reported as "does not exist".
weakening Python, JS/TS, Rust, Go, Java/Kotlin, C# Heuristic, line-based git diff analysis.
map, impact all of the above PageRank-ranked map under a hard token budget; reverse reachability with tests to run.
verify, doctor, enrich, init Baseline-diffing gate; provider detection; opt-in SCIP indexers; agent config writer.
SCIP overlay rust-analyzer, scip-typescript, scip-python indexes Compiler-grade edges where the index resolved a reference, per-reference fallback (docs/SCIP.md). Exercised on toy projects with scip-python and scip-typescript.
Diagnostics Rust, TS/JS, Python, any LSP Normalised cargo/clippy, tsc, pyright, ruff, LSP publishDiagnostics (docs/DIAGNOSTICS.md).
Rule engines semgrep, ast-grep Run as subprocesses with --run; semgrep needs .semgrep.yml or --semgrep-config, ast-grep needs sgconfig.yml.

How it compares

Facts below come from each project's own README/docs on 2026-10-10 (links in docs/LANDSCAPE.md); we did not benchmark any of them, and "not documented" means we did not find it, not that it is absent. Star counts are not used.

Plumbgraph Serena CodeGraph Aider repo map Sourcegraph
Main job Verify a change (dead code, fake deps, weakened tests) plus navigation Semantic retrieval and editing for agents Pre-indexed code knowledge graph for agents Give the LLM a ranked map of the repo Code search and navigation platform
How it analyses tree-sitter; optional SCIP and LSP-diagnostics overlays Language servers (LSP) Local code graph (see its docs for details) tree-sitter definitions/references, graph ranking Search-based, plus precise navigation from SCIP indexes
Interface CLI, MCP (stdio) MCP MCP, CLI Inside aider Web UI, API; MCP server on the enterprise plan
Runs locally, no service Yes Yes Yes ("100 % local") Yes Self-hosted or single-tenant cloud
Dead-code / hallucinated-dependency / test-weakening checks Yes Not documented Not documented No (not its purpose) Not documented
Confidence and source on every result Yes Not documented Not documented n/a n/a
Precise cross-references Only with a SCIP index; name-based otherwise Yes, via LSP Not verified Not type-resolved (tree-sitter) Yes, with SCIP indexes
License Apache-2.0 GPL-3.0-or-later (app), per its README MIT Apache-2.0 Commercial (enterprise from $16K/year, pricing page)

Use them together: if you need precise navigation and editing today, an LSP-backed tool such as Serena will beat our tier-0 graph; Plumbgraph's niche is the verification side and honest provenance.

What does not work yet

  • Without a SCIP index, analysis is name-based: no types, no cross-language edges; common names give ambiguous, lower-confidence edges.
  • Dead-code precision is low on libraries in the default (app) mode and recall is unmeasured on real code. Hand review of 76 findings on chi and gson found 1 real unused function; four systematic false-positive classes were fixed (docs/EVALUATION.md). Use --lib for libraries.
  • Reflection, eval, DI containers, macros and framework magic are invisible (they lower confidence but are not understood).
  • Go, Java, C# are tier-0 only; C# was not benchmarked on a real repository.
  • SCIP: rust-analyzer's SCIP output, scip-go, scip-java and scip-dotnet were not run; scip-python and scip-typescript only on toys.
  • MCP: stdio only, tools and resources only (no prompts). Tested with the official TypeScript SDK, the MCP inspector CLI and one agent host on Windows; Claude Code, Cursor and Codex were not tested.
  • Unity: lifecycle methods and common attributes are treated as entry points, but scenes and prefabs are not read, so a component never referenced from code cannot be reported dead.
  • weakening is line-based and heuristic. Windows: one machine, manual runs, no CI (see Windows). No crates.io package or prebuilt binaries yet.

Documentation

Docs index · Architecture · Verify gate · MCP · SCIP · Diagnostics · Language packs · Validation · Strategy · Evaluation · Landscape · Changelog

Development

scripts/verify.sh            # fmt, clippy -D warnings, tests, test-integrity, cargo-deny/audit if installed
plumb verify .               # plumbgraph checks itself (allow-list with reasons in .plumbgraph/allow.toml)

See CONTRIBUTING.md, AGENTS.md and SECURITY.md. Licensed under Apache-2.0.

About

Local code intelligence and a pre-submit verification gate for AI coding agents: dead code, hallucinated dependencies, weakened tests. CLI + MCP.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages