Skip to content
judge
BUSL-1.1View on GitHub
Cargo subcommand · Rust · Source-available

What the compiler
does not tell you

judge reads the current source tree, the workspace structure, the public APIs and the dependency graph. It never repeats what the compiler or Clippy already report.

0.7.0
crates.io
102
evidence findings in the run
0 / 1 / 2
exit codes
lightweight-pdf (8 crates)
$ cargo judge
[WARN] Judge summary
  Analysis context: boundary rules: 0 not checked (no judge.toml)

  Evidence: 102   Advisory: 58

  Top issue rules:
      84x  duplicate-code
      35x  complexity-inflation
      14x  maintainability-index
       9x  swallowed-result
       5x  silent-default
cargo-judge 0.7.0 · run from 2026-09-16exit code 0
Rules
  • duplicate-code
  • complexity-inflation
  • maintainability-index
  • swallowed-result
  • silent-default
  • panic-in-lib
  • integer-cast-risk
  • suppression-debt
  • unused-pub-workspace
  • unused-feature-flag
  • heavy-dependency
  • workspace-dep-drift
  • undocumented-public-item
  • semver-hazard
102
evidence findings

Measured on the lightweight-pdf workspace with 8 crates and 765 analysed functions. Plus 58 heuristics, reported separately.

41
clone families

cargo judge dupes in mild mode: 84 members across 41 families, each with file, line range and function names. Test code counts only with --include-tests.

97.8 (A)
health score in the same run

A configurable trend index, not an objective quality verdict. The delta against a baseline is the message, not the absolute number.

01 — Overview

Structural findings that only become visible across a whole workspace.

judge is built as a Cargo subcommand and runs both as cargo judge and as cargo-judge. It analyses the checked-out state – no commit history, no authorship, no telemetry. Results apply equally to human-written, generated and agent-refactored code.

github.com/casoon/judge →
  1. 01Deterministic — same source tree, same findings; no network access unless you ask for it
  2. 02Evidence, not guesswork — every finding carries an evidence class, a location and a reason
  3. 03Heuristics kept apart — advisory findings affect neither verdict nor score
  4. 04Not a replacement — no linter, no formatter, no security scanner
02 — Categories

Five directions judge looks in.

Each category is its own subcommand and part of the combined run – except the ones that are explicitly opt-in.

  1. 01

    Duplication

    dupes groups repeated token spans into clone families, in four modes from strict to semantic. Intentional duplicates can be justified with // judge-dupe-ignore: <reason> before the function – without a reason the directive does not apply.

  2. 02

    Complexity and maintainability

    complexity and health report cyclomatic complexity per function and a maintainability index per file. Production and test code stay separate.

  3. 03

    Dead code

    dead-code belongs to the Deep Tier and reports unused-pub-workspace: pub items with no reference from another workspace crate and no reachability from a recognised entry point. That means “no use found in the examined view”, not “proven dead”.

  4. 04

    Dependency hygiene

    deps checks dependency kinds, feature flags and local name collisions. crates.io lookups and cross-referencing an already generated cargo audit --json report are opt-in – judge never runs cargo-audit itself.

  5. 05

    API surface and boundaries

    api shows undocumented-public-item and semver-hazard. boundaries checks crate boundaries declared in a judge.toml and finds cycles; without a config it does nothing.

03 — Findings

Three outputs from a real run.

cargo judge dupesDuplication
$ cargo judge dupes
mode: mild
min tokens: 20
clone families: 41
refactoring summary: 41 clone families, 84 members (repeated tokens, not an automatic merge recommendation)
  #1  3 members × 22 tokens = 66 repeated tokens across 2 files  collect_anchors_in_node, collect_headings_in_node, collect_anchor_pages_in_node
  #2  3 members × 20 tokens = 60 repeated tokens across 1 files  layout_rich_text, layout_rich_text, layout_text_fixed_overflow
  #3  2 members × 66 tokens = 132 repeated tokens across 1 files  layout_row_cells, render_cells_starting_at
  #4  2 members × 63 tokens = 126 repeated tokens across 1 files  hard_break_word, hard_break_styled_word
  #5  2 members × 59 tokens = 118 repeated tokens across 1 files  natural_row_heights, apply_rowspan_deficits
cargo judge depsDependencies
$ cargo judge deps
dependency findings: 5
  [unused-feature-flag] lightweight-pdf  serde
  [heavy-dependency] lightweight-pdf-cli  lightweight-pdf
  [workspace-dep-drift] ?  png
  [workspace-dep-drift] ?  schemars
  [workspace-dep-drift] ?  serde

feature-only candidates (no code usage found; see unused-feature-flag findings above for detail): serde
cargo judge health --scoreHealth
$ cargo judge health --score
functions analyzed: 765

slop signals: 14 (52 advisory)
  swallowed-result: 9
  suppression-debt: 2
  complexity-inflation: 35
  maintainability-index: 14
  abstraction-inflation: 1
  integer-cast-risk: 2
  panic-in-lib: 3

health score: 97.8 (A) — 16026 authored LOC, 0 fail, 12 warn, 57 advisory (not scored)
The same run, in numbers
8
crates in the workspace
765
analysed functions
16,026
authored lines of code
0
findings at severity fail
04 — Get started

