ревью в цикле агента

CLI, хук и MCP

Одна политика — две точки контроля. Бот проверяет MR/PR и остаётся независимым гейтом; те же правила команды и тот же судья доступны агенту прямо в редакторе — до того, как код уедет на ревью.

что это даётАгент пишет код → сам зовёт ревью по стандартам вашей команды → правит → открывает MR/PR, который подтверждает независимый бот. Код не покидает ваш контур: бинарь читает репозиторий локально, а ревью выполняет либо ваш LLM-провайдер напрямую, либо ваш сервер ReviewGate — смотря что вы выберете ниже.

Сначала выберите свой случай

Дальше всё одинаково — установка, команды, хук, MCP. Различается ровно одно: где берётся доступ к модели. Выберите строку, которая описывает вас, и настройте только её.

Ваш случайЧто настраиваете
Я один, ключ мой
фрилансер, пет-проект, свой аккаунт у провайдера
LLM_API_KEY в окружении или в файле настроек — раздел «Свой ключ» ниже. Сервер не нужен вовсе
Мы команда, ключ у компании
CTO не раздаёт ключ разработчикам
адрес сервера ревью и личный токен GitLab — раздел «Через сервер команды». Инструкция тому, кто выдаёт доступ: сервер ревью для команды
У нас корпоративный шлюз LLM
LiteLLM или свой прокси с личными токенами
тот же «Свой ключ», но LLM_BASE_URL указывает на шлюз, а LLM_API_KEY — ваш токен к нему, не ключ вендора
Модель локальная
Ollama или vLLM на машине либо на общем сервере
LLM_PROVIDER и LLM_BASE_URL; ключ не нужен. Подробности — LLM и свой ключ

Установка

Один файл без зависимостей: ни Node, ни Docker не нужны. Требуется git в PATH — бинарь его в себе не несёт.

ПлатформаФайл
macOS · Apple Siliconreviewgate-latest-darwin-arm64.xz
macOS · Intelreviewgate-latest-darwin-x64.xz
Linux · x86-64reviewgate-latest-linux-x64.xz
Linux · ARM64reviewgate-latest-linux-arm64.xz
Linux · musl (Alpine)reviewgate-latest-linux-x64-musl.xz
Windows · x86-64reviewgate-latest-win-x64.exe.xz

Контрольные суммы — в файле SHA256SUMS рядом с артефактами. Сверяйте их: вы запускаете исполняемый файл, скачанный из сети.

Те же файлы выложены релизом на GitHub — байт в байт, с теми же контрольными суммами. Берите то, что быстрее; если сайт недоступен, релиз всё равно на месте.

macOS · Apple Silicon
curl -fsSLO https://reviewgate.dev/dl/reviewgate-latest-darwin-arm64.xz
curl -fsSLO https://reviewgate.dev/dl/SHA256SUMS
shasum -a 256 -c SHA256SUMS --ignore-missing

# no xz? brew install xz
xz -d reviewgate-latest-darwin-arm64.xz
chmod +x reviewgate-latest-darwin-arm64
sudo mv reviewgate-latest-darwin-arm64 /usr/local/bin/reviewgate
Linux · x86-64
curl -fsSLO https://reviewgate.dev/dl/reviewgate-latest-linux-x64.xz
curl -fsSLO https://reviewgate.dev/dl/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing

xz -d reviewgate-latest-linux-x64.xz
chmod +x reviewgate-latest-linux-x64
sudo mv reviewgate-latest-linux-x64 /usr/local/bin/reviewgate
Windows · PowerShell
# PowerShell. Windows cannot unpack .xz out of the box — take 7-Zip (winget install 7zip.7zip)
curl.exe -fsSLO https://reviewgate.dev/dl/reviewgate-latest-win-x64.exe.xz
curl.exe -fsSLO https://reviewgate.dev/dl/SHA256SUMS

# the hash must appear in SHA256SUMS — an empty output means it does NOT match
$hash = (Get-FileHash reviewgate-latest-win-x64.exe.xz -Algorithm SHA256).Hash.ToLower()
Select-String $hash SHA256SUMS

