The moment I decided to build PRCheck was not a dramatic epiphany. It was a Tuesday afternoon, and I was on my fourth review cycle of a PR that should have been merged two days earlier.
I was a senior engineer at a mid-size SaaS company at the time, part of a backend team of about eight people. The PR in question was a modest one: a refactor of our data export pipeline to add support for a new output format. The code was good. The problem was that each review cycle surfaced a different category of issue: first a style comment, then a missing edge case, then a concern about error handling, then a question about whether the new code was consistent with how we had handled similar things elsewhere.
None of those findings were wrong. All of them should have been caught. But they came one by one, across four separate back-and-forth cycles, over the course of nearly three days. And as I sat there on Tuesday afternoon, writing my response to the latest round of comments, I had a clear thought: almost all of these things could have been automated. We were using human review time for work that did not require human judgment. And because reviewer attention was finite, the things that did require human judgment got less of it.
The bottleneck nobody names
I started paying closer attention to this after that Tuesday. I kept a rough log for about two months: how many PRs were open at any given time on our team, what the review cycle counts looked like, and what categories of comments were being left. The pattern was consistent. Roughly 60% of first-round review comments were about things that could be expressed as rules: style conventions we had documented, error handling patterns we had agreed on, test coverage requirements we technically had but never enforced, security practices that were in the team wiki but not in anyone's memory during review.
Thirty percent were genuine design and correctness feedback that required a person. Ten percent were somewhere in between, questions and suggestions that were useful but not strictly necessary for the code to be correct and safe.
What this told me was that we were spending human reviewer attention, the scarcest resource in the whole pipeline, on the most automatable 60% of the work. And because each review cycle had a latency of hours to a day, the PR cycle time was inflated by waiting rather than by actual work.
Why existing tools were not the answer
This was not a new observation. Linters existed. GitHub had its own basic check infrastructure. Several newer tools promised "AI code review" and I had tried them. The linters handled formatting and obvious syntax issues but had no way to encode team-specific conventions or API usage patterns. The AI review tools were impressive in demos and disappointing in practice: they left lots of comments, but the ratio of signal to noise was low enough that developers on my team started reflexively dismissing the findings.
The deeper problem I kept running into was that most tools operate on the diff in isolation. A changed function looks fine in isolation, but might violate a contract established by the rest of the codebase that the diff does not show. A new API call looks correct syntactically but may be calling a function whose documented preconditions are not met by the caller. These categories of issues require understanding the changed code in its context, and that context is not in the diff.
I left that company in late 2023, and the first thing I built was a prototype that parsed the full files modified by a PR, not just the diff, and ran structured checks against the surrounding call context. The prototype was rough. The precision was already noticeably better than the diff-only tools I had used professionally.
What we set out to build
Daniel joined me early in 2024. We spent the first few months agreeing on what the core design constraint should be: precision over recall. It is better to produce five accurate findings than twenty findings where half are false positives. A tool with a false-positive problem trains developers to ignore it, which is worse than no tool at all.
That constraint shaped everything. We chose to build structured rule checks, with defined pass/fail conditions, rather than relying primarily on open-ended language model generation. We chose to extract call graph context before analysis rather than analyzing only the diff. We chose to support suppression annotations with clear documentation, so that legitimate exceptions to rules could be expressed without disabling the rule entirely.
We are not claiming we got everything right in the first version. We have shipped rules that turned out to have edge cases we did not anticipate, and we have removed rules that were producing too much noise despite our testing. The process of maintaining low false-positive rates across real codebases is ongoing work, not a one-time design decision.
What changed the moment we started using it ourselves
We use PRCheck on PRCheck's own repository. This is not a marketing claim; it is just how we work. The thing that changed for us immediately was that the first round of human review became substantially more focused. The reviewer opened a PR knowing that style, test coverage, and a set of correctness and security patterns had already been checked. They did not have to mentally re-run those checks while also thinking about design.
The quality of the human review improved. Not because the reviewers got better at reviewing, but because they were no longer splitting attention between mechanical verification and genuine judgment. The mechanical layer was already handled.
That is the experience we are building toward for the teams using PRCheck. Not replacing code review, which requires judgment that tools do not have. Removing from code review the parts that should never have required human judgment in the first place, so that the human judgment that remains goes toward the work that actually needs it.
The Tuesday afternoon that started this is still the clearest picture I have of the problem. A good engineer, doing careful review work, spending three days on a PR that should have taken one. Most of that extra time was avoidable. That seemed like something worth fixing.