writing
Sharing a Small Tool I Use Myself (Self-Made)
ReviewGate is an open-source MIT-licensed pre-merge filtering tool that screens for high-risk issues from perspectives like security, performance, logic, and AI Smell, categorizing them as block or warn. It prefers to fail rather than give a false green light. It supports --fix, CI integration, and false-positive sharing, and is read-only by default. It's recommended to observe first, then gradually enable.
Using tools like Claude Code and Cursor to write code, I've recently had a feeling: work gets done faster, but I'm not confident.
It can spit out hundreds of lines at once, and I glance over them—they seem fine. But if I really try to review line by line, I start to drift by the end—my attention scatters, I can't focus on the parts I should, and I end up merging with a "looks fine" attitude. A couple of days later, the issues that pop up in production are often the few lines I didn't look at carefully.
The problem isn't that AI writes poorly; it's that it ramps up the volume of code but dumps the exhausting review work back on me. My eyes alone can't keep up with its speed.
So I wrote ReviewGate, which does one thing: it goes through the code for me before merging.
I made it clear from the start—it's not here to review code for me; I don't trust any tool to make the final call for me. Its job is filtering: it pulls out high-risk issues and puts them in front of me, while suppressing low-value noise. I want to save my eyes, not have another chatterbox.
Each time, it looks from several angles simultaneously—security, performance, logic, and other usual ones (see image below). What I really care about is the category I specifically added—AI Smell, which targets the mistakes AI tends to make: calling non-existent APIs, making assumptions without checking, and copying old code without updating it. These are things regular linters can't catch, but they're exactly where AI most often trips up.
After reviewing, it doesn't just say "there's a problem"—it categorizes:
- High-risk issues are marked as
block, which stops the merge; - Less certain ones are collapsed, and I can expand them if I want.
This way, when I open the results, the first thing I see is the most critical item.
One design I'm most satisfied with: it never treats incomplete reviews as passed. If it times out, the code is too large for the context, or the analysis doesn't finish, it downgrades everything to WARN—it would rather tell me "I didn't see everything this time" than give me a false green light. I've been burned by false "passes," so this is a hard rule I set for it.
It's not complicated to use. First, install it with one command:
curl -fsSL https://raw.githubusercontent.com/dengmengmian/ReviewGate/main/install.sh | sh
After installation, run it with one command:
reviewgate review
I personally use three modes most often:
- After making changes, compare against the requirements doc to see if it's off track, using
--intent spec.md - If it finds issues and I want it to fix them, use
--fix—it only makes changes with my approval for each one - To integrate with CI, add
--fail-on block—it exits with code 1 on high-risk issues, so no one can merge problematic code into the main branch
I haven't slacked on false positives either. When something is confirmed as a false positive, it doesn't silently delete it; instead, it records it in an ignore file, marks it with a fingerprint, and shares it across the team. This way, the same issue won't bother me twice, and there's a record—who marked it and why are all traceable.
On security, I've drawn a line: it's read-only by default, and only modifies files when I explicitly add --fix, with paths locked to the repository and no external access. Under the hood, it uses tree-sitter for parsing and can integrate with Claude Code, GitHub Actions, GitLab CI, pre-commit, and more.
These rules aren't made up on a whim. I've fed it batches of real PRs, covering 45 languages, and specifically targeted commits that were later reverted—to see if it could catch issues before merging. The evaluation data is all in the docs/evals/ folder in the repo, publicly accessible, not just my own claims.
If I had to complain, it's still a bit conservative—it prefers to over-report rather than miss anything, and sometimes it's verbose. My advice for adoption is to take it slow: first, run it in read-only mode without blocking, observe for a while, then enable warnings, and finally enforce blocking on merges. Don't choke the team from day one.
It doesn't replace testing or human review; it's just an extra gate between me and the main branch. It's open source, MIT licensed.
Want to try it: github.com/dengmengmian/ReviewGate