& "$env:ProgramFiles\7-Zip\7z.exe" x reviewgate-latest-win-x64.exe.xz
Rename-Item reviewgate-latest-win-x64.exe reviewgate.exe
# move reviewgate.exe to a directory on PATH, e.g. %LOCALAPPDATA%\Programs
Linux: glibc или muslОбычные дистрибутивы (Ubuntu, Debian, Fedora, RHEL) — берите linux-x64. Для Alpine и других musl-систем есть отдельная сборка linux-x64-musl; ей нужен пакет libstdc++ (в образах node:*-alpine он уже есть). Сборки перепутать нельзя — на чужой системе бинарь не запустится.

Свой ключ

Ключ провайдера берётся из окружения процесса или из вашего файла настроек в домашнем каталоге — но никогда из рабочей копии. Это граница безопасности: клон чужого репозитория не должен уводить ваш дифф на чужой endpoint.

терминал
export LLM_API_KEY=...        # your provider key
export LLM_JUDGES=...         # optional: a default judge (without one, a single pass)

Чтобы не задавать переменные в каждой сессии терминала, положите их в файл. Объявленные там generators / judges задают вашу схему для локальных прогонов — она замещает командную целиком (берётся как единое целое, генераторы обязательны), отчёт говорит об этом, а --team-llm прогоняет ролями команды. Подробнее: домашний конфиг.

~/.config/reviewgate/config.yml
llm:
  api_key: sk-...
  generators:                   # your schema for local runs: taken as a whole,
    - model: claude-sonnet-5    # it replaces the team llm.* from the repo config
  judges:                       # (--team-llm runs with the team schema instead)
    - model: claude-opus-5
  # base_url: https://llm.вашакомпания.ru/v1   # корпоративный шлюз, если он есть

Секрет можно не хранить в открытом виде: вместо api_key укажите api_key_command — команду вашего менеджера паролей. Её вывод нигде не сохраняется.

~/.config/reviewgate/config.yml
llm:
  api_key_command: op read op://dev/anthropic/credential
что в этом файле НЕ настраиваетсяПравила команды, ignore, пресет и порог блокировки живут только в .reviewgate/config.yml вашего репозитория. Домашний файл задаёт, куда ходить, но не что считать проблемой: иначе у каждого разработчика была бы своя политика, и локальный прогон перестал бы предсказывать вердикт бота на MR/PR.

Через сервер команды

Если ключ у компании и раздавать его не собираются, ревью выполняет ваш сервер ReviewGate. Вам нужен только его адрес и ваш личный токен GitLab — тот же, которым вы ходите в GitLab. Ключ модели не нужен.

~/.config/reviewgate/config.yml
server:
  url: https://bot.вашакомпания.ru
  gitlab_token: glpat-...   # your personal GitLab token
  # gitlab_token_command: pass show work/gitlab   # or this way, without storing it in the file

Дифф собирается у вас локально; на сервер уходят изменённые файлы, а остальное он дозапрашивает по мере надобности — ровно то, что реально понадобилось судье. Флаг --local возвращает прогон на ваш собственный ключ: пригодится вне сети компании. Как включить режим на сервере — отдельная страница для того, кто выдаёт доступ.

Первый прогон

терминал
reviewgate doctor      # check the environment before the first run
reviewgate rules       # which team standards were read
reviewgate review      # review the uncommitted changes

doctor проверяет окружение и говорит, чего не хватает, до того как вы потратите время и токены: он называет источник каждого значения и, в режиме сервера, живьём проверяет доступ. rules показывает, какие правила прочитаны из .reviewgate/config.yml — тот же файл, по которому работает бот.

Дальше бинарь объясняет себя сам: reviewgate help — обзор всех команд и флагов, reviewgate help review — подробно по одной. Те же сведения с примерами и ссылками — в справочнике CLI.

Машинный режим

С --json в stdout уходит только отчёт, всё остальное — в stderr. Коды возврата детерминированные: 0 — гейт пройден или выключен, 2 — есть находки не ниже порога, 1 — сбой (объект ошибки уходит в stdout, если задан --json, иначе текст в stderr). Порог по умолчанию берётся из политики команды, а она из коробки severity_gate: off — то есть без --fail-on код всегда 0.

терминал
reviewgate review --json --fail-on major

Поля отчёта, коды ошибок и рецепты для CI — в справочнике CLI.

Хук: ревью перед push

