what it does

Review against your team's standards

Not generic checks, but the conventions of one particular team — on its stack, by its rules. In two places: with the agent in the editor while the code is being written, and on the pull request (merge request on GitLab) when it is time to accept it. Here is what the engine does.

two points of control

One policy — in the editor and on the pull request

Agents write more and more of the code, and catching their mistakes only on the pull request is late — every fix travels a full round trip. So the same team rules and the same judge work right inside the agent's loop. The bot on the pull request stays an independent gate: an agent cannot approve its own work, and the change-control point keeps its audit trail.

Where the ReviewGate tools apply A single .reviewgate/config.yml file sets the team rules for every checkpoint. Locally, while the code is being written, MCP (standards before the code), the CLI (checking the changes) and the git push hook all apply. After the push, the bot on the pull request remains an independent gate. .reviewgate/config.yml team rules · preset · judge LOCALLY · WHILE THE CODE IS WRITTEN MCP standards first CLI checks the changes Hook gate on git push caught before the push git push GITLAB Bot on the PR an independent gate an agent cannot self-approve

A CLI in any repository

reviewgate review reads the same .reviewgate/config.yml and the same presets as the bot, and runs the same two-pass judge. A single file with no Node and no Docker — six platforms, Windows and Alpine included.

A hook before git push

The agent cannot push changes that carry blocking findings. The gate sits on the push rather than on every step: a measurement showed the judge adds 35–47% to the cost of a run, so the thing to economise on is how often it is called.

MCP: the agent calls the review itself

Two tools: review the current changes, and read the team standards BEFORE writing code instead of learning them from a review afterwards. Works in MCP-compatible clients; we have run it on Claude Code.

Neither Node nor Docker is needed on the developer's machine, and the provider key is read only from the process environment — how to install and connect it →

in the pull request

Comments where people actually read them

Inline comments

Findings are anchored to specific diff lines — GitLab discussions, GitHub review comments — exactly as a human reviewer would leave them.

A summary grouped by severity

One summary comment with the findings grouped by severity and the verdict of the severity gate.

The severity gate as a status check

The bot publishes a check run on GitHub and a commit status on GitLab. With «pipeline must succeed» or a required check, that blocks the merge — a gate with real teeth.

precision, not noise

Findings you can trust

The main pain of AI review is noise and repetition. The engine attacks it with three mechanisms.

Two passes, not one

A cheap model finds; a strong one judges every finding against the real code (whole files and the neighbours they import) and against the team standards. The judge contract is strict: it looks for nothing new, it can only lower severity, and when in doubt it must drop — so fewer false positives reach the pull request. One role in llm.judges turns it on.

It does not spam on every push

A re-push reviews only the files that changed, never repeats an open finding and respects resolved threads — one living summary instead of an avalanche of duplicates. It saves tokens and reviewers alike.

It sees context, not only the diff

Optionally the bot takes the changed files whole, the neighbours they import and the stack versions from the manifests — it catches problems outside the hunk without inventing what is not there. The strict anti-hallucination rail stays on.

one-click fix

It does not only find — it offers the fix

For unambiguous problems the bot attaches a suggestion right in the thread: GitLab and GitHub render an «Apply» button, and the change lands in the branch with one click, with no copy-paste. Multi-line fixes included — up to 20 lines at a time. With a judge enabled (llm.judges) a strong model first checks the fix itself against the code — and its line range — so that only what genuinely repairs the problem can be applied in one click. Both options are switched on in the config.

How to enable it →
🔴 web-api-di-tokens · auth.ts:42
Direct localStorage access breaks SSR.

- localStorage.setItem('token', v)
+ this.storage.set('token', v)

[ ✓ Apply suggestion ]
a conversation in the thread

Disagree with the bot? Ask it

A developer answers a comment with a question, and the bot explains itself in the same thread — usually within a minute or two — leaning on the code and on the team standards from your config. The answer arrives on its own: no CI job to trigger, no command to type. To «fixed» or «ok, thanks» the bot stays quiet, and it gives at most three answers per thread by default. When the objection is fair the bot says so plainly, and it can back a colleague's proposal — citing the team rule. A human always closes the thread. An @mention invites the bot into someone else's thread too.

