> I Built a Terminal PR-Review Tool That Wraps Claude: Why and How
A build log: why I wrote prcheck, a terminal UI that wraps the gh and Claude CLIs to draft GitHub PR reviews with the ticket and CI context already loaded, and never posts anything without me.
I open gh and eleven pull requests are waiting for my review across five repos. I know
what to do: click on the first, wait for the diff to load, mentally track what I’ve read,
then open the ticket in a new tab to remind myself what this thing is about. I switch to the
CI tab to check the build, return, and have forgotten what I was looking at.
It doesn’t help that PRs have gotten so big compared to the pre-AI era. I used to think a hundred-line PR was substantial, and now I’m reviewing a few thousand. But that’s getting ahead of myself.
By the third PR my mind is mush and I’m rubber-stamping.
So I wrote a small terminal program that does the boring work for me and lets me skim a review before sending. This is a rough sketch of why and how.
The problem
PR review has two kinds of overhead that don’t contribute to actually reading the code.
The context-switching burden
Before I can understand a diff I need three things in front of me: the change itself, the ticket that describes what it is supposed to do, and the CI tab to make sure it even compiles. Three surfaces, three tabs, three context switches before I’ve even read any code.
The triage burden
github.com/pulls gives me a single flat list. It remembers nothing about what has changed
since I last looked. It does not organize my PRs by repo, and does not distinguish between
what I’m blocking on, what mentioned me, and what I mentioned someone else on.
Not insurmountable problems, but all together they comprise a slooow process that quietly erodes the quality of my reviews as a function of time. A tooling problem that needs a tooling solution.
What prcheck is (and isn’t)
prcheck is a terminal UI, implemented in Go, using Bubble
Tea for the framework, lipgloss for theming,
and chroma for diffs. It wraps two command-line tools that you are probably already using:
gh and an AI agent (Claude or cursor-agent).
The reason for that is my own design decision to make prcheck a thin wrapper, rather than a
platform. The program itself does not store any tokens or credentials for you. It uses
whichever credentials you’ve already configured for gh and your agent CLI. There is no
server, nothing at scale. If you can already run gh pr list and claude -p, prcheck will
work for you.
But I made one non-negotiable design decision: prcheck will not post reviews on your behalf. Everything it produces is a draft that you have to read and approve. The value proposition is in the context and the mechanics that let you arrive at your own judgment, unencumbered by the medium itself.
The review pipeline
Let’s walk through a review. Open the app, select a PR, hit Enter, select a model, and the
pipeline begins. The UI streams the progress of the pipeline to your terminal so that you’re
never waiting at a black screen, and you can hit q to kill the whole thing if you change
your mind.
- It starts by fetching the diff, using
gh pr diff. - Then it checks the CI, using
gh pr viewso that a red build won’t surprise you when you switch to that tab later. - Then it fetches the linked ticket, using your agent’s Atlassian MCP server. This is where I think Claude does the most interesting work, because the review has context about what the PR was supposed to do, rather than just what it did. Again, no Jira token is stored in prcheck itself; it proxies through your agent.
- Your agent (
claude -porcursor-agent) runs and is fed the diff, CI failures, and ticket context. - Finally, a pending review is posted with a summary, aspect checklist, and inline comments anchored to the diff lines.
Then you go open the PR in your browser to edit and send the review. While prcheck is
running, hitting q will kill it cleanly. This is the whole point. These three surfaces that
used to take three tabs to organize are collapsed into one keystroke and a TUI, and what
comes out the other end is a review draft that you can skim before sending.
The things that made it worthwhile
A few of these are the kinds of “I’m going to throw this away” features that ended up being the reason I kept working on it. I have them on my second monitor at all times.
The three queues — Mine, Review-requested, and Mentioned — are grouped by repo, sorted by newest, and span every repo I can see. A disk cache paints the last session’s PRs on the TUI as a placeholder while new data loads, so it’s fast. The “new since last viewed” indicators let me see at a glance what’s changed.
The model picker per review lets me choose a model to use for each PR. It’s attached to
the Enter key before the pipeline starts, so I can see which particular Claude model did my
review (I name them claude-opus-4-8, etc). The default picks based on the same chain the
claude CLI would: ANTHROPIC_MODEL, then repo, then user. A minor convenience, but one I
value: knowing which model wrote this particular review.
Bookmarks and batch review. Bookmark a few interesting PRs (b), and hit B to run the
pipeline on all of them in succession. This is my morning routine: I bookmark everything in
Review, hit batch, go make coffee, and come back to a bunch of drafted reviews that I can
skim.
Quick-approve (a). For particularly quick PRs (e.g. config updates), I don’t need a
review at all. An LGTM is sufficient.
The security model (said plainly)
It’s my responsibility to be as precise as possible about what leaves my machine, since “AI code review tool” is a phrase that makes many people nervous.
- What gets sent to the model: the diff, the CI failure messages, and the ticket text. Nothing beyond that, no secrets, unless you explicitly add them to the review.
- Authentication: your credentials are those already used to authenticate
ghand your agent CLI. prcheck trusts nothing else on your machine. - Output: always a pending review. Nothing reaches your teammates until you explicitly approve a draft.
If you’re already comfortable exposing claude or cursor-agent to your machine, prcheck
doesn’t give you any additional attack surface beyond what you’ve already permitted. It’s
just a compositional convenience for copy-paste operations.
Architecture, briefly
For those who want to skim the implementation, most of it is boring. The package is split into dirs that express a dumb idea:
internal/tui— Bubble Tea model/update/view code, plus overlay components (agent picker, model picker, stats).internal/pipeline— the review steps as an event stream. This is what makes the TUI possible.internal/claude— agent abstraction (claude/cursor), model picking,--modelflag parsing, prompting, Jira querying.internal/github—ghquery/view/diff/checks/review code.internal/cache— snapshots, seen markers, bookmarks, history, and notifications.
Releases are built with goreleaser on push to a tag, and binaries are available for darwin, linux, and windows. No install needed: you just download the one for your OS and run it.
The one feature I’m proudest of is the event-stream review pipeline. Because each step emits
an event rather than blocking, the TUI is able to update the status and render progress. As a
result, it’s intuitive to cancel a long-running operation (q) and exit cleanly. All in all,
it feels less like a script and more like an actual app.
Takeaways
Build on foundations. I’m not a Go developer, but I could write this program in it
because it’s mostly gh + agent CLI + frontend. The ability to use existing tools I already
trusted was the reason this got built in the first place.
Automate the labor, not the judgment. Pending-only reviews preserve the critical separation between the judgment of the reviewer and the automation that gets their message across.
Give the reviewer the ticket. Having the Jira context alongside the diff is what allows the model to be accurate and precise.
Stream your pipelines. You get live status and progress for free, and it’s a nice UX win to cancel long operations with a keystroke.
This is the repo: github.com/KamilSupera/github-pullrequests-checkecker. Please try it out on your own queue and tell me what breaks.