Хук перехватывает git push у агента и не даёт отправить изменения с блокирующими находками. Замер показал, что ставить гейт стоит именно на push, а не на каждый ответ агента: экономить надо на частоте вызова, а не на глубине проверки.

~/.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "reviewgate review --hook-stdin" }]
      }
    ]
  }
}

Порог блокировки — тот же, что у команды: хук читает severity_gate из конфига репозитория, поэтому решение перед push и вердикт бота на MR/PR совпадают. Единственное исключение — гейт, выключенный политикой (severity_gate: off, это дефолт): тогда хук применяет свой порог major и сообщает об этом, иначе он не блокировал бы никогда и был бы бесполезен. Свой порог на один запуск задаётся --fail-on. Диалекты ответа — в справочнике.

Если вы вешаете хук не на push, а на завершение работы агента (событие Stop), цикла не будет: раннер помечает такое повторное событие признаком «продолжаю из-за твоей блокировки», и на нём ReviewGate пропускает прогон вместо того, чтобы снова ревьюить. Иначе находка, которую агент не может или не хочет устранить, крутила бы «стоп → ревью → блокировка → стоп» без потолка, сжигая по полному прогону за виток.

сколько ждатьХук идёт полной схемой — той же, что задана в config.yml. На ансамбле из двух генераторов с арбитром это минуты: наш замер на изменении в два файла — 6,5 минуты и около $0,6, тогда как --fast (один генератор, без судьи) — полторы минуты и вчетверо дешевле. Так и задумано: ложная блокировка push стоит дороже ожидания, а на MR/PR тот же код проверит бот. Нужен более быстрый гейт — добавьте --fast в команду хука, понимая цену: находки не подтверждены независимой моделью, шума будет больше. Дешёвая дорога, сохраняющая судью, — своя схема LLM в домашнем конфиге: хук, как любой локальный прогон, идёт ею, а merge request бот по-прежнему ревьюит командной схемой.

MCP: агент зовёт ревью сам

Два инструмента: review_changes — проверить изменения, get_team_rules — узнать стандарты команды до написания кода, а не из ревью после. Если config.yml у проекта есть, но не разобран, get_team_rules скажет об этом прямо: «правил нет» и «правила не применились» — разные ответы, и агент должен их различать.

конфигурация MCP-клиента
{
  "mcpServers": {
    "reviewgate": { "command": "reviewgate", "args": ["mcp"] }
  }
}
короткий путь: пусть настраивает ваш агентДальше описаны три ступеньки, на которых спотыкается подключение. Проходить их руками не обязательно — скопируйте эту строку в чат со своим ассистентом:
run reviewgate help agent-setup and do what it says
Команда печатает инструкцию, написанную для агента, и он переведёт её в формат своей среды сам. Мы намеренно не правим конфигурацию клиентов: их много, у одного человека их бывает несколько сразу, и угаданный нами файл был бы хуже отсутствующего. Читать раздел стоит, чтобы понимать, что именно происходит и почему настройка иногда «не срабатывает молча».

Или поставьте из MCP Registry

Сервер опубликован в официальном MCP Registry под именем dev.reviewgate/reviewgate. Клиент, умеющий ставить из реестра (или принимающий бандлы .mcpb — например, Claude Desktop), получает самодостаточный пакет: бинарь внутри, инструменты объявлены, форма настройки — путь к конфигу и ключ модели. У каждого бандла есть fileSha256, и клиент сверяет с ним скачанное. Бандл — на каждую платформу свой: берите под вашу ОС и архитектуру; те же файлы приложены к GitHub Releases.

Подключить сервер мало: агент должен знать, что инструменты есть

Многие клиенты — в их числе Claude Code — грузят описания MCP-инструментов лениво: на старте сессии агент видит имя сервера, но не его инструменты, и просто не догадывается их позвать. Инструмент, которого нет в контексте, не будет вызван, каким бы точным ни было его описание. Лечится двумя строками в файле-инструкции проекта (CLAUDE.md, .cursorrules — смотря чем пользуется ваш агент):

CLAUDE.md проекта
The standards of this project come from the `mcp__reviewgate__get_team_rules` tool —
call it BEFORE writing code, instead of reading the ADRs by hand.

Before finishing a task and before `git push`, check the changes with the
`mcp__reviewgate__review_changes` tool — it is the same judge and the same rules
that check the pull request.

