Open-source AI pull request reviewer
The MergeJudge GitHub Action and runner are an open-source AI pull request reviewer for GitHub, under the MIT license. You add one workflow file, use your own API key or run rules-only, and every pull request gets a lane (auto, review or block), a summary comment, line comments and a mergejudge/lane check.
The source is the public gauravsharmaGG/mergejudge-runner repository and the mergejudge-runner npm package. The Action is also on the GitHub Marketplace. Only that repository is the open-source AI pull request reviewer. MergeJudge as a product is an AI pull request reviewer with an open-source engine. The hosted service, which the GitHub App and the runner CLI connect to, is not open source.
The full workflow, with learning, deep mode and fork handling, is in Self-hosted AI code review GitHub Action. What the lanes mean: sort pull requests by risk. What the product is: What is MergeJudge?.
What is open source, and what isn't
| Part | Where | Open source? |
|---|---|---|
| Review engine: rules, prompts, response parsing, result format | core/ in mergejudge-runner | yes (MIT) |
GitHub Action: action.yml and the committed bundle action/index.cjs (Node 24) | mergejudge-runner | yes (MIT) |
Runner CLI (mergejudge-runner setup, run, status) | src/ in mergejudge-runner, and the mergejudge-runner npm package | yes (MIT) |
| Hosted MergeJudge service: GitHub App backend, panel, job queue | not public | no |
The Action, the hosted GitHub App and the runner all use this one review engine. Lanes, rubrics and policy files therefore work the same way in all three.
Install criteria
| Criterion | What you get |
|---|---|
| License | MIT, for the engine, the Action and the runner CLI |
| Self-host | The Action runs in your GitHub Actions runner and does not call the hosted service. Self-hosting the Worker itself is not public. |
| Own key | Your Anthropic, OpenAI, z.ai or OpenAI-compatible key, stored as a GitHub secret. MergeJudge does not issue keys. |
| Rules-only | provider: none, or no key. No model call. This is also what fork pull requests get, because they receive no secrets. |
| Base-branch config | .mergejudge.yml is read from the pull request's base branch. The pull request cannot change the rules that review it. |
One workflow file
The Action runs the review inside your own GitHub Actions runner. It does not call the hosted MergeJudge service and does not need a MergeJudge account.
Add your AI key as a secret (skip this for rules-only):
shgh secret set AI_API_KEYAI_API_KEYis your own Anthropic, OpenAI or z.ai key, stored as a GitHub secret. MergeJudge doesn't issue keys. Leave it out for free rules-only reviews.The secret name is up to you.
api_key_envtells MergeJudge which environment variable to read. MergeJudge doesn't log or post your key.Add the workflow:
yaml# .github/workflows/mergejudge.yml 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 }} # omit for rules-only with: provider: anthropic # or openai, zai, openai-compatible, none model: your-model-name # check your provider's docs for current names api_key_env: AI_API_KEYlabeledandunlabeledre-run the review when someone adds or removes a hold label such asdo-not-merge.Open a pull request. The run posts a sticky comment, line comments and the
mergejudge/lanecheck.Optional: add a
.mergejudge.yml. Without one, built-in defaults apply. The config is always read from the PR's base branch, so a PR can't change the rules that review it. Every option is in the config reference.
Pin @v1 for compatible updates, or a full commit SHA if your policy requires immutable references. The Action is also listed on the GitHub Marketplace.
Inputs and outputs
| Input | Default | What it does |
|---|---|---|
github_token | the workflow token (github.token) | Needs pull-requests: write and checks: write; contents: write to store lessons and open learning PRs |
app_id, app_private_key | (not set) | Optional GitHub App credentials (pass the key from a secret). An installation token is then used for all API calls, which approval.mode: bot-approve needs (approvals) |
mode | auto | auto picks from the event; or triage, feedback, propose |
config_path | .mergejudge.yml | Config file, read from the PR's base branch |
provider | (not set) | Overrides provider.type: anthropic, openai, zai, openai-compatible or none (rules-only, no AI call) |
base_url | (not set) | Overrides provider.base_url (for openai-compatible) |
model | (not set) | Overrides provider.model |
api_key_env | (not set) | Overrides provider.api_key_env: the environment variable that holds your key |
The inputs override the provider settings in .mergejudge.yml. Outputs: lane (auto, review or block) and proposal_pr (the number of the learning proposal PR, when a propose run opened one). With mode: auto, a pull_request event runs triage (the review), issue_comment runs feedback, and schedule or workflow_dispatch runs propose. The self-hosted guide has a workflow that wires up all three.
Choose a model, or none
A hosted API with your own key:
provider: anthropic,openaiorzai. Example configs are on LLM providers.Any Chat Completions endpoint, including one you run yourself:
provider: openai-compatiblewithbase_url:yaml# .mergejudge.yml provider: type: openai-compatible base_url: https://your-endpoint.example/v1 model: your-model-name api_key_env: AI_API_KEYNo model at all:
provider: none, or no key. Only the deterministic rules run. This is also what happens on fork PRs, which get no secrets. See fork pull requests.
What it does on each pull request
- The rules set a floor. Deterministic rules pick the minimum lane. They check protected paths (by default
.github/**,deploy/**,**/auth/**,**/migrations/**and a few more), obvious secrets in added lines, removed safety guards, file types, size and hold labels. No model is involved. See Lanes and rules. - The AI reviews the change, following your policy files and rubrics. The PR's title, body and diff go to the model as untrusted data, and the model is told to ignore instructions inside them.
- The AI can only raise a lane, never lower it. The one opt-in exception is
lanes.code_auto. If the model call fails or returns invalid JSON after one retry, the review falls back to rules-only and says so. - The result lands on the PR: one sticky summary comment, up to 20 line comments, and a
mergejudge/lanecheck (success= auto,neutral= review,failure= block).
| Lane | Meaning |
|---|---|
🟢 auto | Low risk, not a guarantee. Branch protection and required checks still apply. MergeJudge does not merge it. |
🟡 review | A human must look |
🔴 block | Do not merge |
MergeJudge doesn't merge pull requests itself. To make block stop a merge, make mergejudge/lane a required check in branch protection.
Give the model more of the repo: deep mode
By default (diff mode), the model sees the changed hunks, your policy files and rubrics. To give it the code the change touches, add a checkout step before the Action:
steps:
- uses: actions/checkout@v4
- uses: gauravsharmaGG/mergejudge-runner@v1
# ...same env and with as aboveThen set deep mode on the base branch:
# .mergejudge.yml
review:
mode: deepThe Action indexes the checked-out files in memory for this run only. It adds related code to the prompt (importers, imports, callers, and files that mention the changed names) and reviews in a single pass. Limits, the files it skips and the fallback to context mode are covered in deep mode and review modes.
Don't use pull_request_target with a checkout of the PR head. That runs untrusted code with your secrets.
Where your code goes
What our servers see: MergeJudge's servers read the pull request diff from GitHub to run the rules. The GitHub Action does not call those servers. When an AI provider is configured, the diff is sent to that provider.
With the Action, the parties are GitHub and the AI provider you configure. When a provider is set, the pull request diff, the title and body, your policy files and any related code snippets are sent to that provider, under your account and that provider's data terms. The diff does leave your runner, to that provider. With provider: none (or no key), there is no AI step and the diff goes nowhere except GitHub. The Action does not call the hosted MergeJudge service. MergeJudge does not use your code to train models. Your provider's own terms decide what that provider does with the prompt.
The Action does not send the diff to MergeJudge. On the runner, code handed through the job queue is deleted within about 48 hours. Review findings, which can quote short lines of code, are kept for a limited time. Details: https://mergejudge.si/privacy
The field-by-field table is in Where your data goes. For the hosted service and the runner, see Privacy and your code and the privacy policy.
The runner: the AI step on your own machine
The runner, from the same repository and npm package, works with the hosted service, not on its own. The MergeJudge GitHub App handles GitHub events, lanes and posting. Your machine takes review jobs and runs the model step with your own Claude Code or Codex login, or a z.ai API key.
npx mergejudge-runner setup # sign in with GitHub and register this machine
npx mergejudge-runner run # take review jobs (if you skipped auto-start)
npx mergejudge-runner statusIt needs Node.js 20 or newer, and the MergeJudge GitHub App installed on an account or organization you administer. Setup, engines and auto-start are covered in Run reviews on your own machine.
Learning from your team
The MergeJudge comment ends with feedback checkboxes. Someone with write access can tick one, or comment /mergejudge learn <note>. The Action then records a lesson on a separate mergejudge-learning branch. A scheduled run can open a proposal PR that adds protected paths or rubric notes to .mergejudge.yml. That PR is labelled do-not-merge and needs-human, and MergeJudge never approves or merges it. The Action learns from explicit feedback only. Setup, including the contents: write permission the proposal needs, is in learning.
Build it or contribute
git clone https://github.com/gauravsharmaGG/mergejudge-runner
cd mergejudge-runner
npm ci
npm run verify # typecheck + tests + build
node dist/cli.js --helpRead CONTRIBUTING.md before opening a pull request. The code in core/ is shared with the MergeJudge core, so propose behaviour changes there in an issue first. To report a vulnerability, follow SECURITY.md in the repository.
Checklist
- Add your AI key as a repository secret, or skip it for rules-only.
- Add
.github/workflows/mergejudge.ymlwithgauravsharmaGG/mergejudge-runner@v1. - Open a PR and check the comment and the
mergejudge/lanecheck. - Make
mergejudge/lanea required check ifblockshould stop merges. - Add a
.mergejudge.ymlon the default branch for protected paths, review mode and rubrics. - For more context, add
actions/checkoutandreview.mode: deep. - For learning, use the full workflow in Self-hosted AI code review GitHub Action.
FAQ
Is there an open-source AI pull request reviewer for GitHub?
Yes. The MergeJudge GitHub Action and the runner are an open-source AI pull request reviewer under the MIT license, in the gauravsharmaGG/mergejudge-runner repository and the mergejudge-runner npm package. One workflow file reviews every pull request. The hosted GitHub App is not open source.
What is open source, and what is hosted?
The review engine, the GitHub Action and the runner CLI are MIT-licensed in gauravsharmaGG/mergejudge-runner. The hosted GitHub App and its backend are not open source. The Action does not call the hosted service. The runner CLI does: it takes jobs from that service and runs the model step on your machine.
Can I run it with my own API key, or with no model?
Both. Set provider to anthropic, openai, zai or openai-compatible and pass your own key. MergeJudge does not issue keys. Set provider to none, or omit the key, and only the deterministic rules run.
What should I check before I install it?
The license is MIT. The Action runs in your GitHub Actions runner and does not call MergeJudge's servers. You bring your own key, or you run rules-only with no key. Config is read from the base branch, so the pull request cannot change the rules that review it.