Mixed-language dead-code scanning

One dead-code scanner for mixed-language repos.

graveyard scans Python, JS/TS, Go, and Rust in one pass, ranks findings with git-aware confidence, and gives teams a CI-safe baseline diff instead of four disconnected tools and a cleanup freeze.

Python + JS/TS + Go + Rust git-aware confidence baseline diff --ci JSON / CSV / SARIF crates.io / PyPI / npm / Homebrew

Demo

See the workflow in one short loop.

The demo shows the two commands that matter most for adoption: a ranked scan of the current repo state, then a baseline diff that isolates only newly introduced dead code for CI.

Animated terminal demo of graveyard scan followed by baseline diff in CI mode

Why it exists

Stop stitching together dead-code tools per language.

AI coding agents make stale code faster to create than to notice. Most dead-code tooling still assumes one language at a time, which leaves mixed-language repos juggling separate scanners, separate ignore rules, and separate CI policies. graveyard is the single workflow for teams that want one report they can trust.

One pass across the repo

Manifest-aware walking covers Python, JavaScript, TypeScript, Go, and Rust without splitting work across multiple linters.

One ranking model

Findings are scored with deadness age, reference count, scope, and recent churn so fresh work and public APIs do not drown out the queue.

One CI adoption path

Save a baseline once, then fail the build only when a pull request introduces new dead code instead of inheriting the whole backlog.

One output surface

Use the table locally, JSON or CSV in automation, and SARIF when you want findings surfaced inside GitHub code scanning.

Comparison

The wedge is mixed-language repos, not every repo.

The fastest way to make a new developer tool trustworthy is to be candid about when something else is a better fit. graveyard is not trying to replace every dead-code or dependency tool. It is the right choice when the repository crosses language boundaries and the team wants one dead-code workflow instead of several.

Use vulture

When the problem is Python-only dead code, a focused single-language tool can be the cleanest answer.

Use knip

When the repo is centered on JavaScript or TypeScript dependency and export cleanup, knip is a strong fit.

Use cargo-machete

When you need unused Rust dependency pruning, use the tool built for that job. graveyard works at the source-code layer.

Use graveyard

When the repo mixes Python, JS/TS, Go, and Rust and the team wants one scan, one ranking model, and one CI ratchet.

What it looks like

From local scan output to CI ratchet in two commands.

The install surface matters, but the proof is the workflow: scan once, save a baseline, then only fail the build when a pull request adds new dead code. The examples below show the parts teams actually wire into day-to-day review and CI.

Local scan

$ graveyard scan --format table --min-confidence 0.80

0.94  ExportedUnused  src/lib.rs:42         legacy::old_api
0.88  Dead            services/foo.py:17    cleanup_task

Found 2 dead symbol(s)

CI ratchet

$ graveyard baseline diff --baseline .graveyard-baseline.json --ci

baseline findings: 18
new findings: 1
exit code: 1

Code scanning handoff

$ graveyard scan --format sarif --output graveyard.sarif
$ upload-sarif graveyard.sarif

3 findings surfaced in GitHub code scanning

Install

Pick the package manager your team already trusts.

The command is always graveyard, even when the wrapper package name changes across ecosystems. That keeps local usage, CI snippets, and shell completions aligned.

pip / pipx

pip install graveyard
pipx install graveyard
graveyard --version

npm

npm install -g graveyard-cli
graveyard --version

cargo

cargo install graveyard
graveyard --version

Homebrew

brew tap Meru143/homebrew-tap
brew install graveyard
graveyard --version

CI adoption

Start with a baseline, then only fail on new dead code.

This is the wedge that makes a scanner feel realistic in an existing codebase. You do not have to fix an old backlog in one merge. Save a baseline once, then let pull requests earn trust by keeping the number from growing.

graveyard baseline save --output .graveyard-baseline.json
graveyard baseline diff --baseline .graveyard-baseline.json --ci
graveyard scan --format sarif --output graveyard.sarif
graveyard scan --ci --min-confidence 0.80