reviewproof

A review ledger per pull request that refuses unchecked review claims.

It refuses a finding without a source, a withdrawal without evidence, a verdict before the gates have finished and every changed file has been read, and a post without a named person. It does not review code and calls no model: an agent or a person does the review, reviewproof does the bookkeeping. Built for AI-assisted review over several rounds on GitHub and GitLab; it works for people too.

In one review round reviewproof starts a ledger for the pull request and its head sha, counts the files the agent reads, runs and logs the gates, records findings with a severity, a source and file:line@sha, refuses a verdict until the gates are finished, every changed file is read and carried findings are settled, and writes a draft; a person reads the draft and runs post, which comments on the pull request and reads the comment back, and every verdict and post is one commit in the ledger git repo.
Every verdict and every post is one commit in the ledger, a git repository of its own (~/.reviewproof), so a review never touches the reviewed repository. No token is written to disk. Open the diagram

What it refuses

Each rule closes one way an AI review goes wrong: a finding nobody can trace, a file nobody opened, a verdict while the tests still run, a round-1 finding quietly dropped in round 2, a note posted before a person looked at it.

A finding without a source

Each finding needs a severity, a source (a rule, a design, legacy code or other, with a reference) and a place file:line, checked at the round's head and stored as file:line@sha. A missing field, a file that does not exist at the head or a line past its end is refused.

A withdrawal without new evidence

In the next round every open finding needs a status: verified, reopened at a place in the new head, or withdrawn. Withdrawing needs evidence holding a file:line@sha or a URL; “the author disagrees” is not evidence.

A verdict before the work is done

No verdict while a gate is unfinished, a changed file is unread or a carried finding has no status. Reads are measured: in Claude Code a hook on the Read tool records each file and line range the agent opened. pass is also refused while a blocking finding is open or a gate failed or was skipped, and a summary with hedge words (probably, seems, might) is refused.

A post without a named person

The person reads the draft and runs reviewproof post --approved-by <name> in their own terminal. It refuses to run inside Claude Code, and the plugin's hook stops the agent from running it. The posted comment is read back and compared with the draft.

One round

Run inside a checkout at the head of the pull request. The agent (or you) does the review; reviewproof keeps the ledger.

$ reviewproof start o/r#12                  # round 1 (a URL or gitlab:g/r!7 also work)
$ reviewproof diff                          # prints the round diff, counts the files read
$ reviewproof gate run tests -- npm test    # no shell; the log is kept, a rerun is attempt 2
$ reviewproof gate skip e2e --reason "needs a staging server"
$ reviewproof add findings.json             # sourced findings, linted
$ reviewproof status                        # what still blocks a verdict
$ reviewproof verdict not-yet --summary "Two findings open; tests pass."
$ reviewproof draft                         # writes the note and prints it

findings.json

Severity: blocking, major, minor. Source kind: rule, design, legacy, other.

[
  {
    "severity": "major",
    "source": { "kind": "rule", "ref": "CONTRIBUTING.md#error-handling" },
    "at": "src/api/client.ts:88",
    "title": "Network errors are swallowed",
    "body": "The catch block returns null, which callers read as 'not found'."
  }
]

Round 2, after the author pushes

Run start again: every finding still open needs a status before the next verdict.

$ reviewproof start o/r#12
$ reviewproof mark F1-1 verified
$ reviewproof mark F1-2 reopened --at src/api/client.ts:91
$ reviewproof mark F1-3 withdrawn --evidence "src/api/client.ts:40@3f9c2ab handles it"

Then the person posts

The agent stops at the draft. You read it and post from your own terminal, not from the agent. post sends the draft as a comment, reads it back, compares it with the draft and stores the comment's id and URL.

$ reviewproof post --approved-by <name>

Other commands: read <file> [--lines a-b] counts a file read elsewhere, skip <file> --reason R leaves a changed file out of coverage, export --sarif [--out FILE] writes the latest round as SARIF 2.1.0 for code-scanning tools.

Parallel reviews

The ledger is locked per pull request while a command changes it, so commands run at the same time are safe: none loses another's change, and a gate's log is never overwritten.

Gates in the background

Start each gate as its own background command right after start, and review while they run. status shows a gate still running as missing.

Helpers per file group

Split a large diff among helper agents, one group of files each. Their Reads count, each recorded with the agent's id. The main session reads the code behind every major or blocking candidate itself before add.

One agent per pull request

One checkout (a git worktree) and one agent per pull request. Each pull request has its own ledger, so they never wait for each other.

Compared with

Other tools cover parts of this. A survey in November 2026 found none that refuses the claims above.

AI reviewers Copilot code review, CodeRabbit, Cursor Bugbot, Claude Code Review, Greptile. They review the code and carry findings across rounds, but they can resolve or drop a finding on their own.
“Viewed” marks Reviewable, Gerrit, GitHub “Viewed”. Files are marked reviewed, but a person declares it; nothing measures what was read.
reviewproof Finds no bugs and calls no model, so it works with any agent, or a person. It adds the refusals: no finding without a source, no withdrawal without evidence, no verdict before the gates and reads are done, measured read coverage, and the posted note read back.

Get started

Works on Windows, macOS and Linux.

Prerequisites

  • Node 22.18 or newer, for the CLI (Claude Code itself does not need Node).
  • git
  • GitHub: the gh CLI, logged in (gh auth login).
  • GitLab: a GITLAB_TOKEN environment variable (a token with api scope). reviewproof calls the GitLab API itself; glab is not needed.

CLI

$ npm i -g reviewproof

Claude Code plugin

Adds the Read and shell hooks and the review-round skill, which drives one round and stops at the draft.

/plugin marketplace add vannt-dev/reviewproof
/plugin install reviewproof@reviewproof

Limits