Skip to main content
Glama

gitl

Action self-test

ИИ-ревьюер истории 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 ollama

Related 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. Приоритет, от высшего к низшему:

  1. Установлена переменная окружения NO_COLOR (любое значение, даже пустое) — цвет выключен (no-color.org);

  2. output.color: false в конфиге (или GITL_OUTPUT_COLOR=false) — цвет выключен;

  3. stdout не является TTY — цвет выключен;

  4. в противном случае — цвет включён.

output:
  color: true   # default; set false to disable ANSI color

Тихий режим (output.quiet)

Без API-ключа review выводит информационное уведомление "using deterministic offline review" в stderr при каждом запуске (а changelog --ai выводит аналогичное уведомление об откате). В заведомо офлайн-контекстах — особенно в pre-commit hook, который срабатывает при каждом коммите — этот баннер является шумом. Подавите его любым из способов (каждый слой может независимо включить подавление):

  1. флаг --quiet для review / changelog;

  2. установленная переменная окружения GITL_QUIET (любое значение, даже пустое);

  3. 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 завершается с кодом выхода gitl 2 (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/CDtemplates/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) — но в большинстве конфигураций GitLab CI_JOB_TOKEN не авторизован для Notes API, так что откат, как ожидается, завершится ошибкой (с явным сообщением, а не тихим пропуском). Явный GITL_GITLAB_TOKEN — надёжный путь.

Полный самопроверочный пайплайн с комментариями — он же ближайший аналог полного примера использования — это .gitlab-ci-selftest.yml (запускается как .gitlab-ci.yml в зеркале этого репозитория на GitLab).

Статус проверки — прочтите, прежде чем полагаться на это. REST-вызовы GitLab (список заметок MR + sticky-маркер-детекция, POST create, PUT update) и сам YAML компонента (spec:/inputs:-интерполяция, include:local с inputs, через CI Lint API) были проверены end-to-end против реального локального инстанса GitLab CE (gitlab/gitlab-ce 19.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 — job docker-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_* — офлайн-ревью → корректный sticky comment.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=high

MCP-сервер

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-call base_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.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/akomyagin/gitl'

If you have feedback or need assistance with the MCP directory API, please join our Discord server