for whoever decides

Review server: access for the team without sharing a key

Review in the editor needs a model key. Nobody wants to hand the corporate key to twenty developers, and only a few will buy their own — which leaves the second point of control with a minority of the team. The review server solves that: the key stays on your server, and each developer gets their own access to it.

How it works

The binary on the developer machine collects the changes with ordinary git and sends them to your ReviewGate server — the same one that checks pull requests. The server performs the review: with its key, its model, over its network. The developer needs no key and is given none.

where the code goesThe code never leaves your infrastructure: the binary reads the repository locally and your own server performs the review. There is one difference from checking a pull request, and it is worth stating plainly: uncommitted code reaches the server — drafts, and whatever a developer usually tidies up before committing. The server does not keep it: only review metadata goes to the log and the metrics; neither the diff nor file contents settle there.

What to enable on the server

Three environment variables. Until the first one is set the mode is off entirely — that is deny by default, not an oversight: the server will not start accepting runs by itself after an upgrade.

the .env of your server
# GitLab groups that grant access to the review server (comma-separated, full paths).
# Empty or unset — the mode is off and CLI runs are not accepted.
REVIEWGATE_CLI_GROUPS=dev/reviewgate-cli

# How many reviews the server runs at once. The mode needs at least 2.
REVIEW_CONCURRENCY=4
# How many of those may be taken by developers working locally.
# Half by default; must be strictly less than REVIEW_CONCURRENCY.
REVIEW_CLI_CONCURRENCY=2

# Session timings — rarely worth changing; the values below are the defaults.
# How long a run waits for a free slot before it is refused with «the server is busy».
REVIEW_CLI_QUEUE_WAIT_MS=60000
# Waiting for ONE file from the developer machine. Deliberately shorter than the session cap:
# the slot is held while the server waits, and a sleeping laptop would otherwise eat capacity.
REVIEW_CLI_FILE_TIMEOUT_MS=30000
# The lifetime cap of a session. A full run with an ensemble and an arbiter takes ~5 minutes.
REVIEW_CLI_SESSION_TIMEOUT_MS=900000

The developer pool is capped, and the difference from the total capacity is your reserve: that many pull request checks start immediately, whatever the developers are doing locally. The gate never queues behind somebody else's run. The server prints this guarantee in words at startup and reports the same in /api/health.

The same place shows who is holding the slots right now — the first thing to look at when someone complains that «the CLI says the server is busy»: whether a pull request check is running, whether somebody else's run is stuck, or whether the capacity is simply too small.

server occupancy
curl -s http://localhost:3000/api/health
# {"status":"ok", ... "capacity":{
#   "total":4,"cli":2,"mrReserve":2,        <- the configuration
#   "inFlight":{"mr":1,"cli":2},            <- busy right now
#   "waiting":1                             <- waiting for a slot
# }}

In the server log such refusals are warnings, not errors: a capacity policy doing its job must not get lost among real failures.

What the developer controls, and what you do

The review runs on the policy from the developer's working copy — that is by design: a person edits .reviewgate/config.yml and sees the effect at once, without committing. But the other side is worth knowing: that file sets the model, the second pass and the composition of the ensemble, and the deployment key pays for them. An uncommitted edit along the lines of «let me give myself a stronger model» raises the company's bill, and the server does not argue with it.

what the server limits, and what it does notWhat is limited is the number of concurrent runs and access (membership of a GitLab group). The cost of a single run is not limited: there is currently no ceiling on the model or on the number of passes. The spend is visible in the metrics — CLI runs are written to the same table as pull request reviews, with the developer's login.

Who is allowed is decided in GitLab

Access is granted by membership of a GitLab group, not by a separate list on our side. Add a person to the group and they have access. Remove them and they do not. Block the account when they leave and access closes by itself, with no separate action from an administrator.

You may list several groups: a separate one for people with wider access, for instance. Membership is checked with inheritance — access granted on a parent group works in its subgroups too.

What may be reviewed

The binary reports the origin address of its repository, and the server checks through your GitLab API that such a project exists on your instance and that this person has Reporter access or above to it. A personal project on somebody else's hosting will not pass: the corporate key is spent on your code, not on whatever happens to be around.

The server accepts review requests only and answers with a list of findings. It is not a proxy to a language model: you cannot hold a conversation through it or get arbitrary text out of it.

What you can see

Every run lands in the server log: who (the GitLab login), which project, how many files and in which mode — in the same place as the rest of the bot's logs (logs and monitoring). Who ran how many checks is visible from the log.

An abandoned run costs nothing: if the developer interrupted the command or lost the connection, the server stops calling models — an answer already in flight will most likely be billed, but the next steps (the second generator, the judge) never start. In the log such a run appears as cancelled, and in the metrics with the cancelled status.

The spend is visible too: every CLI run writes a row into the same Postgres metrics as pull request checks — with the developer's login, the project, the models and the tokens per role. A ready-made «who spent how much this month» query is on the same page. Metrics are enabled by setting DATABASE_URL; without it the bot works, but nothing is accounted for.

what is not there yetThere are no spend limits per person or per team: an overrun is visible in the metrics but is not stopped automatically — only the number of concurrent runs is capped. There is no ready dashboard either; the figures come from a query against the database. If either of those is a condition for you to start, write to us — the priority follows demand.

What the developer does

Installs the binary (CLI, hook and MCP) and creates one file in their home directory:

~/.config/reviewgate/config.yml
server:
  url: https://bot.вашакомпания.ru
  gitlab_token: glpat-...        # the developer's personal GitLab token

The token is an ordinary GitLab personal access token belonging to the developer — the same one they use for GitLab. They need no model key. To check that the workstation is ready:

terminal
reviewgate doctor

The command says whether access exists: it names the developer login and the project path the server saw, or the reason for refusal (the token was rejected, no access to the repository, no network). It does not check how busy the server is: that is a state of the minute, and it is learned on the run itself — as a «try again later», not as a denial of access.