Install, run, freeze.

  1. 1Install

    From crates.io

    Requires Rust 1.95 or newer (edition 2024). Alternatively build from the repository or use cargo install --path ..

    cargo install cargo-judge
  2. 2Run

    Combined report

    The default view groups by rule and shows one representative location per group. --details lists every finding, --format json writes the full artifact.

    cargo judge
  3. 3Freeze

    Set a baseline

    The baseline is a file, not a Git revision. From then on, only what is new against that state counts.

    cargo judge --save-baseline
05 — Reproducibility

Why two runs produce the same thing.

No network unless asked

Without the opt-in flags of deps, judge makes no network calls. The result therefore does not depend on when you ran it.

No history

compare compares the current state with a saved artifact file and works without Git.

Versioned artifacts

Every JSON file starts with a header holding the working directory, output path, timestamp, a command description and an assessment.

A score only under the same formula

A trend is shown only when the baseline was produced with the same score formula version and the same crate profiles. Anything else is reported as not comparable instead of a false delta.

06 — CI

One job, two artifacts.

.github/workflows/judge.ymlExample
# .github/workflows/judge.yml
name: judge
on: [pull_request]

jobs:
  judge:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - run: cargo install cargo-judge
      # fails as soon as anything new appears against the baseline
      - run: cargo judge --baseline .judge/baseline.json
      # SARIF 2.1.0 goes to stdout, e.g. for code scanning
      - run: cargo judge --format sarif > judge.sarif
07 — Scope

What judge deliberately leaves alone.

CriterionjudgeClippycargo-audit
Field of viewworkspace, across filesfile and expressiondependency graph
Duplication across cratesyesnono
Known vulnerabilitiesonly against an existing reportnoyes, its own source
Baseline with a verdictyesnono
Needs a buildonly in the Deep Tieryesno

judge replaces neither tool. The rule in the repository: anything the compiler or Clippy already tells you, judge does not repeat.

08 — Two tiers

Fast Tier and Deep Tier.

  1. Default

    Fast Tier

    Analysis via syn, cargo metadata and the manifests. No build of the project needed, so it is fast enough for every pull request.

    syncargo metadatano build
  2. Opt-in

    Deep Tier

    Loads the workspace into rust-analyzer to work with real reference data instead of syntax-level guesses. Building the ra_ap_* crates takes noticeably longer.

    --features deepdead-codeexplain --why-live
  3. Handoff

    Artifacts

    Versioned JSON on every report command, SARIF 2.1.0 for code scanning, Markdown for pull-request descriptions. A separate MCP adapter passes the JSON output on to assistants.

    jsonsarifmarkdownjudge-mcp
09 — Baseline

The verdict CI listens to.

Terminalrun from 2026-09-16
$ cargo judge --save-baseline
$ cargo judge compare .judge/baseline.json
verdict: pass
unchanged: 160
resolved: 0
introduced: 0
introduced advisory (heuristic — no verdict effect): 0
severity changed: 0
10 — Limits

What the analysis does not do.

The findings are evidence, not verdicts. Four limits judge names itself.

Dead code is not proven dead

unused-pub-workspace means “no use found in the examined view”. The workspace is loaded without a proc-macro server and without running build.rs, so generated code is invisible.

The score is a trend index

Not an objective quality ranking. With no basis to compute it, judge reports the score as unavailable and exits with code 2 – rather than inventing a perfect number.

Early in the project

The Fast Tier is implemented, the Deep Tier only as a first slice. Module-level boundaries and several planned maintainability and dependency-hygiene rules are still missing.

Duplication needs judgement

A clone family is an observation of repeated tokens, not an automatic recommendation to merge. That is why refactor never invents a patch.

LicenceSource-available under the Business Source License 1.1, not OSI open source. Viewing, modifying and running it in production is allowed – commercially too. What is excluded is offering cargo-judge, or a modified version, to third parties as a hosted service or a competing product. Each version converts to Apache 2.0 four years after its release.Licence text in the repository →
11 — A good fit for
  • Rust workspaces with several crates
  • Reviews after large refactorings
  • Pull-request gates
  • Handovers between teams
  • Coding agents as readers
12 — FAQ

Frequently asked questions.

Does judge replace Clippy?

No. The rule in the repository: anything the compiler or Clippy already tells you, judge does not repeat. It covers structural and cross-file concerns that only become visible across a whole workspace.

Which exit codes are there?

0 for a clean run, 1 when findings are reported, 2 for an error or an incomplete analysis. In the run against lightweight-pdf on 2026-09-16 the exit code was 0 even though 102 evidence findings were reported: none of them had severity fail.

How do I keep CI from failing on old debt?

With a baseline. cargo judge --save-baseline writes the current state to .judge/baseline.json, after which cargo judge --baseline only judges what is new against that state. The baseline is a file and needs no Git.

Does judge read my commit history?

No. The analysis looks at the checked-out source tree, the workspace structure, the public APIs and the dependency graph. Authorship, commit history, telemetry and code provenance are explicitly out of scope, and compare compares against an artifact file rather than a revision.

What is the difference between evidence and advisory?

Evidence findings are tied to verifiable proof and affect verdict and score. Advisory findings are reproducible interpretations, that is heuristics: they are reported separately and affect neither verdict nor score.

Can a coding agent use the output?

Yes, that is part of the design. Every report command can write versioned JSON, and the judge-mcp directory holds a thin stdio adapter that shells out to an already-built cargo-judge binary and returns its JSON as MCP tool calls. It computes nothing itself and is not a requirement for judge.

Run it once, then set a baseline.

The first run needs no build of the project and no configuration.