How to enable it →
🟠 magic-values · recently-viewed.ts:52
the id is concatenated with a «magic»
prefix 4200000 before it goes into the
shared list — the other write path stores
a clean id: one list, two formats.

  ├ author: that is intended — items from
  │         the external catalogue carry a
  │         prefixed id. isn't this a false
  │         positive?
  │
  ├ lead: @author, let's move the prefix
  │        into a constant anyway
  │
  └ bot: Not a false positive: a deliberate
         prefix does not remove the two id
         formats living in one list. I back
         @lead: by your magic-values rule
         the prefix belongs in a constant and
         the encoding in a single helper.
a transparent run

You can see what the bot did — and what it cost

The summary can carry the price of the run on your key: tokens and money, at your rates and in your currency. And a collapsed diagnostics block: what context the model saw, what calls were made and, above all, the judge's decisions with their reasons — including the findings it dropped. Why the judge removed a finding is visible right in the pull request, with no access to the bot's server or its logs. There is no code in the block, only metadata. Both options are switched on by a flag in the config.

⚙️ This review: 46.2K tokens in ·
   3.8K out · ≈ $0.21

🔬 Run diagnostics
Model context: diff: 14 files ·
   environment: ✓
Calls:
· generator sonnet — 41.3K→2.9K
  tokens · 38s · findings: 5
· judge opus — 96K→1.1K
  tokens · 64s · dropped: 1
Judge dropped / lowered:
❌ cart.service.ts:42 error-handling —
   «catchError is already one line above»
stack presets

Depth for your stack, not "find a bug, any bug"

Eleven language cores and dozens of frameworks from day one. The core knows the idioms and the traps of the language; the framework layer knows the specifics of the stack. The core itself is language-agnostic — without a preset it works on any language through your rules.

JavaScript / TypeScriptpreset: typescript

Strict types instead of any, races in async/await, leaked subscriptions, the trust boundary around input.

AngularReactVueSvelteNext.jsNestJSExpress
Pythonpreset: python

Typing and contracts, blocking calls inside async, resources through context managers, injections.

DjangoFastAPIFlask
Gopreset: go

Every err handled, cancellation through context, goroutine races and leaks, defer for resources.

GinEchoFiber
Javapreset: java

Optional instead of null, thread safety, resources through try-with-resources, boundary validation.

Spring
C# / .NETpreset: csharp

Nullable references, async/await without deadlocks, IDisposable/using, allocations in LINQ.

ASP.NET Core
PHPpreset: php

Strict comparisons instead of ==, typing and readonly, SQL injection, unsafe deserialisation.

LaravelSymfonyYii2
Kotlinpreset: kotlin

Null safety, structured coroutine concurrency, exhaustive when, leaked CoroutineScope.

AndroidKtor
Rubypreset: ruby

Metaprogramming risks, N+1 and blocking calls, exception handling, injections.

Rails
Rustpreset: rust

Borrows and lifetimes, no unwrap/panic, errors through Result, unsafe under a magnifying glass.

AxumActix
Swiftpreset: swift

Optionals without force-unwrap, retain cycles and [weak self], async/await, value vs reference.

iOS / SwiftUI
Dartpreset: dart

Null safety, dispose and the async gap, Future/Stream errors, needless widget rebuilds.

Flutter

Team rules apply on top of any preset, and some presets have options of their own. The full list and every option are in the configuration reference →

your team standards

Rules in plain English, in the repository

The standards live in .reviewgate/config.yml next to the code and are versioned through pull requests. You describe your conventions in plain English and the model applies them to the diff — that is the difference from a linter. Rules can also see the pull request metadata: a rule «no description — ask {mr:author} to add one» puts the @author into the comment, and the platform notifies them. And review_prompt sets the whole review guideline — extending the default one (extend) or replacing it entirely (replace).

Configuration reference →
rules:
  - id: commit-prefix
    description: "Commits carry TASK-<number>"
    severity: critical
  - id: no-any
    description: "No any, except in *.spec.ts"
    severity: major
  - id: mr-description
    description: "No PR description —
      ask {mr:author} to add one"
    severity: minor

severity_gate: off
your model

On your model, with your key

Anthropic's cloud, any OpenAI-compatible endpoint (DeepSeek, OpenRouter, Yandex AI Studio, your own vLLM) or a local model through Ollama — in which case nothing leaves at all. The code never leaves your infrastructure.

See it on your own pull request

Bring the bot up in your infrastructure and open a test pull request.