gitl
gitl
ИИ-ревьюер истории git для CLI и CI. gitl (git-log-lens) читает историю git репозитория и превращает её в структурированный инженерный артефакт с помощью LLM:
gitl review <range>— ИИ-ревью диапазона коммитов / PR с машиночитаемой оценкой риска (low|medium|high) для гейтинга в CI (--fail-on=high→ код выхода 2); потоковая передача токенов в терминал в реальном времени; кэш ответов LLM на диске с опциональным общим удалённым кэшем для CI; пользовательские шаблоны системного промпта;--stagedревьюит staged (незакоммиченные) изменения передgit commit(также доступно как pre-commit hook).gitl changelog [<range>]— журнал изменений в стиле Keep a Changelog, сгруппированный по conventional commits (по умолчанию от последнего тега доHEAD); детерминированный по умолчанию,--aiопционально переписывает его моделью в читаемый текст релиз-ноутов;gitl digest [--days=N] [--repos=a,b,c]— сводка активности по автору/теме/файлу, включая несколько репозиториев параллельно; интерактивный TUI-просмотрщик (--tui).
Чистый CLI-бинарник плюс обёртка для GitHub Action — без сервера, без базы данных, без хостинга ключей. BYOK (принеси свой ключ) с поддержкой нескольких провайдеров: OpenAI-совместимый API, Ollama (локальный/самохостинг), Azure OpenAI, нативный Anthropic (Claude), Google Gemini. Без телеметрии.
Статус: выпущена
v0.6.2— все три команды работают на реальных репозиториях со всеми тремя форматами вывода (md|text|json). Action публикует ИИ-ревью как закреплённые комментарии к PR и гейтит по оценке риска. Релизные бинарники кросс-скомпилированы, подписаны cosign и покрыты SLSA L3 provenance сборки (см. VERIFY.md).
Быстрый старт
Требуется Go 1.22+ и git в PATH.
# build
go build ./...
# AI review of a commit range — streams tokens to the terminal in real time
GITL_API_KEY=sk-... go run ./cmd/gitl review HEAD~5..HEAD
# no key = deterministic offline review (heuristic risk, no network call)
go run ./cmd/gitl review HEAD~5..HEAD
# review staged (not yet committed) changes before `git commit`
go run ./cmd/gitl review --staged
# review a GitHub PR by number — requires the `gh` CLI (installed + authenticated);
# resolves base/head via gh, fetches `pull/N/head` locally when needed, and reviews
# the merge-base diff (base...head), same as GitHub shows
go run ./cmd/gitl review pr/42
# machine-readable output for CI + risk gating
go run ./cmd/gitl review HEAD~5..HEAD --format=json
go run ./cmd/gitl review HEAD~5..HEAD --fail-on=high # exit code 2 on high risk
# exit codes: 0 = ok (risk below --fail-on), 1 = tool/runtime error (git/LLM/
# config failure), 2 = the --fail-on risk gate triggered — CI can branch on 2
# estimate cost without making an API call
go run ./cmd/gitl review HEAD~5..HEAD --dry-run
# custom system-prompt template (e.g. your team's review policy) — set via
# config only (prompt.system_template_file); there is no --system-template flag
# see Configuration → Custom templates below
# skip the on-disk LLM cache (always call the model)
go run ./cmd/gitl review HEAD~5..HEAD --no-cache
# disable streaming (non-interactive, buffered output)
go run ./cmd/gitl review HEAD~5..HEAD --no-stream
# suppress the informational offline-mode notice on stderr (errors and the
# review output are unaffected) — also via GITL_QUIET=1 or output.quiet: true
go run ./cmd/gitl review HEAD~5..HEAD --quiet
# changelog from last tag (or full history if no tags) — no LLM by default
go run ./cmd/gitl changelog
go run ./cmd/gitl changelog v1.2.0..HEAD --format=json
# AI changelog: the model rewrites the grouped result as release-note prose and
# reclassifies significant non-conventional commits out of "Other". Without an API
# key (or on a malformed model response) it falls back to the deterministic
# changelog with a warning — never fails. --dry-run/--max-cost-usd/--no-cache work
# the same as for review.
GITL_API_KEY=sk-... go run ./cmd/gitl changelog --ai
# activity summary for the last N days — no LLM
go run ./cmd/gitl digest --days=14
# multi-repo digest: runs in parallel; one unreachable repo does not fail the rest
go run ./cmd/gitl digest --repos=../service-a,../service-b --format=json
# interactive TUI viewer for digest (requires a TTY)
go run ./cmd/gitl digest --days=14 --tui
go run ./cmd/gitl version
go run ./cmd/gitl --help
# tests
go test ./...Установка:
# Go toolchain
go install github.com/akomyagin/gitl/cmd/gitl@latest
# Homebrew (macOS/Linux)
brew install akomyagin/tap/gitl
# npm — downloads the prebuilt binary for your platform from GitHub Releases
# and verifies its SHA256 checksum (no Go toolchain needed).
npx gitl-cli review HEAD~5..HEAD # or: npm install -g gitl-cli
# Or download a signed release binary from GitHub Releases (see VERIFY.md)Дополнения для оболочки
gitl поставляет сгенерированные cobra дополнения для bash, zsh, fish и PowerShell.
Homebrew устанавливает дополнения для bash/zsh/fish автоматически (релизные архивы также содержат их в completions/). В противном случае включите их по требованию:
# bash (current shell)
source <(gitl completion bash)
# bash (persistent) — Linux
gitl completion bash > /etc/bash_completion.d/gitl
# zsh (persistent)
gitl completion zsh > "${fpath[1]}/_gitl"
# fish
gitl completion fish > ~/.config/fish/completions/gitl.fish
# PowerShell
gitl completion powershell | Out-String | Invoke-ExpressionФлаги с фиксированными наборами значений — --format (md|text|json), --fail-on (never|low|medium|high) и --provider — дополняют свои допустимые значения.
Локальный тест с несколькими провайдерами (Ollama)
docker-compose.yml запускает только dev-зависимость — локальный экземпляр Ollama для тестирования мультипровайдерного LLM-клиента (gitl сам не контейнеризирован):
docker compose up ollamaRelated MCP server: grippy-code-review
Конфигурация
Быстрый путь: gitl init записывает стартовый .gitl.yaml с комментариями в корень репозитория (отказываясь перезаписывать существующий без --force; --output записывает в другое место). Отредактируйте его вместо копирования из этого раздела — остальное ниже является полным справочником.
Два уровня, объединяются по приоритету:
флаг > env > .gitl.yaml (репозиторий) > ~/.config/gitl/config.yaml (личный).
Репозиторный .gitl.yaml коммитится как общая командная политика (порог риска, исключённые пути, категории журнала изменений). Без ключа gitl работает в детерминированном офлайн-режиме.
В офлайн-режиме — или когда реальная модель пропускает валидный блок риска и gitl откатывается к эвристике — заголовок риска помечается *(heuristic)* (и "heuristic": true в --format=json), чтобы детерминированная оценка никогда не принималась за собственное суждение модели.
Провайдеры (llm.provider)
# OpenAI-compatible API (default)
llm:
provider: "openai"
api_key: "" # or env GITL_API_KEY
base_url: "https://api.openai.com/v1"
model: "gpt-4o-mini"
# Ollama — local/self-hosted, no key, free
llm:
provider: "ollama"
base_url: "http://localhost:11434/v1"
model: "llama3.1"
# Azure OpenAI — custom auth/endpoint format
llm:
provider: "azure_openai"
api_key: "" # or env GITL_API_KEY
model: "gpt-4o-mini" # used only for cost estimation
azure_openai:
endpoint: "https://<resource>.openai.azure.com"
deployment: "<deployment-name>"
api_version: "2024-08-01-preview"
# Anthropic (native Claude Messages API)
llm:
provider: "anthropic"
api_key: "" # or env GITL_API_KEY
model: "claude-sonnet-4-6"
# base_url optional; defaults to https://api.anthropic.com
# Google Gemini (Google AI Studio)
llm:
provider: "gemini"
api_key: "" # or env GITL_API_KEY
model: "gemini-2.5-flash"
# base_url optional; defaults to https://generativelanguage.googleapis.com/v1betaПотоковая передача (output.stream)
При интерактивном ревью (md или text формат на TTY) gitl передаёт токены в терминал по мере их поступления — без ожидания полного ответа. Потоковая передача включена по умолчанию и автоматически отключается в CI (stdout не TTY), при --format=json и при настройке пользовательского output.template_file (шаблону нужен полный ответ, поэтому ревью буферизуется и рендерится через него).
Потоковая передача в настоящее время реализована только для OpenAI-совместимого провайдера (openai / ollama / azure_openai). С нативным провайдером anthropic или gemini gitl прозрачно выдаёт то же ревью как единый буферизованный ответ (без посимвольного вывода) независимо от output.stream / --no-stream.
output:
stream: true # default; set false to always bufferОтключить для одного вызова: gitl review HEAD~5..HEAD --no-stream
Цвет (output.color)
На интерактивном терминале gitl review раскрашивает уровень риска в заголовке (HIGH красным, MEDIUM жёлтым, LOW зелёным). Цвет автоматически отключается, когда stdout не является TTY (пайпы, логи CI), и никогда не появляется в выводе --format=json. Приоритет, от высшего к низшему:
Установлена переменная окружения
NO_COLOR(любое значение, даже пустое) — цвет выключен (no-color.org);output.color: falseв конфиге (илиGITL_OUTPUT_COLOR=false) — цвет выключен;stdout не является TTY — цвет выключен;
в противном случае — цвет включён.
output:
color: true # default; set false to disable ANSI colorТихий режим (output.quiet)
Без API-ключа review выводит информационное уведомление "using deterministic offline review" в stderr при каждом запуске (а changelog --ai выводит аналогичное уведомление об откате). В заведомо офлайн-контекстах — особенно в pre-commit hook, который срабатывает при каждом коммите — этот баннер является шумом. Подавите его любым из способов (каждый слой может независимо включить подавление):
флаг
--quietдляreview/changelog;установленная переменная окружения
GITL_QUIET(любое значение, даже пустое);output.quiet: trueв конфиге (илиGITL_OUTPUT_QUIET=true).
--quiet подавляет только информационный баннер: ошибки, отрендеренное ревью/журнал изменений на stdout и гейт --fail-on никогда не затрагиваются.
output:
quiet: false # default; set true to suppress the offline noticesКэш ответов LLM (cache)
gitl review кэширует ответы модели на диске (SHA-256 от провайдера + модели + промпта). Идентичные диффы мгновенно используют кэшированный результат без вызова API и затрат.
cache:
enabled: true # default
ttl_hours: 24 # entries older than this are ignoredКэш хранится в ~/.cache/gitl/review/ (совместимо с XDG). Отключить для одного вызова: gitl review HEAD~5..HEAD --no-cache
В --format=json каждый артефакт ревью несёт аддитивные метаданные запуска (schema_version остаётся 1; потребители, созданные до этого, видят тот же документ плюс два новых ключа):
{
"duration_ms": 1234,
"cache": { "hit": true, "tier": "local" }
}duration_ms— время всего запуска ревью в миллисекундах (попадание в кэш всё равно сообщает реальное, обычно крошечное число).cache.hit— было ли это ревью обслужено из кэша ответов LLM вместо свежего вызова модели.cache.tier— топология кэша, действующая для запуска:none(офлайн-режим,--no-cache,cache.enabled: falseилиttl_hours <= 0),local(только диск) илиtiered(диск + удалённый). Сообщает сконфигурированный режим, а не то, какой бэкенд обслужил конкретное попадание.
Намеренно нет поля usage (количество токенов): gitl не парсит использование провайдера из ответов, и постоянно пустое поле было бы хуже, чем отсутствующее. Оно будет добавлено — аддитивно, без изменения схемы — когда появится парсинг использования.
Общий удалённый кэш (cache.remote) — opt-in
Opt-in, выключен по умолчанию, BYO-бэкенд: gitl никогда не хостит сервис и не делает сетевых запросов к какому-либо кэшу, пока вы его не настроите. Полезно для холодных стартов CI — каждый раннер начинает с пустого диска, но общая HTTP KV-конечная точка позволяет одному раннеру переиспользовать ревью другого для того же диффа.
cache:
enabled: true
ttl_hours: 24
remote: # opt-in shared cache for CI cold starts (off by default)
url: https://cache.example.com/gitl # your endpoint; gitl hosts nothing
token_env: GITL_REMOTE_CACHE_TOKEN # env var holding an optional bearer token
timeout_ms: 3000При настройке локальный дисковый кэш остаётся первым уровнем: чтение проверяет диск, затем удалённый (попадание в удалённый кэш записывается на диск); запись идёт в оба.
Протокол — простое хранилище ключ-значение по HTTP — подойдёт любой статический объектный стор или крошечный обработчик:
GET {url}/{key}→200с телом JSON-записи, или404= промах. Любой другой статус, сетевая ошибка или таймаут считаются промахом.PUT {url}/{key}с JSON-записью в теле запроса (Content-Type: application/json) → любой2xx= сохранено.Если
token_envуказывает на переменную окружения с непустым значением, оба запроса несутAuthorization: Bearer <token>. Сам токен никогда не читается из файла конфигурации (та же дисциплина, что иGITL_API_KEY).Ключи — 64-символьные hex-строки SHA-256; значения непрозрачны для сервера.
Контракт безопасности: любой удалённый сбой (таймаут, 5xx, недоступная конечная точка) молча деградирует до локального кэша / без кэша — он никогда не приводит к сбою ревью. Хранимые записи содержат только ответ модели, ключ — непрозрачный хэш: ни дифф, ни текст промпта никогда не попадают в удалённый кэш. Записи старше ttl_hours игнорируются на стороне клиента независимо от того, что возвращает сервер.
Тренд риска (policy.risk_log_enabled)
Каждый запуск gitl review добавляет свой результат риска (уровень, диапазон, провайдер, временная метка) в локальный JSONL-лог: $XDG_DATA_HOME/gitl/risk-history.jsonl (по умолчанию ~/.local/share/gitl/risk-history.jsonl; %AppData%\gitl\ на Windows). gitl digest читает его и показывает секцию "Risk trend (last N days)" для каждого репозитория — количество ревью по уровням, направление высокого риска (последняя половина окна против более ранней) и последние несколько ревью. В --format=json это появляется как опциональное поле risk_trend (schema_version остаётся 1; потребители, созданные до этого, видят тот же документ, что и раньше). Репозитории без истории просто опускают секцию.
Ревью соотносятся с репозиторием по URL удалённого origin (при отсутствии origin — по пути рабочей копии).
Ограничение: история локальна для вашей машины — она не сохраняется между раннерами CI (каждый начинает с холодного диска), поэтому тренд — это функция для локальной разработки, а не для CI.
Отказ в конфиге (без CLI-флага):
policy:
risk_log_enabled: falseПользовательские шаблоны (prompt.*_template_file / output.template_file)
Независимые переопределения только через конфиг (ни для одного из них нет CLI-флага):
prompt.system_template_file— ваш собственный системный промпт для ревью, чтобы направить фокус модели (чек-лист безопасности, архитектурные ограничения, командные правила). Используется толькоgitl review:prompt: system_template_file: "./review-policy.md" # path relative to CWDШаблон системного промпта ревью имеет доступ к
{{ .Commits }},{{ .Diff }},{{ .Range }},{{ .Staged }}(см.internal/prompt/templates.go).prompt.changelog_system_template_file— ваш собственный системный промпт для журнала изменений, используется толькоgitl changelog --ai:prompt: changelog_system_template_file: "./changelog-policy.md" # path relative to CWDШаблон системного промпта журнала изменений имеет доступ к
{{ .Commits }},{{ .Range }},{{ .Grouped }}— не{{ .Diff }}:changelog --aiработает с метаданными коммитов, диффа нет, и шаблон в форме ревью, использующий.Diff, здесь не сработает. Именно поэтому два ключа раздельны: каждая команда читает только свой ключ, и любой из них может быть установлен без другого.output.template_file— ваш собственный шаблон рендера в форматеmdдля готового артефакта ревью:output: template_file: "./review-output.tmpl" # path relative to CWDШаблон вывода имеет функции рендера из
internal/render/render.go(render.TemplateFuncs()).
Примечание о доверии: ключи
prompt.*_template_file/output.template_fileмогут быть установлены репозиторным.gitl.yaml, а не только вашим личным конфигом — поэтому запускgitl reviewпротив клонированного репозитория, которым вы не управляете, может указать на шаблон внутри того же репозитория. Это предполагаемый механизм для общей командной политики ревью, а не ошибка:text/templateздесь не может читать произвольные файлы или выполнять код, но относитесь к.gitl.yamlнедоверенного репозитория с той же осторожностью, что и к его.git/hooksили скриптам сборки.
GitHub Action
gitl можно подключить как GitHub Action: он ИИ-ревьюит коммиты pull request и публикует комментарий с оценкой риска, опционально блокируя слияние выше порога. Action собирает gitl из исходников (go install на закреплённой версии). Также доступен в GitHub Marketplace, если вы предпочитаете добавить его оттуда.
Добавьте .github/workflows/gitl-review.yml в ваш репозиторий:
name: gitl review
on:
pull_request:
permissions:
contents: read # for checkout
pull-requests: write # to post the review comment
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # required: without full history base..head won't resolve
- uses: akomyagin/gitl@v0.6.2
with:
gitl-api-key: ${{ secrets.GITL_API_KEY }} # BYOK, see below
fail-on: high # optional: block merge on high riskРекомендации по безопасности:
Ключ — только через
secrets.*.gitl-api-keyберётся изsecrets.GITL_API_KEY(задаётся в Settings → Secrets and variables → Actions) и никогда не захардкожен в YAML и не закоммичен. Если секрет не задан, Action работает в детерминированном offline-режиме (без сети, без затрат).Минимальные
permissions:. Нужны толькоpull-requests: write(для публикации комментария) иcontents: read(для checkout) — не выдавайте более широких прав.fetch-depth: 0обязателен. GitHub предоставляет SHA-хэшиbase/headв событииpull_request, но при shallow-клоне не получится разрешитьbase.sha..head.sha.fail-onпо умолчанию равенnever. Action только оставляет комментарий; он не блокирует merge, если вы явно не включите это (fail-on: highи т. п.) — тот же принцип «WARN по умолчанию, жёсткий гейт — явный opt-in», что и в CLI (--fail-on). Когда гейт срабатывает, job завершается с кодом выхода gitl2(risk gate) — настоящая ошибка инструмента завершается с кодом1, так что downstream-шаги могут отличить «рискованное изменение» от «gitl сломался».Конфиденциальность диффа. В CI дифф отправляется тому LLM-провайдеру, который настроен (по умолчанию: OpenAI-совместимый API). Для приватного кода используйте self-hosted/enterprise-провайдера (Ollama, Azure OpenAI) — см. Providers выше.
Выбор провайдера. По умолчанию Action использует провайдера из вашего конфига (OpenAI-совместимый, если не задан). Чтобы нацелиться на нативного провайдера, передайте
provider:(openai|ollama|azure_openai|anthropic|gemini), и опциональноmodel:иbase-url:, вместе сgitl-api-key:. Все три параметра необязательны и, если опущены, подхватываются из вашего.gitl.yaml/личного конфига и встроенных умолчаний gitl — см. Providers выше. Пример:provider: anthropicс ключом Claude вsecrets.GITL_API_KEY.Маскирование секретов. GitHub автоматически маскирует значения
secrets.*в логах runner'а как***, но это не повод печатать ключ в собственных шагах workflow.
Сводка рисков в описании PR (opt-in)
С update-pr-description: true (по умолчанию false) Action дополнительно поддерживает
компактный блок сводки рисков в конце описания PR — строку риска плюс
ссылку на полный комментарий ревью, обновляемую при каждом запуске:
- uses: akomyagin/gitl@v0.6.2
with:
gitl-api-key: ${{ secrets.GITL_API_KEY }}
update-pr-description: trueЭто opt-in, потому что редактирование описания PR более интрузивно, чем sticky-комментарий;
дополнительные права не нужны — pull-requests: write, уже требуемое для
комментария, покрывает и тело PR. Блок ограничен парой маркеров
<!-- gitl-review-summary -->, и заменяется только текст между маркерами —
всё, что вы пишете вне их, никогда не затрагивается. Пока только для GitHub
(игнорируется в Gitea Actions).
Gitea Actions (экспериментально)
Тот же action.yml работает и в Gitea Actions —
runner Gitea исполняет GitHub-совместимые composite-actions, и action gitl определяет
платформу во время выполнения по переменной GITEA_ACTIONS=true, которую act_runner
Gitea внедряет в каждый job. Единственная платформо-зависимая часть — публикация sticky-комментария
к PR — идёт через REST API Gitea
(POST/PATCH /api/v1/repos/{owner}/{repo}/issues/...) с помощью curl вместо
CLI gh, который говорит только с API GitHub. Пользователи GitHub не затронуты: без
GITEA_ACTIONS action ведёт себя ровно как раньше.
Добавьте .gitea/workflows/gitl-review.yml в ваш репозиторий (полный пример с комментариями:
.gitea/workflows/gitl-review.yml в этом репозитории):
name: gitl review
on:
pull_request:
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: https://github.com/actions/checkout@v7
with:
fetch-depth: 0
- uses: https://github.com/akomyagin/gitl@v0.6.2
with:
gitl-api-key: ${{ secrets.GITL_API_KEY }} # BYOK; omit for offline modeТребования: включённые Actions, свежий act_runner (с поддержкой node24) и образ runner'а
с bash, git, curl, jq и node. GITL_API_KEY кладётся в
секреты Actions Gitea, никогда в YAML — те же правила BYOK, что и на GitHub.
Статус проверки — прочтите, прежде чем полагаться на это. REST-вызовы на
curl(список комментариев, create, patch, sticky-детекция) были прогнаны против реального инстанса Gitea (gitea/giteaв Docker) end-to-end — list-empty → POST-create → re-list-finds-it → PATCH-update → по-прежнему ровно один комментарий. Эта часть работает как написано. Что ещё не проверено — окружающий CI-контекстact_runner: выглядят лиGITEA_ACTIONS/GITHUB_API_URL/payload события PR ровно так, как предполагается, внутри живого запуска workflow (это сверялось с исходниками Gitea/ act_runner/act-fork, а не прогонялось внутри реального job). Относитесь к CI-триггерному пути как к экспериментальному, пока кто-нибудь не подтвердит зелёный прогон end-to-end в настоящих Gitea Actions; баг-репорты с реальных инстансов очень приветствуются.
GitLab CI (экспериментально)
gitl также поставляет компонент GitLab CI/CD —
templates/gitl-review.yml — зеркало GitHub Action:
он устанавливает gitl через go install на закреплённой версии, ревьюит диапазон
merge request'а ($CI_MERGE_REQUEST_DIFF_BASE_SHA..$CI_COMMIT_SHA), рендерит комментарий через
общий платформо-нейтральный ci/comment.sh и создаёт/обновляет
sticky-заметку MR через REST API GitLab (тот же маркер <!-- gitl-review -->, что и на
GitHub/Gitea). Job выполняется только в пайплайнах merge request.
Компонент опубликован в каталоге GitLab CI/CD
через зеркало этого репозитория, обновляемое при релизах, по адресу
gitlab.com/alkom68/gitl (одностороннее GitHub → GitLab,
пушится на каждый релизный тег). На gitlab.com подключайте его как компонент каталога:
# .gitlab-ci.yml (gitlab.com)
include:
- component: gitlab.com/alkom68/gitl/gitl-review@v0.6.2
inputs:
fail_on: "never" # default; set "high" to block risky MRs
# max_cost_usd: "0.50"
# gitl_version: "v0.6.2"На self-hosted-инстансе GitLab include:component разрешает компоненты только
с того же инстанса — потребляйте шаблон через include:remote напрямую с
GitHub (inputs работают и с remote-подключением):
# .gitlab-ci.yml (self-hosted GitLab)
include:
- remote: "https://raw.githubusercontent.com/akomyagin/gitl/v0.6.2/templates/gitl-review.yml"
inputs:
fail_on: "never"Настройка — две переменные CI/CD (Settings → CI/CD → Variables, обе masked, никогда в YAML):
GITL_API_KEY— BYOK-ключ LLM. Необязателен: без него gitl выполняет детерминированное offline-ревью (без сети, без затрат). Достаточно определить переменную проекта — она имеет приоритет над пустым умолчанием input'аgitl_api_keyкомпонента. Если используете input, передавайте ссылку на переменную (gitl_api_key: $MY_LLM_KEY), никогда не литеральное значение ключа: значения input'ов интерполируются в конфиг пайплайна.GITL_GITLAB_TOKEN— токен для публикации заметки MR (project access token или PAT, скоупapi, роль Reporter или выше; отправляется какPRIVATE-TOKEN). Если не задан, job откатывается наCI_JOB_TOKEN(заголовокJOB-TOKEN) — но в большинстве конфигураций GitLabCI_JOB_TOKENне авторизован для Notes API, так что откат, как ожидается, завершится ошибкой (с явным сообщением, а не тихим пропуском). ЯвныйGITL_GITLAB_TOKEN— надёжный путь.
Полный самопроверочный пайплайн с комментариями — он же ближайший аналог полного примера
использования — это .gitlab-ci-selftest.yml (запускается как
.gitlab-ci.yml в зеркале этого репозитория на GitLab).
Статус проверки — прочтите, прежде чем полагаться на это. REST-вызовы GitLab (список заметок MR + sticky-маркер-детекция,
POSTcreate,PUTupdate) и сам YAML компонента (spec:/inputs:-интерполяция,include:localс inputs, через CI Lint API) были проверены end-to-end против реального локального инстанса GitLab CE (gitlab/gitlab-ce19.2.0 в Docker) на настоящем merge request — list-empty → POST-create → re-list-finds-it → PUT-update → по-прежнему ровно одна заметка — с использованием ровно тех командcurl/jq, что в шаблоне. Что ещё не проверено — живой прогон пайплайна: значенияCI_MERGE_REQUEST_DIFF_BASE_SHA/CI_COMMIT_SHA/CI_JOB_URLвнутри реального пайплайна merge request взяты из документации GitLab, а не наблюдены, а отклонение отката наCI_JOB_TOKENописано по документации GitLab об allowlist job-токенов, а не воспроизведено. Относитесь к пайплайн-пути как к экспериментальному, пока кто-нибудь не подтвердит зелёный end-to-end прогон; баг-репорты приветствуются.
Заметка о доверии. Компонент скачивает
ci/comment.shиз зеркала GitLab (gitlab.com/alkom68/gitl) на версииgitl_versionи исполняет его — без проверки контрольной суммы/подписи, та же граница доверия, что и у строкиgo install ...@${gitl_version}прямо над ней (тот же репозиторий, тот же ref). Эта загрузка происходит независимо от того, как подключён компонент — Catalog илиinclude:remote— потому что подключение компонента доставляет только YAML-шаблон, а не файлы репозитория компонента, так что загрузку нельзя обойти механически. Скачивание с того же инстанса GitLab, который публикует компонент (а не с GitHub), сохраняет тот же namespace/ref — более честная модель доверия, чем кросс-хостовое скачивание. Если это важно для вашей threat model, закрепитеgitl_versionна SHA коммита, а не на теге (теги перемещаемы).
Bitbucket Pipelines (экспериментально)
Интеграция с Bitbucket поставляется как Pipe —
а pipes по определению являются Docker-образами, так что, в отличие от action для GitHub/Gitea и
компонента GitLab (обычные YAML-обёртки), это самодостаточный образ:
bitbucket-pipe/Dockerfile собирает статический бинарник
gitl и встраивает общий рендерер ci/comment.sh плюс
entrypoint bitbucket-pipe/pipe.sh. Pipe вычисляет
диапазон PR ($BITBUCKET_PR_DESTINATION_COMMIT..$BITBUCKET_COMMIT), запускает
gitl review --format=json и создаёт/обновляет sticky-комментарий PR через
REST API Bitbucket Cloud (тот же маркер <!-- gitl-review -->, что и на других
платформах). Справочник переменных: bitbucket-pipe/pipe.yml.
Статус образа. Опубликован на Docker Hub как
alkom68/gitl-review-pipeначиная сv0.5.2— jobdocker-publishрелизного workflow пушит:<version>и:latestна каждый релизный тег. В реестре существуют только0.5.2и новее: более ранние релизы предшествуют публикации (теги0.5.0/0.5.1никогда не пушились), так что не закрепляйте их.
# bitbucket-pipelines.yml
pipelines:
pull-requests:
'**':
- step:
name: gitl review
clone:
depth: full # the default depth-50 clone may not contain the PR base commit
script:
- pipe: docker://alkom68/gitl-review-pipe:0.6.2
variables:
GITL_API_KEY: $GITL_API_KEY # BYOK; omit for offline review
GITL_BITBUCKET_TOKEN: $GITL_BITBUCKET_TOKEN # posts the PR comment
# FAIL_ON: "high" # default "never" — comment only, no gate
# MAX_COST_USD: "0.50"Настройка — две защищённые переменные репозитория/workspace (Repository settings →
Pipelines → Repository variables; всегда ссылайтесь как $VAR, никогда не литеральными значениями
в YAML):
GITL_API_KEY— BYOK-ключ LLM. Необязателен: без него gitl выполняет детерминированное offline-ревью (без сети, без затрат).GITL_BITBUCKET_TOKEN— учётные данные для публикации комментария PR: access token репозитория/проекта/workspace со скоупомpullrequest:write, отправляемый какAuthorization: Bearer. Альтернатива: задайтеGITL_BITBUCKET_USER+GITL_BITBUCKET_APP_PASSWORD(app password со скоупомpullrequest:write) для Basic-аутентификации. Если не настроено ни то ни другое, pipe быстро завершается с явным сообщением — до траты любого LLM-бюджета.
Заметка о цепочке поставок (почему это отличается от компонента GitLab). Pipe не исполняет ничего, скачанного во время выполнения: бинарник
gitl,ci/comment.shи entrypoint встроены в версионированный образ из одного дерева исходников. Компоненту GitLab приходится скачиватьci/comment.shпо сети без проверки целостности (см. его заметку о доверии выше); pipe закрывает этот пробел по построению.
Статус проверки — прочтите, прежде чем полагаться на это. Сборка образа и полный внутриконтейнерный поток были проверены локально:
docker buildиз этого репозитория, затемdocker runна реальном тестовом git-репозитории с эмулированными переменнымиBITBUCKET_*— офлайн-ревью → корректный stickycomment.md→ создание комментария (POST), sticky-обновление (PUT, по-прежнему ровно один комментарий) и распространение кода выхода--fail-on, проверенные end-to-end на локальном моке API комментариев Bitbucket; fail-fast пути (отсутствующие переменные учётных данных/PR) и запасное уведомление на плохом диапазоне также были проверены в контейнере. Что ещё не проверено: всё, что касается реальной инфраструктуры Bitbucket — REST-вызовы к api.bitbucket.org (формы взяты из документации Atlassian API), точные предопределённые переменные внутри живого PR-пайплайна (BITBUCKET_PR_DESTINATION_COMMITи т.д. — документированные предположения, а не наблюдаемые значения), и то, как Pipelines монтирует клон в pipe-контейнеры. Относитесь к пути живого пайплайна как к экспериментальному, пока кто-нибудь не подтвердит зелёный прогон на реальном Bitbucket-воркспейсе; баг-репорты приветствуются.
Pre-commit хук (локально)
gitl поставляется с хуком фреймворка pre-commit, так что
gitl review --staged --quiet запускается автоматически перед каждым коммитом — локально,
офлайн и бесплатно по умолчанию (--quiet включён по умолчанию в манифесте хука, поэтому
офлайн-уведомление не печатается при каждом коммите).
Добавьте в .pre-commit-config.yaml вашего репозитория:
repos:
- repo: https://github.com/akomyagin/gitl
rev: v0.6.2 # pin to a released tag
hooks:
- id: gitl-reviewзатем выполните pre-commit install. Фреймворк сам собирает бинарник gitl
(language: golang) и кэширует окружение в ~/.cache/pre-commit/, так что
стоимость сборки оплачивается один раз, а не при каждом коммите.
Чтобы включить блокирующий хук с ограничением стоимости:
hooks:
- id: gitl-review
args: [--fail-on=high, --max-cost-usd=0.05] # opt-in: block on high risk, cap costЭкспортируйте GITL_API_KEY в вашем окружении для реального AI-ревью; без него
хук выполняет детерминированное офлайн-ревью (без сети, без затрат).
Что нужно знать:
Офлайн по умолчанию. Без API-ключа, без сети, без затрат на коммит. Установите
GITL_API_KEY, чтобы включить реальное AI-ревью.Неблокирующий по умолчанию. Хук выводит ревью, но не проваливает коммит — тот же принцип «WARN по умолчанию, жёсткий шлюз — явное согласие», что и в CLI/Action. Добавьте
args: [--fail-on=high]для блокировки.Задержка. Реальное API-ревью занимает несколько секунд; держите его вне горячего пути, оставив офлайн, или ограничьте с помощью
--max-cost-usd.Конфиденциальность диффа. С реальным ключом staged-дифф уходит вашему настроенному LLM-провайдеру — для приватного кода используйте self-hosted/enterprise-провайдера (Ollama, Azure OpenAI), см. Providers выше.
Подавление офлайн-уведомления. Манифест передаёт
--quietпо умолчанию, поэтому уведомление «using deterministic offline review» в stderr при каждом коммите замалчивается; тот же переключатель доступен вreview/changelogкак--quiet/GITL_QUIET, или на уровне репозитория черезoutput.quiet: true(MCP-сервер учитывает толькоoutput.quiet/GITL_OUTPUT_QUIET— у него нет флагов, поэтому короткий алиасGITL_QUIETтам не работает). Ошибки и сам вывод ревью не затрагиваются.
Без фреймворка pre-commit
Подойдёт и обычный git-хук:
# .git/hooks/pre-commit (chmod +x)
#!/usr/bin/env bash
set -euo pipefail
# Offline, non-blocking review of staged changes (WARN by default); --quiet
# suppresses the per-commit offline notice on stderr.
gitl review --staged --quiet || true
# To block the commit on high risk instead, replace the line above with:
# gitl review --staged --quiet --fail-on=highMCP-сервер
gitl mcp запускает gitl как stdio-сервер Model Context Protocol —
отдельный дополнительный канал по сравнению с использованием CLI/CI выше, для интерактивного
использования gitl внутри агентской сессии (Claude Desktop, Cursor, Windsurf и т.д.) вместо
вызова из командной строки. Он предоставляет два инструмента:
gitl_review— тот же движок ревью, что иgitl review:range/pr/staged(ровно один), опциональное переопределениеmodelна каждый вызов. Провайдер и endpoint фиксируются при запуске сервера по замыслу: вызывающий инструмент — это AI-агент, которым можно управлять через prompt injection внутри ревьюируемого содержимого — per-callbase_urlпозволил бы вредоносному коммиту перенаправить запрос и утечь реальный API-ключ. Всегда возвращает структурированный JSON-артефакт (без md/text-рендеринга, без стриминга — результат инструмента атомарен).risk.levelвозвращается как данные; в MCP-режиме нет--fail-on, поскольку нет кода выхода процесса, который можно было бы шлюзовать.gitl_digest— то же, чтоgitl digest:days(по умолчанию 7), опциональныйrepos. Без явного аргументаreposинструмент обрабатывает только рабочую директорию сервера (плюсdigest.reposиз.gitl.yaml, если настроено) — он никогда не обходит произвольные пути по собственной инициативе. Явный аргументreposучитывается как есть (вызывающий агент уже имеет доступ к файловой системе через свои инструменты; это не граница контроля доступа, а просто дефолт «не удивляй пользователя»).
Добавьте в конфиг вашего MCP-клиента (Claude Desktop, Cursor и т.д.):
{
"mcpServers": {
"gitl": {
"command": "gitl",
"args": ["mcp"]
}
}
}Конфиг загружается один раз при запуске так же, как и для обычных команд
(.gitl.yaml + личный конфиг + переменные окружения GITL_*, из директории, в
которой запущен gitl mcp). Без ключа вызовы инструментов работают в том же
детерминированном офлайн-режиме, что и CLI. stdout зарезервирован под протокол
MCP — туда никогда не пишется ничего человекочитаемого; предупреждения идут в
stderr.
Лицензия
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
AI-native git hosting — repos, PRs, issues, CI gates, and AI code review over MCP (60 tools).
Team memory for AI coding agents and code reviews, reviewed by humans and served over MCP.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Related MCP Servers
- AlicenseAqualityCmaintenanceA local Git intelligence MCP server that provides deep repository analytics including hotspots, temporal coupling, knowledge maps, churn analysis, and risk scoring for AI agents.1212MIT
- AlicenseNot gradedqualityCmaintenanceOpen-source AI code review MCP server for local git diff auditing with deterministic security rules and AI-powered analysis using any OpenAI-compatible model.4MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for automated code review using AI agents. It analyzes code diffs or file paths for bugs, security issues, and style violations.MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for AI code provenance, enabling traceability of file changes to AI agents, sessions, and prompts, plus reporting on AI-generated code activity.2 npmMIT