The CI for PR feedback. Did every comment get an answer?
review-replay verifies whether the concerns raised in a GitHub PR review have actually been addressed — by code changes, by explicit acknowledgments in the thread, or by the reviewer marking it resolved. It is not a review generator (that's CodeRabbit, Copilot Review). It is not a fix implementer (that's Claude Code, Cursor agent). It is the verifier that closes the loop.
$ review-replay owner/repo#42
owner/repo#42 · head a7c1e3d
3 addressed · 1 partial · 1 pending · 1 needs-discussion
# │ kind │ author │ status │ src │ conf │ evidence │ comment │ draft reply
──────┼────────┼─────────────┼────────────────┼───────┼──────┼──────────┼───────────────────────────────┼────────────────────────
1 │ inline │ alice │ addressed │ rule │ 0.95 │ - │ extract this into a helper │ -
2 │ inline │ alice │ pending │ rule │ 0.95 │ - │ this should be debounced │ -
3 │ inline │ alice │ addressed │ llm │ 0.92 │ e4f5g6h │ rename `tmp` to descriptive │ Renamed to pendingWriteBuffer.
...| Role | Tools | What it does |
|---|---|---|
| Generation | CodeRabbit, Copilot Review, Greptile | Generates review feedback |
| Implementation | Claude Code skills, Cursor agent, Ellipsis | Implements review fixes |
| Verification | review-replay | Verifies the fixes actually resolve the comments |
As more code gets written by agents that claim "I addressed it", you need an independent check. review-replay reads the PR conversation + current code state, classifies each comment, and gates the merge if anything is still pending.
go install github.com/alejandroSuch/review-replay/cmd/review-replay@latestBinary lands in $(go env GOPATH)/bin. Add that to your PATH if it isn't already.
@latest resolves to the most recent semver tag. If you want to follow the development branch (no tag is required), or you just pushed a fix and want it immediately, install from main and bypass the Go module proxy cache:
GOPROXY=direct go install github.com/alejandroSuch/review-replay/cmd/review-replay@mainOther useful pins:
go install github.com/alejandroSuch/review-replay/cmd/review-replay@v0.1.0 # tag
go install github.com/alejandroSuch/review-replay/cmd/review-replay@1e079c3 # commitwhich review-replay
go version -m "$(which review-replay)" | grep vcs.revisionThe revision should match the commit you intended to install.
git clone https://github.com/alejandroSuch/review-replay
cd review-replay
go build -o review-replay ./cmd/review-replayreview-replay reads from GITHUB_TOKEN or GH_TOKEN. How you get one depends on where you're running it.
The simplest path is to reuse the token from your gh CLI session:
gh auth login # one-time, browser flow
export GITHUB_TOKEN="$(gh auth token)"That's enough for read-only runs (the default and --check). The default gh auth scopes already include what review-replay needs to read PR conversations.
For scripts, CI outside Actions, or shared environments, generate a fine-grained PAT at https://github.com/settings/personal-access-tokens with these repository permissions:
| Permission | Level | Needed for |
|---|---|---|
| Contents | Read | Commit metadata, file content at HEAD |
| Pull requests | Read | Reviews, threads, issue comments |
| Pull requests | Read and write | Only if you plan to use --post to reply to comments |
| Metadata | Read | (auto) |
Then:
export GITHUB_TOKEN="github_pat_..."Classic PATs (ghp_...) also work; the relevant scope is repo (or public_repo for public repos only).
You do not need to create a token. The runner provides one automatically:
- uses: alejandroSuch/review-replay/action@main
with:
api-key: ${{ secrets.OPENROUTER_API_KEY }}
# github-token defaults to ${{ github.token }}, no setup neededThe auto-provided token has read access to the PR by default. Make sure the job has:
permissions:
pull-requests: read
contents: read
# plus pull-requests: write if you ever enable --postreview-replay <pr> [flags]<pr> accepts a GitHub URL or owner/repo#N.
| Flag | Behavior |
|---|---|
| (default) | Classify and print a report |
--check |
Exit 1 if any comment is classified pending. Use as a required CI check. |
--post |
Post draft replies to inline review threads. Default is interactive: prompts y/N/q per comment. Add --yes to skip prompts, --dry-run to preview without hitting the GitHub API. |
--no-llm |
Skip classification, only show deterministic evidence packets. |
--ping-llm |
Probe LLM provider config and exit. |
--json |
Emit full JSON output instead of the table. |
| Provider | Default model | Notes |
|---|---|---|
openrouter (default) |
openai/gpt-4o-mini |
OpenAI-compatible wire format, broadest model catalog. |
openai |
gpt-4o-mini |
Official OpenAI endpoint. |
anthropic |
claude-haiku-4-5 |
Native Messages API (not OpenAI-compatible). |
gemini |
gemini-2.5-flash |
Native generateContent API. |
For any OpenAI-compatible endpoint (Together, Groq, Fireworks, vLLM, LM Studio, Ollama via /v1, etc.), use --provider openai --base-url <your-endpoint>.
| Variable | Purpose |
|---|---|
GITHUB_TOKEN / GH_TOKEN |
GitHub auth (required) |
RR_PROVIDER |
Default provider (overridden by --provider) |
RR_MODEL |
Default model (overridden by --model) |
RR_API_KEY |
Generic LLM API key |
RR_BASE_URL |
Custom base URL for OpenAI-compatible endpoints |
OPENROUTER_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY |
Provider-specific fallbacks |
Block merge only on a specific reviewer (e.g., Copilot, your tech lead):
review-replay owner/repo#42 --reviewer copilot --checkCase-insensitive substring match on author login.
- Fetch the PR via the GitHub GraphQL + REST APIs: review threads (with
isResolvedandresolvedBy), review summaries, issue comments, commits. - Build deterministic evidence packets per comment:
- For inline comments: did the region change at HEAD? Which later commits touched the file? Are there inline replies? Is the thread resolved by the opener?
- For review summaries and issue comments: which commits and replies came after? Filter chitchat (
LGTM,thanks, emoji-only) and PR-author self-reviews. Dedupe near-identical bodies.
- Short-circuit rules (no LLM call):
- Thread resolved by the reviewer who opened it →
addressed. - No region change, no replies, no later commits →
pending.
- Thread resolved by the reviewer who opened it →
- Classify the rest with your chosen LLM provider.
- Report: per-comment status + confidence + evidence commit + draft reply, plus a summary line.
- uses: alejandroSuch/review-replay/action@main
with:
mode: check
api-key: ${{ secrets.OPENROUTER_API_KEY }}Make the job a required check to block merge on pending comments.
See action/examples/copilot-followup.yml for a workflow that only blocks on Copilot's reviews.
The repo doubles as a single-plugin Claude Code marketplace. Inside Claude Code:
/plugin marketplace add alejandroSuch/review-replay
/plugin install review-replay@review-replay
The skill triggers when the user says things like "did I address the reviews?" or "re-check the PR before pinging the reviewer". See integrations/claude-code/ for manual install + prerequisites.
Drop-in rules / skills for Cursor, Codex CLI, Windsurf, Continue.dev and Aider live under integrations/. Each subfolder has the ready-to-copy file plus a per-tool README.
Capture fixtures from real PRs, label by hand, run the classifier, compare runs across model swaps.
# install the eval binary
go install github.com/alejandroSuch/review-replay/cmd/review-replay-eval@latest
# capture fixtures (preserves any existing labels)
review-replay-eval capture owner/repo#42
# label the JSON files by hand: set label.status to addressed | partial | pending | needs-discussion
# run the classifier and save the run
review-replay-eval run --save baseline
# swap model and compare
RR_MODEL=anthropic/claude-haiku-4-5 review-replay-eval run --save haiku
review-replay-eval diff baseline haikureview-replay processes:
- Inline review threads (comments anchored to a line of code).
- Review summary bodies (the text of an Approve / Request changes review).
- Structured issue comments (general PR comments with substantive content; chitchat is filtered).
Out of scope: GitHub Discussions, commit comments, file-level non-line comments, GitLab/Bitbucket.
MIT.