Разница измеримая. На проекте с восемью ADR мы попросили агента выяснить стандарты команды перед написанием кода, не упоминая ReviewGate: без этих строк он около трёх минут читал документы и код вручную; с ними — позвал get_team_rules на шестнадцатой секунде и получил тот же ответ вдвое дешевле. Правила при этом приходят из одного источника, а не восстанавливаются по коду с риском ошибиться.

Второй барьер: клиент спросит разрешение на вызов

Инструменты MCP — сторонний код, поэтому при первом обращении клиент спрашивает у человека, можно ли его звать. В обычной сессии это диалог: выбираете «разрешить», и дальше работает (вариант «разрешить всегда» клиент запоминает в настройках проекта). А вот в неинтерактивном запуске — claude -p "…", прогон из CI, любой скрипт — диалог показывать негде и некому нажимать.

чем это опасноАгент не останавливается на отказе. Он честно скажет, что ждёт разрешения, — и, не дождавшись, ответит собственным мнением о коде вместо ревью. Выглядит похоже: тот же тон, те же формулировки, иногда даже верная находка. Но это не проверка вашими правилами и не вердикт судьи: в нашем замере агент без доступа к инструменту нашёл в диффе одну критическую проблему, тогда как полное ревью того же диффа дало четырнадцать замечаний, девять из них критических. Если в ответе агента нет вызова инструмента — ревью не было, чем бы ответ ни выглядел.

Лечение — перечислить инструменты при запуске либо один раз выдать разрешение в обычной сессии, после чего неинтерактивные прогоны пойдут без флагов. Имена собираются из имени сервера в вашей конфигурации: назвали сервер reviewgate — инструменты зовутся mcp__reviewgate__review_changes и mcp__reviewgate__get_team_rules.

неинтерактивный прогон с разрешением
# one-off: list the tools at startup
claude -p "check the uncommitted changes" \
  --allowedTools mcp__reviewgate__review_changes mcp__reviewgate__get_team_rules

# once and for all: grant the permission in an ordinary session
# and the client remembers it for this project
claude
как убедиться, что всё сложилосьПроверять конфигурационные файлы бесполезно: у каждого клиента они свои, и наличие записи не значит, что вызов состоится. Проверка одна и работает везде — тоже одной строкой в чат:
call the get_team_rules tool and show me what it returned
Правила пришли и в ответе виден вызов — работает вся цепочка разом. Инструмент бесплатный, модель он не зовёт. Нет вызова — нет ревью, чем бы ответ ни выглядел.

Одна тонкость, на которой мы сами обожглись: конфигурацию клиенты читают при старте, поэтому проверять сразу после записи бессмысленно — перезапустите сессию. Иначе увидите либо отказ на верной настройке, либо, что хуже, успех по настройке, которая была на машине раньше.

Механизм у каждого клиента свой: приведённый флаг — из Claude Code, в других агентах ищите «tool permissions» или «allowed tools». Общее одно: сервер, которому не разрешили работать, молчит не громче, чем сервер, который не подключён, — и отличить эти два случая можно только по наличию вызова в протоколе.

Что происходит во время прогона

Ревью идут по одному: второй вызов ждёт первого, а не делит с ним бюджет и лимиты провайдера. Канал при этом свободен — короткие методы протокола отвечают сразу, и клиент видит, что сервер жив.

Отмена работает. Агент прекратил вызов (пользователь нажал Esc, задача снята) — прогон останавливается, и ответ на отменённый вызов не отправляется. Честная граница: ответ, который модель уже начала, провайдер посчитает в любом случае; экономия в том, что не начинаются следующие вызовы — судья, ансамбль, арбитр. То же и при закрытии соединения: заказчика нет — считать не для кого.

Ошибка инструмента приходит с isError: true, а в тексте — тот же объект reviewgate.error/v1 с кодом, что печатает CLI (полный список — на странице CLI). Агенту есть по чему ветвиться, и разбирать сообщение регулярками не нужно.

WindowsПроверено на Windows Server 2019: диагностика, сбор изменений, хук и MCP работают. В консоли выполните chcp 65001, иначе не-ASCII символы отчёта — в их числе эмодзи-маркеры — выведутся нечитаемо. На --json это не влияет: в stdout всегда UTF-8.