Open Source Code Review Tools for GitHub and Self-Hosted Teams
Open source code review tools fall into two groups, and search results often mix them. Open source code review tools for GitHub run inside pull requests you already have: a GitHub Action or a CLI posts on the pull request, and the repository stays on GitHub. Self-hosted Git forges and review servers are the other group: they are where the repository, or the review request, lives.
MergeJudge (mergejudge.si) is an AI pull request reviewer with an open-source engine for GitHub. The engine, the Action and the runner CLI are MIT-licensed in gauravsharmaGG/mergejudge-runner. Every pull request is sorted into an auto, review or block lane. Deterministic rules set the floor, and the AI step can only raise that lane. auto means low risk, not a guarantee. MergeJudge never merges pull requests itself.
Use the first table when the code stays on GitHub. Use the second table when you are choosing software to host Git, or a review server that sits beside a Git host you already run.
Open-source code review tools inside GitHub pull requests
These four tools plug into GitHub. None of them replaces GitHub. None of them is a Git server.
| Tool | License | What It Checks | Runs Where | Needs LLM Key? | Best For |
|---|---|---|---|---|---|
| MergeJudge Runner | MIT | Deterministic base-branch rules, rubric checks, and an optional AI review. Sorts every pull request into auto, review or block. | Your GitHub Actions runner (GitHub-hosted or one you operate). The Action does not call MergeJudge's servers. | Only for the AI step. Rules-only needs no key and makes no model call. | A merge lane on existing GitHub pull requests that the pull request cannot loosen. |
| reviewdog | MIT | Linter and static-analysis output, filtered onto the diff. | CI. On GitHub, a GitHub Action or the CLI. | No | Inline comments from tools you already run, on the lines that changed. |
| Danger | MIT | Pull request conventions you write in a Dangerfile: JavaScript, TypeScript (danger-js) or Ruby. Typical checks are the description, labels, changelog and changed paths. | CI. On GitHub, a GitHub Action or the CLI. | No | Process rules about the pull request itself. |
| super-linter | MIT | Syntax and style across many languages, using the linters bundled in its container image. | GitHub Actions (a container Action). It can also run anywhere you can run that image. | No | One Action that lints a polyglot repo and fails the check. |
auto on a MergeJudge run means low risk, not a guarantee. Branch protection and required checks still apply, and MergeJudge never merges the pull request.
What each GitHub tool is for
MergeJudge Runner reads .mergejudge.yml from the pull request's base branch, then posts one sticky summary comment, line comments (at most 20 findings) and a mergejudge/lane check. The check is success for auto, neutral for review and failure for block. Rules-only mode is zero API key, free and deterministic. With AI_API_KEY the Action calls only the provider you set: Anthropic, OpenAI, z.ai, or an OpenAI-compatible endpoint. OpenRouter (base_url: https://openrouter.ai/api/v1) is the documented compatible endpoint, and its catalog includes Gemini models. MergeJudge does not issue keys. Install details: open-source AI pull request reviewer.
reviewdog takes a report your linter already produced (rdjson, checkstyle, SARIF and other formats) and publishes it as a GitHub review. The usual reporter is github-pr-review, which comments on diff lines. Filter to added lines, or to the diff, so a pull request does not inherit every old warning in the repo. reviewdog does not choose a risk lane and does not read a policy file from the base branch.
Danger runs a Dangerfile in CI and comments once on the pull request. Teams use it for rules a linter cannot see: a missing changelog entry, a pull request body that is too short, a forbidden path, a missing label. It is a convention check on metadata and the file list. It is not a substitute for a linter, and it does not set auto, review or block.
super-linter runs many language linters inside one Action and reports through the job log and GitHub Actions status checks. It can also write a pull request summary when the workflow grants pull-requests: write. It does not, by itself, attach one comment per finding the way reviewdog does. The default VALIDATE_ALL_CODEBASE is true, which lints the whole workspace. Set it to false to lint changed files. A few bundled linters still scan the whole workspace: the project documents which ones. The image is large, so expect a heavier job than a single linter.
Self-hosted open-source Git forges and review servers
These five projects are the place code is hosted, or a review server next to that host. Installing one of them does not add a check to a GitHub pull request. You move the repository, or you send diffs to the review server.
| Platform | License | Review Model (branch PR vs patchset change) | Required Approvals in Free Tier | Footprint / Ops Notes |
|---|---|---|---|---|
| Gitea | MIT | Branch pull request | Yes. Branch protection takes a required approval count. Reviews from users with write access count, unless you restrict the allowlist. | One Go binary. SQLite is enough for a small team. MySQL or PostgreSQL when you outgrow that. Low memory compared with a full DevOps suite. |
| Forgejo | GPL-3.0-or-later | Branch pull request | Yes. Branch protection takes a required approval count, same idea as Gitea. | One Go binary, same shape as Gitea. |
| GitLab Community Edition | MIT | Branch merge request | No. Community Edition records optional approvals. A minimum approval count that blocks the merge is not part of Community Edition. Protected branches and required pipelines are. | Omnibus package or Helm. PostgreSQL, Redis, Gitaly and background workers. Plan for several GB of RAM and treat upgrades as a platform change. |
| Gerrit | Apache-2.0 | Patch-set change | Yes. The default submit rule is Code-Review +2 on the latest patch set and no -2. You edit that expression in project config. The whole server is this open-source release. | A Java process. Review metadata lives in Git (NoteDb). A reverse proxy in front is typical. You operate a review server, not a bundled CI platform. |
| Review Board | MIT | Review request over a diff (pre-commit or post-commit) | The open-source server treats a request as approved with at least one Ship It and no open issues. That state is recorded. A hook or rbt land is what refuses the commit. | A Django app plus a SQL database. Your Git host stays separate. RBTools (rbt post) uploads the diff. |
Branch pull request (Gitea, Forgejo) and branch merge request (GitLab Community Edition) mean the same working shape: a branch, a diff against a base branch, inline comments, then a merge. A Gerrit patch-set change is one commit you push to refs/for/target-branch and update with git commit --amend. A Review Board review request is the diff itself, posted before or after that commit lands, and Review Board is not the Git remote.
GitLab's Community Edition source is MIT. The upstream repository also contains code that is not built into Community Edition. Install the Community Edition package when that is the edition you mean. Forgejo releases from v9 onward are GPL-3.0-or-later. Earlier Forgejo releases are MIT.
How to layer an open-source GitHub code review stack without noise
A modern team on GitHub uses three layers. Each layer owns one job. When two tools report the same finding, people stop reading both.
| Layer | Tool | Owns | Leave to another layer |
|---|---|---|---|
| 1. Mechanical lint | reviewdog or super-linter | Syntax and style on the lines that changed | Risk lanes, policy, merge gates |
| 2. Deterministic policy | MergeJudge Runner, rules-only | Protected paths, obvious secrets, removed safety guards, size, labels, the lane | Formatting nits |
| 3. Rubric and AI | MergeJudge Runner with your key, or the hosted App | Criterion ids, a quote from the diff, a lane that can only go up | Lowering the rules floor, merging the pull request |
Danger sits beside layer 1 when you care about pull request hygiene (changelog, description, labels). It should not re-implement the linter, and it should not try to be the risk lane.
1. Fast mechanical linters on changed lines
Run reviewdog when you already have a linter and you want its findings on the diff, in the GitHub review UI. Run super-linter when you want one Action to cover many languages and you are fine with a status check (and an optional summary comment) instead of a comment per line.
Pick one publisher per linter. If super-linter already runs a language's linter, do not also send that same linter through reviewdog, or every style issue appears twice. Point the linter at the change:
- reviewdog: filter to added lines, or to the diff context, so untouched files stay quiet.
- super-linter:
VALIDATE_ALL_CODEBASE: falseso the job lints new and changed files. Check the few linters that ignore that switch.
These tools fail style. They do not know that .github/** must not be an auto merge, and they do not read .mergejudge.yml.
2. Deterministic policy and risk lanes
Run MergeJudge Runner in rules-only mode for the lane. The Action runs in your GitHub Actions runner (or a self-hosted runner you operate). It does not call MergeJudge's servers. Rules-only is zero API key, free and deterministic: the job makes zero model calls.
.mergejudge.yml is read from the base branch first. The pull request head is not the config source. A pull request cannot delete a protected path, turn rubrics off, or switch the provider for the review that is about to run. That holds when a person opens the pull request and when an AI coding agent opens it. A pull request that edits .mergejudge.yml itself is at least review. The same base-branch rule applies to policy files such as AGENTS.md and REVIEW_POLICY.md. How to keep an agent from merging its own pull request: stop AI agents merging their own pull requests.
With the built-in defaults, rules-only already does the following. The full list is in lanes.
- Protected paths (by default
.github/**,deploy/**,**/auth/**,**/migrations/**and a few more) are at leastreview. - Obvious secrets in added lines, and removed safety guards in a protected path, are
block. - Code files are
reviewunless you opt in tolanes.code_autoon the base branch. - Small docs and style-only paths under the line limit can be
auto. That is low risk, not a guarantee. MergeJudge never merges the pull request.
The rules-only run still posts one sticky comment and the mergejudge/lane check. It does not add a style comment for every lint warning. That is layer 1's job.
3. Evidence-backed rubric and AI review
Add a model only after the floor exists. Two ways to run the same engine:
- The open-source Action, with your own key. Set
providertoanthropic,openai,zaioropenai-compatible, and passAI_API_KEY. The Action still runs in your runner and still does not call MergeJudge's servers. It calls only the provider you chose. OpenRouter isopenai-compatiblewithbase_url: https://openrouter.ai/api/v1. Use it when you want one key for many models, including Gemini models OpenRouter lists. Model ids change: copy the id from your provider's docs intomodel. - The hosted GitHub App, if you do not want a workflow file. On that path, diffs are read only to run the review and deleted afterwards. They are never stored as a copy of the repository and never used for training. Review findings can quote short lines and are kept for a limited time. Details: privacy and the hosted service.
Rubrics are short questions with a criterion id, such as sec.no-secrets or cor.logic. The rubric row cites that id. A confirmed finding quotes a line that MergeJudge verifies against the diff, and a failed high-severity criterion with that quote raises the lane (to review, or to block when the criterion says so). A suspicion the model cannot quote is listed and does not raise the lane. The write-up of each pack is in rubric packs.
The AI can only raise the lane (auto, review or block). It cannot lower the floor the deterministic rules already set. The one opt-in exception is lanes.code_auto, which is off by default. A pull request cannot turn it on, because that key is read from the base branch. auto is still low risk, not a guarantee, and MergeJudge never merges the pull request.
If the model call fails, or the reply is not valid JSON after one retry, the review falls back to rules-only and says so. The lane does not become auto because the model was down.
Copy the MergeJudge workflow
Use one of these files, at .github/workflows/mergejudge.yml. Running both on the same pull request posts two reviews. Pin @v1 for compatible updates, or pin a full commit SHA when your policy requires an immutable Action reference.
Keep the trigger on pull_request. Do not switch it to pull_request_target and check out the pull request head. That runs untrusted code with your secrets.
Fork pull requests receive no secrets, so this workflow runs rules-only there even if the repository has a key. That fallback is intentional.
Rules-only (zero API key, free and deterministic)
No AI_API_KEY. provider: none. The Action makes zero model calls.
# .github/workflows/mergejudge.yml
# Rules-only: zero API key, free and deterministic. No model call.
name: MergeJudge
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
permissions:
contents: read
pull-requests: write
checks: write
jobs:
lane:
runs-on: ubuntu-latest
steps:
- uses: gauravsharmaGG/mergejudge-runner@v1
with:
provider: noneYour own API key
AI_API_KEY is your Anthropic, OpenAI, z.ai or OpenAI-compatible key, stored as a GitHub secret (gh secret set AI_API_KEY). MergeJudge does not issue keys. The Action sends the diff to that provider only.
# .github/workflows/mergejudge.yml
# AI mode: your key, your provider. The Action calls that provider only.
name: MergeJudge
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
permissions:
contents: read
pull-requests: write
checks: write
jobs:
lane:
runs-on: ubuntu-latest
steps:
- uses: gauravsharmaGG/mergejudge-runner@v1
env:
AI_API_KEY: ${{ secrets.AI_API_KEY }}
with:
provider: anthropic # anthropic | openai | zai | openai-compatible
model: your-model-name # copy the current id from your provider's docs
api_key_env: AI_API_KEYOpenRouter (and any other Chat Completions host, including a Gemini model served there) uses provider: openai-compatible plus a base_url. Put that in .mergejudge.yml on the base branch, or pass base_url the way LLM providers describes. Example base-branch config:
# .mergejudge.yml on the default branch, not only on the pull request branch
provider:
type: openai-compatible
base_url: https://openrouter.ai/api/v1
model: your-model-name
api_key_env: AI_API_KEYEvery option and default: .mergejudge.yml. A workflow that also covers learning and deep mode: self-hosted GitHub Action.
Require the mergejudge/lane check
A comment is easy to miss. The check is what branch protection can require.
| Lane | Meaning | mergejudge/lane |
|---|---|---|
auto | Low risk, not a guarantee. MergeJudge does not merge it. | success |
review | A human must look. A neutral required check does not stop the merge, so require a human review as well. | neutral |
block | Do not merge. When this check is required, GitHub blocks the merge. | failure |
auto means low risk, not a guarantee, and MergeJudge never merges pull requests itself. Approvals are off by default. Steps to require the check: make AI code review a required status check.
Where the review runs
| Path | Where the job runs | What gets a model call |
|---|---|---|
| GitHub Action, rules-only | Your GitHub Actions runner or your own machine | Nothing. Zero model calls. The Action does not call MergeJudge's servers. |
GitHub Action, AI_API_KEY | Your GitHub Actions runner or your own machine | Only the provider you set (Anthropic, OpenAI, z.ai, or an OpenAI-compatible endpoint such as OpenRouter). The Action does not call MergeJudge's servers. |
| Hosted GitHub App | MergeJudge's service | Diffs are read only to run the review and deleted afterwards. They are never stored as a copy of the repository and never used for training. |
The npx mergejudge-runner process that takes jobs from the hosted App is a different setup from the Action above. It connects to the hosted service and runs the model step on your machine. That path is documented in run reviews on your own machine.
FAQ
What are open source code review tools for GitHub?
Open source code review tools for GitHub run inside pull requests that already live on GitHub. This page compares four MIT-licensed ones: MergeJudge Runner (gauravsharmaGG/mergejudge-runner) sorts every pull request into auto, review or block from base-branch rules, rubric checks and an optional bring-your-own-key AI review; reviewdog posts linter output on changed lines; Danger checks pull request conventions from a JavaScript, TypeScript or Ruby Dangerfile; super-linter bundles many language linters in one GitHub Action. auto means low risk, not a guarantee, and MergeJudge never merges pull requests.
How is a self-hosted Git forge different from a GitHub pull request review tool?
A self-hosted forge or review server is where the repository or the review request lives. Gitea, Forgejo and GitLab Community Edition review branch pull requests or merge requests. Gerrit reviews patch-set changes. Review Board reviews a diff and is not a Git server. reviewdog, Danger, super-linter and MergeJudge Runner do not replace GitHub. They run in GitHub Actions or a CLI and post on the pull request.
Can I run open source code review on GitHub with no model key?
Yes. reviewdog, Danger and super-linter never call a model. MergeJudge Runner rules-only mode (provider: none, or no AI_API_KEY) is zero API key, free and deterministic: the Action runs in your GitHub Actions runner, does not call MergeJudge's servers, and makes zero model calls. With AI_API_KEY it calls only the provider you set.
Can a pull request, or an AI coding agent, loosen its own MergeJudge review?
No. MergeJudge reads .mergejudge.yml from the pull request's base branch, not from the head. Protected paths, rubric packs and the provider for this review come from that base file. A pull request that edits .mergejudge.yml is at least review. Deterministic checks set the floor. The AI can only raise the lane, except the opt-in lanes.code_auto, which is off by default and is also read from the base branch.
Does the auto lane merge the pull request?
No. auto means low risk, not a guarantee. MergeJudge never merges pull requests itself. Branch protection and required checks still apply. The mergejudge/lane check is success for auto, neutral for review and failure for block. GitHub treats a neutral required check as successful, so a review lane does not stop a merge on its own.
Which self-hosted open source review tools use patch sets instead of branch pull requests?
Gerrit reviews each change as patch sets. You push to refs/for/target-branch and update the change by amending the commit. The default submit rule is Code-Review +2 on the latest patch set and no -2. Review Board stores a review request over a diff, either before or after the commit, and the Git server stays wherever you already host it. Gitea, Forgejo and GitLab Community Edition use branch pull requests or merge requests.