Skip to main content
Glama

gitl

Action self-test

KI-gestützter Git-Historie-Reviewer für CLI und CI. gitl (git-log-lens) liest die Git-Historie eines Repositorys und verwandelt sie per LLM in ein strukturiertes Engineering-Artefakt:

  • gitl review <range> — KI-Review eines Commit-Bereichs / PRs mit maschinenlesbarem Risiko-Scoring (low|medium|high) für CI-Gating (--fail-on=high → Exit-Code 2); streamt Tokens in Echtzeit ins Terminal; LLM-Antwort-Cache auf der Platte mit optionalem gemeinsam genutztem Remote-Cache für CI; benutzerdefinierte System-Prompt-Vorlagen; --staged reviewt gestaged (nicht committete) Änderungen vor git commit (auch als pre-commit hook verfügbar).

  • gitl changelog [<range>] — Keep-a-Changelog-konformes Changelog, gruppiert nach Conventional Commits (Standard: letzter Tag → HEAD); standardmäßig deterministisch, --ai schreibt es optional mit dem Modell als lesbare Release-Notes-Prosa neu;

  • gitl digest [--days=N] [--repos=a,b,c] — Aktivitätsübersicht nach Autor/Thema/Datei, einschließlich mehrerer Repositorys parallel; interaktiver TUI-Viewer (--tui).

Ein schlankes CLI-Binary plus ein GitHub-Action-Wrapper — kein Server, keine Datenbank, kein gehosteter Schlüsselspeicher. BYOK (bring your own key) mit Multi-Provider- Unterstützung: OpenAI-kompatible API, Ollama (lokal/self-hosted), Azure OpenAI, natives Anthropic (Claude), Google Gemini. Keine Telemetrie.

Status: v0.6.2 veröffentlicht — alle drei Befehle funktionieren mit echten Repositorys und allen drei Ausgabeformaten (md|text|json). Die Action postet KI-Reviews als sticky PR-Kommentare und gated auf den Risiko-Score. Release-Binaries sind cross-kompiliert, cosign-signiert und durch SLSA-L3-Build-Provenance abgedeckt (siehe VERIFY.md).

Schnellstart

Erfordert Go 1.22+ und git im 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 ./...

Installieren:

# 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)

Shell-Komplettierungen

gitl bringt cobra-generierte Komplettierungen für bash, zsh, fish und PowerShell mit.

Homebrew installiert bash/zsh/fish-Komplettierungen automatisch (Release-Archive enthalten sie ebenfalls unter completions/). Andernfalls bei Bedarf aktivieren:

# 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

Flags mit festen Wertemengen — --format (md|text|json), --fail-on (never|low|medium|high) und --provider — vervollständigen ihre erlaubten Werte.

Lokaler Multi-Provider-Test (Ollama)

docker-compose.yml startet nur die Dev-Abhängigkeit — eine lokale Ollama-Instanz zum Testen des Multi-Provider-LLM-Clients (gitl selbst ist nicht containerisiert):

docker compose up ollama

Related MCP server: grippy-code-review

Konfiguration

Der schnelle Weg: gitl init schreibt eine kommentierte Starter-.gitl.yaml in das Repo-Root (weigert sich, eine vorhandene ohne --force zu überschreiben; --output schreibt woanders hin). Bearbeiten Sie diese, statt aus diesem Abschnitt zu kopieren — der Rest unten ist die vollständige Referenz.

Zwei Ebenen, nach Priorität zusammengeführt: Flag > Env > .gitl.yaml (Repo) > ~/.config/gitl/config.yaml (persönlich). Die Repo-Ebene .gitl.yaml wird als gemeinsame Team-Policy committet (Risikoschwelle, ausgeschlossene Pfade, Changelog-Kategorien). Ohne Schlüssel läuft gitl im deterministischen Offline-Modus.

Im Offline-Modus — oder wenn ein echtes Modell einen gültigen Risikoblock auslässt und gitl auf die Heuristik zurückfällt — wird der Risiko-Header mit *(heuristic)* annotiert (und "heuristic": true in --format=json), sodass ein deterministischer Score nie mit dem eigenen Urteil eines Modells verwechselt wird.

Provider (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

Streaming (output.stream)

Bei interaktiven Reviews (md- oder text-Format auf einem TTY) streamt gitl Tokens ins Terminal, sobald sie eintreffen — kein Warten auf die vollständige Antwort. Streaming ist standardmäßig aktiviert und schaltet sich in CI automatisch ab (Non-TTY-Stdout), bei --format=json und wenn eine benutzerdefinierte output.template_file konfiguriert ist (die Vorlage benötigt die vollständige Antwort, daher wird das Review gepuffert und stattdessen durch sie gerendert).

Streaming ist derzeit nur für den OpenAI-kompatiblen Provider implementiert (openai / ollama / azure_openai). Beim nativen anthropic- oder gemini-Provider erzeugt gitl transparent dasselbe Review als einzelne gepufferte Antwort (keine Token-für-Token-Ausgabe), unabhängig von output.stream / --no-stream.

output:
  stream: true   # default; set false to always buffer

Pro Aufruf deaktivieren: gitl review HEAD~5..HEAD --no-stream

Farbe (output.color)

Auf einem interaktiven Terminal färbt gitl review die Risikostufe im Header ein (HIGH rot, MEDIUM gelb, LOW grün). Farbe schaltet sich automatisch ab, wenn stdout kein TTY ist (Pipes, CI-Logs), und erscheint nie in der --format=json-Ausgabe. Priorität, höchste zuerst:

  1. NO_COLOR-Umgebungsvariable gesetzt (beliebiger Wert, auch leer) — Farbe aus (no-color.org);

  2. output.color: false in der Konfiguration (oder GITL_OUTPUT_COLOR=false) — Farbe aus;

  3. stdout ist kein TTY — Farbe aus;

  4. andernfalls — Farbe an.

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

Quiet-Modus (output.quiet)

Ohne API-Schlüssel gibt review bei jedem Lauf einen informativen Hinweis "using deterministic offline review" auf stderr aus (und changelog --ai gibt einen analogen Fallback-Hinweis aus). In bekannten Offline-Kontexten — vor allem im pre-commit-Hook, der bei jedem Commit feuert — ist dieses Banner Rauschen. Unterdrücken Sie es mit einem der folgenden Mittel (jede Ebene kann die Unterdrückung unabhängig einschalten):

  1. das --quiet-Flag bei review / changelog;

  2. die GITL_QUIET-Umgebungsvariable gesetzt (beliebiger Wert, auch leer);

  3. output.quiet: true in der Konfiguration (oder GITL_OUTPUT_QUIET=true).

--quiet unterdrückt nur das informative Banner: Fehler, das gerenderte Review/Changelog auf stdout und das --fail-on-Gate sind nie betroffen.

output:
  quiet: false   # default; set true to suppress the offline notices

LLM-Antwort-Cache (cache)

gitl review cached Modellantworten auf der Platte (SHA-256 von Provider + Modell + Prompt). Identische Diffs verwenden das gecachte Ergebnis sofort wieder, ohne API-Aufruf und ohne Kosten.

cache:
  enabled: true    # default
  ttl_hours: 24    # entries older than this are ignored

Der Cache liegt in ~/.cache/gitl/review/ (XDG-konform). Pro Aufruf deaktivieren: gitl review HEAD~5..HEAD --no-cache

In --format=json trägt jedes Review-Artefakt zusätzliche Laufzeit-Metadaten (schema_version bleibt 1; Konsumenten, die es vorher gab, sehen dasselbe Dokument plus zwei neue Schlüssel):

{
  "duration_ms": 1234,
  "cache": { "hit": true, "tier": "local" }
}
  • duration_ms — Wanduhrzeit des gesamten Review-Laufs in Millisekunden (ein Cache-Hit meldet trotzdem eine echte, meist winzige Zahl).

  • cache.hit — ob dieses Review aus dem LLM-Antwort-Cache bedient wurde statt aus einem frischen Modellaufruf.

  • cache.tier — die für den Lauf wirksame Cache-Topologie: none (Offline-Modus, --no-cache, cache.enabled: false oder ttl_hours <= 0), local (nur Platte) oder tiered (Platte + Remote). Es meldet den konfigurierten Modus, nicht welches Backend einen bestimmten Treffer bedient hat.

Es gibt bewusst noch kein usage-Feld (Token-Zahlen): gitl parst keine Provider-Nutzung aus Antworten, und ein dauerhaft leeres Feld wäre schlechter als ein fehlendes. Es wird hinzugefügt — additiv, ohne Schema-Bump — wenn das Usage-Parsing Einzug hält.

Gemeinsamer Remote-Cache (cache.remote) — Opt-in

Opt-in, standardmäßig aus, BYO-Backend: gitl hostet nie einen Dienst und macht keine Netzwerkanfrage an irgendeinen Cache, bis Sie einen konfigurieren. Nützlich für CI-Kaltstarts — jeder Runner startet mit leerer Platte, aber ein gemeinsamer HTTP-KV-Endpunkt lässt einen Runner das Review eines anderen für denselben Diff wiederverwenden.

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

Wenn konfiguriert, bleibt der lokale Platten-Cache die erste Stufe: Lesezugriffe prüfen zuerst die Platte, dann den Remote (ein Remote-Treffer wird auf die Platte zurückgeschrieben); Schreibzugriffe gehen an beide.

Das Protokoll ist ein simpler Key-Value-Store über HTTP — jeder statische Objektspeicher oder winzige Handler funktioniert:

  • GET {url}/{key}200 mit dem JSON-Eintrag als Body, oder 404 = Miss. Jeder andere Status, Netzwerkfehler oder Timeout wird als Miss behandelt.

  • PUT {url}/{key} mit dem JSON-Eintrag als Request-Body (Content-Type: application/json) → jedes 2xx = gespeichert.

  • Wenn token_env eine Env-Variable mit nicht-leerem Wert benennt, tragen beide Requests Authorization: Bearer <token>. Das Token selbst wird nie aus einer Konfigurationsdatei gelesen (gleiche Disziplin wie bei GITL_API_KEY).

  • Schlüssel sind 64-stellige hexadezimale SHA-256-Strings; Werte sind für den Server opak.

Sicherheitsvertrag: jeder Remote-Fehler (Timeout, 5xx, unerreichbarer Endpunkt) degradiert still auf den lokalen Cache / keinen Cache — er lässt das Review nie fehlschlagen. Die gespeicherten Einträge enthalten nur die Antwort des Modells, schlüssig über einen opaken Hash: kein Diff und kein Prompt-Text erreichen je den Remote-Cache. Einträge älter als ttl_hours werden clientseitig ignoriert, egal was der Server zurückgibt.

Risikotrend (policy.risk_log_enabled)

Jeder gitl review-Lauf hängt sein Risikoergebnis (Stufe, Bereich, Provider, Zeitstempel) an ein lokales JSONL-Log an: $XDG_DATA_HOME/gitl/risk-history.jsonl (Standard ~/.local/share/gitl/risk-history.jsonl; %AppData%\gitl\ unter Windows). gitl digest liest es zurück und zeigt einen pro-Repo-Abschnitt **"Risk trend (last N days)"** — Review-Anzahl nach Stufe, Hochrisiko-Richtung (jüngere Hälfte vs. ältere Hälfte des Fensters) und die letzten Reviews. In --format=json erscheint es als optionales risk_trend-Feld (schema_version bleibt 1; Konsumenten, die es vorher gab, sehen dasselbe Dokument wie zuvor). Repos ohne Historie lassen den Abschnitt einfach weg.

Reviews werden über die origin-Remote-URL einem Repository zugeordnet (Fallback auf den Worktree-Pfad, wenn es kein origin gibt).

Einschränkung: die Historie ist lokal auf Ihrer Maschine — sie überdauert keine CI-Runner (jeder startet mit kalter Platte), der Trend ist also ein Feature für lokale Entwicklungsnutzung, nicht für CI.

In der Konfiguration abwählen (kein CLI-Flag):

policy:
  risk_log_enabled: false

Benutzerdefinierte Vorlagen (prompt.*_template_file / output.template_file)

Unabhängige, nur über die Konfiguration verfügbare Überschreibungen (es gibt kein CLI-Flag für eine davon):

  • prompt.system_template_file — Ihr eigener Review-System-Prompt, um den Fokus des Modells zu steuern (Sicherheits-Checkliste, Architektur-Constraints, Teamregeln). Wird nur von gitl review verwendet:

    prompt:
      system_template_file: "./review-policy.md"   # path relative to CWD

    Die Review-System-Prompt-Vorlage hat Zugriff auf {{ .Commits }}, {{ .Diff }}, {{ .Range }}, {{ .Staged }} (siehe internal/prompt/templates.go).

  • prompt.changelog_system_template_file — Ihr eigener Changelog-System-Prompt, wird nur von gitl changelog --ai verwendet:

    prompt:
      changelog_system_template_file: "./changelog-policy.md"   # path relative to CWD

    Die Changelog-System-Prompt-Vorlage hat Zugriff auf {{ .Commits }}, {{ .Range }}, {{ .Grouped }}nicht {{ .Diff }}: changelog --ai arbeitet mit Commit-Metadaten, es gibt keinen Diff, und eine review-förmige Vorlage, die .Diff verwendet, würde hier fehlschlagen. Genau deshalb sind die beiden Schlüssel getrennt: jeder Befehl liest nur seinen eigenen Schlüssel, und jeder kann ohne den anderen gesetzt sein.

  • output.template_file — Ihre eigene md-Format-Render-Vorlage für das fertige Review-Artefakt:

    output:
      template_file: "./review-output.tmpl"   # path relative to CWD

    Die Ausgabevorlage hat die Render-Template-Funktionen in internal/render/render.go (render.TemplateFuncs()).

Vertrauenshinweis: die Schlüssel prompt.*_template_file/output.template_file können von einer Repo-Ebene-.gitl.yaml gesetzt werden, nicht nur von Ihrer persönlichen Konfiguration — ein gitl review gegen ein geklontes Repository, das Sie nicht kontrollieren, kann es also auf eine Vorlage innerhalb desselben Repositorys zeigen lassen. Das ist der beabsichtigte Mechanismus für eine gemeinsame Review-Policy eines Teams, kein Bug: text/template kann hier keine beliebigen Dateien lesen oder Code ausführen, aber behandeln Sie die .gitl.yaml eines nicht vertrauenswürdigen Repos mit derselben Vorsicht wie dessen .git/hooks oder Build-Skripte.

GitHub Action

gitl kann als GitHub Action verdrahtet werden: Sie reviewt die Commits eines Pull-Requests per KI und postet einen Kommentar mit dem Risiko-Score, optional mit Merge-Blockierung oberhalb einer Schwelle. Die Action baut gitl aus dem Quellcode (go install bei einer gepinnten Version). Auch im GitHub Marketplace gelistet, falls Sie es von dort hinzufügen möchten.

Fügen Sie .github/workflows/gitl-review.yml zu Ihrem Repository hinzu:

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

Best Practices für Sicherheit:

  • Schlüssel nur über secrets.*. gitl-api-key stammt aus secrets.GITL_API_KEY (festgelegt unter Settings → Secrets and variables → Actions), niemals hartcodiert in YAML oder committet. Wenn das Secret nicht gesetzt ist, läuft die Action im deterministischen Offline-Modus (kein Netzwerk, keine Kosten).

  • Minimale permissions:. Nur pull-requests: write (Kommentar posten) und contents: read (Checkout) werden benötigt – keine weitergehenden Rechte gewähren.

  • fetch-depth: 0 ist erforderlich. GitHub stellt base/head-SHAs im pull_request-Event bereit, aber ein flacher Klon kann base.sha..head.sha nicht auflösen.

  • fail-on ist standardmäßig never. Die Action kommentiert nur; sie blockiert Merges nicht, es sei denn, du optierst explizit ein (fail-on: high usw.) – dasselbe Prinzip „WARN by default, harte Sperre ist explizites Opt-in" wie bei der CLI (--fail-on). Wenn die Sperre auslöst, schlägt der Job mit gitls Exit-Code 2 (Risiko-Sperre) fehl – ein echter Tool-Fehler schlägt mit 1 fehl, sodass nachgelagerte Schritte „riskante Änderung" von „gitl ist kaputt" unterscheiden können.

  • Diff-Privatsphäre. In CI wird das Diff an den konfigurierten LLM-Provider gesendet (Standard: OpenAI-kompatible API). Für privaten Code verwende einen selbst gehosteten/Enterprise-Provider (Ollama, Azure OpenAI) – siehe Provider oben.

  • Provider-Auswahl. Standardmäßig verwendet die Action den Provider deiner Konfiguration (OpenAI-kompatibel, falls nicht gesetzt). Um einen nativen Provider anzusprechen, übergib provider: (openai|ollama|azure_openai|anthropic|gemini) und optional model: und base-url: zusammen mit gitl-api-key:. Alle drei sind optional und fallen, wenn sie weggelassen werden, auf deine .gitl.yaml/persönliche Konfiguration und gitls eingebaute Standardwerte zurück – siehe Provider oben. Beispiel: provider: anthropic mit einem Claude-Schlüssel in secrets.GITL_API_KEY.

  • Secret-Maskierung. GitHub maskiert secrets.*-Werte in Runner-Logs automatisch als ***, aber das ist kein Grund, den Schlüssel in eigenen Workflow-Schritten auszugeben.

Risikozusammenfassung der PR-Beschreibung (Opt-in)

Mit update-pr-description: true (Standard false) pflegt die Action zusätzlich einen kompakten Risikozusammenfassungs-Block am Ende der PR-Beschreibung – die Risikozeile plus einen Link zurück zum vollständigen Review-Kommentar, aktualisiert bei jedem Lauf:

      - uses: akomyagin/gitl@v0.6.2
        with:
          gitl-api-key: ${{ secrets.GITL_API_KEY }}
          update-pr-description: true

Es ist Opt-in, weil das Bearbeiten der PR-Beschreibung invasiver ist als ein sticky Kommentar; es sind keine zusätzlichen Berechtigungen nötig – pull-requests: write, bereits für den Kommentar erforderlich, deckt auch den PR-Text ab. Der Block wird durch das Markerpaar <!-- gitl-review-summary --> begrenzt, und nur der Text zwischen den Markern wird jemals ersetzt – alles, was du außerhalb schreibst, wird nie angefasst. Derzeit nur für GitHub (auf Gitea Actions ignoriert).

Gitea Actions (experimentell)

Dieselbe action.yml läuft auch auf Gitea Actions – Giteas Runner führt GitHub-ähnliche Composite-Actions aus, und gitls Action erkennt die Plattform zur Laufzeit über die Variable GITEA_ACTIONS=true, die Giteas act_runner in jeden Job injiziert. Der einzige plattformspezifische Teil – das Posten des sticky PR-Kommentars – läuft dann über Giteas REST-API (POST/PATCH /api/v1/repos/{owner}/{repo}/issues/...) mit curl statt der gh-CLI, die nur mit GitHub-API spricht. GitHub-Nutzer sind nicht betroffen: Ohne GITEA_ACTIONS verhält sich die Action genau wie zuvor.

Füge .gitea/workflows/gitl-review.yml zu deinem Repository hinzu (vollständig kommentiertes Beispiel: .gitea/workflows/gitl-review.yml in diesem Repo):

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

Anforderungen: Actions aktiviert, ein aktueller act_runner (node24-fähig) und ein Runner-Image mit bash, git, curl, jq und node. GITL_API_KEY kommt in Giteas Actions-Secrets, niemals in das YAML – dieselben BYOK-Regeln wie auf GitHub.

Verifizierungsstatus – vor der Verwendung lesen. Die curl-basierten REST-Aufrufe (Kommentare auflisten, erstellen, patchen, Sticky-Erkennung) wurden gegen eine echte Gitea-Instanz (gitea/gitea in Docker) Ende-zu-Ende ausgeführt – Liste-leer → POST-erstellen → erneut auflisten-findet → PATCH-aktualisieren → immer noch genau ein Kommentar. Dieser Teil funktioniert wie beschrieben. Was noch nicht verifiziert ist, ist der umgebende act_runner-CI-Kontext: ob GITEA_ACTIONS/GITHUB_API_URL/das PR-Event-Payload in einem echten Workflow-Lauf genau wie angenommen aussehen (dies wurde gegen Gitea/act_runner/act-fork-Quellcode gegengeprüft, nicht in einem echten Job ausgeführt). Behandle den CI-auslösenden Pfad als experimentell, bis jemand einen grünen Ende-zu-Ende-Lauf in echten Gitea Actions bestätigt; Fehlerberichte von echten Instanzen sind sehr willkommen.

GitLab CI (experimentell)

gitl liefert auch eine GitLab-CI/CD-Komponentetemplates/gitl-review.yml – die die GitHub-Action spiegelt: Sie installiert gitl mit go install in einer festgepinnten Version, überprüft den Bereich des Merge Requests ($CI_MERGE_REQUEST_DIFF_BASE_SHA..$CI_COMMIT_SHA), rendert den Kommentar über das gemeinsame plattformneutrale ci/comment.sh und erstellt/aktualisiert eine sticky MR-Notiz über GitLabs REST-API (gleicher <!-- gitl-review -->-Marker wie auf GitHub/Gitea). Der Job läuft nur in Merge-Request-Pipelines.

Die Komponente ist im GitLab-CI/CD-Katalog über einen Release-Zeit-Spiegel dieses Repositories unter gitlab.com/alkom68/gitl veröffentlicht (Einbahnstraße GitHub → GitLab, bei jedem Release-Tag gepusht). Auf gitlab.com bindest du sie als Katalogkomponente ein:

# .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"

Auf einer selbst gehosteten GitLab-Instanz löst include:component nur Komponenten von derselben Instanz auf – nutze die Vorlage stattdessen direkt über include:remote von GitHub (Inputs funktionieren mit Remote-Includes):

# .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"

Einrichtung – zwei CI/CD-Variablen (Settings → CI/CD → Variables, beide maskiert, niemals in YAML):

  • GITL_API_KEY – der BYOK-LLM-Schlüssel. Optional: Ohne ihn führt gitl die deterministische Offline-Überprüfung durch (kein Netzwerk, keine Kosten). Die Definition der Projektvariable reicht – sie hat Vorrang vor dem leeren gitl_api_key-Input-Standard der Komponente. Wenn du stattdessen den Input verwendest, übergib eine Variablenreferenz (gitl_api_key: $MY_LLM_KEY), niemals einen Literalschlüssel: Input-Werte werden in die Pipeline-Konfiguration interpoliert.

  • GITL_GITLAB_TOKEN – Token zum Posten der MR-Notiz (Projektzugriffstoken oder PAT, api-Scope, Reporter-Rolle oder höher; gesendet als PRIVATE-TOKEN). Wenn nicht gesetzt, fällt der Job auf CI_JOB_TOKEN zurück (JOB-TOKEN-Header) – aber in den meisten GitLab-Konfigurationen ist CI_JOB_TOKEN nicht für die Notes-API autorisiert, daher wird erwartet, dass der Fallback fehlschlägt (mit einer expliziten Fehlermeldung, nicht mit einem stillen Überspringen). Ein explizites GITL_GITLAB_TOKEN ist der zuverlässige Weg.

Eine vollständig kommentierte Selbsttest-Pipeline – auch das, was einem vollständigen Nutzungsbeispiel am nächsten kommt – ist .gitlab-ci-selftest.yml (ausführbar als .gitlab-ci.yml in einem GitLab-Spiegel dieses Repos).

Verifizierungsstatus – vor der Verwendung lesen. Die GitLab-REST-Aufrufe (MR-Notizen auflisten + Sticky-Marker-Erkennung, POST-Erstellen, PUT-Aktualisieren) und die Komponenten-YAML selbst (spec:/inputs:-Interpolation, include:local mit Inputs, über die CI-Lint-API) wurden Ende-zu-Ende gegen eine echte lokale GitLab-CE-Instanz (gitlab/gitlab-ce 19.2.0 in Docker) auf einem echten Merge Request verifiziert – Liste-leer → POST-erstellen → erneut auflisten-findet → PUT-aktualisieren → immer noch genau eine Notiz – mit den exakten curl/jq-Befehlen aus der Vorlage. Was noch nicht verifiziert ist, ist ein Live-Pipeline-Lauf: Die Werte von CI_MERGE_REQUEST_DIFF_BASE_SHA/CI_COMMIT_SHA/CI_JOB_URL in einer echten Merge-Request-Pipeline stammen aus GitLab-Dokumentation, nicht beobachtet, und die CI_JOB_TOKEN-Fallback-Ablehnung ist gemäß GitLabs Job-Token-Allowlist-Dokumentation dokumentiert, nicht reproduziert. Behandle den Pipeline-Pfad als experimentell, bis jemand einen grünen Ende-zu-Ende-Lauf bestätigt; Fehlerberichte willkommen.

Vertrauenshinweis. Die Komponente lädt ci/comment.sh vom GitLab-Spiegel (gitlab.com/alkom68/gitl) bei gitl_version herunter und führt es aus – ohne Prüfsummen-/Signaturprüfung, gleiche Vertrauensgrenze wie die go install ...@${gitl_version}-Zeile direkt darüber (gleiches Repo, gleicher Ref). Dieser Abruf erfolgt unabhängig davon, wie die Komponente eingebunden wird – Katalog oder include:remote –, denn ein Komponenten-Include liefert nur die YAML-Vorlage, nicht die Dateien des Komponenten-Repositories, sodass der Abruf mechanisch nicht vermeidbar ist. Das Herunterladen von derselben GitLab-Instanz, die die Komponente veröffentlicht (statt von GitHub), hält es im selben Namespace/Ref, ein ehrlicheres Vertrauensmodell als ein Cross-Host-Abruf. Wenn das für dein Bedrohungsmodell relevant ist, pinne gitl_version auf einen Commit-SHA statt auf ein Tag (Tags sind verschiebbar).

Bitbucket Pipelines (experimentell)

Die Bitbucket-Integration wird als Pipe ausgeliefert – und Pipes sind per Definition Docker-Images, also ist diese im Gegensatz zur GitHub/Gitea-Action und der GitLab-Komponente (reine YAML-Wrapper) ein eigenständiges Image: bitbucket-pipe/Dockerfile baut eine statische gitl-Binärdatei und backt den gemeinsamen ci/comment.sh-Renderer sowie den Entrypoint bitbucket-pipe/pipe.sh ein. Die Pipe löst den PR-Bereich auf ($BITBUCKET_PR_DESTINATION_COMMIT..$BITBUCKET_COMMIT), führt gitl review --format=json aus und erstellt/aktualisiert einen sticky PR-Kommentar über die Bitbucket-Cloud-REST-API (gleicher <!-- gitl-review -->-Marker wie auf den anderen Plattformen). Variablenreferenz: bitbucket-pipe/pipe.yml.

Image-Status. Veröffentlicht auf Docker Hub als alkom68/gitl-review-pipe seit v0.5.2 – der docker-publish-Job des Release-Workflows pusht bei jedem Release-Tag :<version> und :latest. Nur 0.5.2 und später existieren in der Registry: Frühere Releases stammen aus der Zeit vor der Veröffentlichung (die 0.5.0/0.5.1-Tags wurden nie gepusht), also pinne diese nicht.

# 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"

Einrichtung – zwei gesicherte Repository-/Workspace-Variablen (Repository settings → Pipelines → Repository variables; immer als $VAR referenziert, niemals Literalwerte im YAML):

  • GITL_API_KEY – der BYOK-LLM-Schlüssel. Optional: Ohne ihn führt gitl die deterministische Offline-Überprüfung durch (kein Netzwerk, keine Kosten).

  • GITL_BITBUCKET_TOKEN – Anmeldedaten zum Posten des PR-Kommentars: ein Repository-/Projekt-/Workspace-Zugriffstoken mit dem Scope pullrequest:write, gesendet als Authorization: Bearer. Alternative: Setze GITL_BITBUCKET_USER + GITL_BITBUCKET_APP_PASSWORD (App-Passwort mit pullrequest:write) für Basic Auth stattdessen. Wenn keines konfiguriert ist, schlägt die Pipe schnell mit einer expliziten Meldung fehl – bevor ein LLM-Budget ausgegeben wird.

Lieferketten-Hinweis (warum sich dies von der GitLab-Komponente unterscheidet). Die Pipe führt zur Laufzeit nichts heruntergeladenes aus: Die gitl-Binärdatei, ci/comment.sh und der Entrypoint sind alle in das versionierte Image aus einem Quellbaum eingebaut. Die GitLab-Komponente muss ci/comment.sh über das Netzwerk ohne Integritätsprüfung herunterladen (siehe ihren Vertrauenshinweis oben); die Pipe schließt diese Lücke konstruktionsbedingt.

Verifizierungsstatus — vor der Verwendung lesen. Das Image-Build und der vollständige In-Container-Ablauf wurden lokal verifiziert: docker build aus diesem Repo, dann docker run gegen ein echtes Test-Git-Repository mit emulierten BITBUCKET_*-Variablen — Offline-Review → korrektes sticky comment.md → Kommentar-Erstellung (POST), sticky Update (PUT, weiterhin genau ein Kommentar) und --fail-on-Exit-Code-Weitergabe, Ende-zu-Ende gegen einen lokalen Mock der Bitbucket-Kommentar-API getestet; die Fail-Fast-Pfade (fehlende Credential-/PR-Variablen) und der Fallback-Hinweis bei einem ungültigen Bereich wurden ebenfalls im Container getestet. Was noch nicht verifiziert ist: alles, was die echte Bitbucket-Infrastruktur betrifft — die REST-Aufrufe gegen api.bitbucket.org (Formen aus Atlassians API-Dokumentation), die genauen vordefinierten Variablen in einer Live-PR-Pipeline (BITBUCKET_PR_DESTINATION_COMMIT usw. sind dokumentierte Annahmen, keine beobachteten Werte) und wie Pipelines den Klon in Pipe-Container einhängt. Behandeln Sie den Live-Pipeline-Pfad als experimentell, bis jemand einen erfolgreichen Lauf in einem echten Bitbucket-Workspace bestätigt; Fehlerberichte sind willkommen.

Pre-commit-Hook (lokal)

gitl enthält einen pre-commit-Framework-Hook, sodass gitl review --staged --quiet automatisch vor jedem Commit ausgeführt wird — lokal, offline und standardmäßig ohne Kosten (--quiet ist im Hook-Manifest standardmäßig aktiviert, sodass der Offline-Hinweis nicht bei jedem Commit erneut ausgegeben wird).

Fügen Sie Folgendes zur .pre-commit-config.yaml Ihres Repositorys hinzu:

repos:
  - repo: https://github.com/akomyagin/gitl
    rev: v0.6.2   # pin to a released tag
    hooks:
      - id: gitl-review

Führen Sie dann pre-commit install aus. Das Framework baut die gitl-Binärdatei selbst (language: golang) und cached die Umgebung unter ~/.cache/pre-commit/, sodass die Build-Kosten nur einmal anfallen, nicht bei jedem Commit.

Für einen blockierenden Hook mit Kostenobergrenze:

hooks:
  - id: gitl-review
    args: [--fail-on=high, --max-cost-usd=0.05]   # opt-in: block on high risk, cap cost

Exportieren Sie GITL_API_KEY in Ihrer Umgebung für ein echtes KI-Review; ohne diesen führt der Hook das deterministische Offline-Review durch (kein Netzwerk, keine Kosten).

Wissenswertes:

  • Standardmäßig offline. Kein API-Schlüssel, kein Netzwerk, keine Kosten pro Commit. Setzen Sie GITL_API_KEY, um ein echtes KI-Review zu aktivieren.

  • Standardmäßig nicht blockierend. Der Hook gibt das Review aus, lässt den Commit aber nicht fehlschlagen — dasselbe Prinzip „WARN standardmäßig, harte Sperre ist explizites Opt-in" wie bei CLI/Action. Fügen Sie args: [--fail-on=high] hinzu, um zu blockieren.

  • Latenz. Ein echtes API-Review dauert einige Sekunden; halten Sie es vom kritischen Pfad fern, indem Sie es offline lassen, oder begrenzen Sie es mit --max-cost-usd.

  • Diff-Datenschutz. Mit einem echten Schlüssel geht der gestaged Diff an Ihren konfigurierten LLM-Anbieter — verwenden Sie für privaten Code einen selbst gehosteten/Enterprise-Anbieter (Ollama, Azure OpenAI), siehe Anbieter oben.

  • Offline-Hinweis unterdrücken. Das Manifest übergibt standardmäßig --quiet, sodass der pro Commit ausgegebene stderr-Hinweis „using deterministic offline review" unterdrückt wird; derselbe Schalter ist bei review/changelog als --quiet / GITL_QUIET verfügbar, oder repo-weit über output.quiet: true (der MCP-Server berücksichtigt output.quiet/GITL_OUTPUT_QUIET nur — er hat keine Flags, daher gilt der kurze GITL_QUIET-Alias dort nicht). Fehler und die Review-Ausgabe selbst sind davon nicht betroffen.

Ohne das pre-commit-Framework

Ein einfacher git-Hook funktioniert ebenfalls:

# .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-Server

gitl mcp führt gitl als Model Context Protocol-stdio Server aus — ein separater, zusätzlicher Kanal zur CLI/CI-Nutzung oben, um gitl interaktiv in einer Agent-Sitzung (Claude Desktop, Cursor, Windsurf usw.) zu verwenden, anstatt es extern aufzurufen. Er stellt zwei Tools bereit:

  • gitl_review — dieselbe Review-Engine wie gitl review: range/pr/staged (genau eines), optionales model-Override pro Aufruf. Anbieter und Endpunkt werden beim Serverstart bewusst festgelegt: Der Tool-Aufrufer ist ein KI-Agent, der durch Prompt-Injection im überprüften Inhalt gesteuert werden kann — ein base_url pro Aufruf würde es einem bösartigen Commit ermöglichen, die Anfrage umzuleiten und den echten API-Schlüssel preiszugeben. Gibt immer das strukturierte JSON-Artefakt zurück (kein md/text-Rendering, kein Streaming — ein Tool-Ergebnis ist atomar). risk.level wird als Daten zurückgegeben; es gibt kein --fail-on im MCP-Modus, da es keinen Prozess-Exit-Code gibt, der gesperrt werden kann.

  • gitl_digest — dasselbe wie gitl digest: days (Standard 7), optional repos. Ohne ein explizites repos-Argument verarbeitet das Tool nur das Arbeitsverzeichnis des Servers (plus digest.repos aus .gitl.yaml, falls konfiguriert) — es durchläuft niemals eigenständig beliebige Pfade. Ein explizites repos-Argument wird unverändert übernommen (der aufrufende Agent hat bereits über seine eigenen Tools Dateisystemzugriff; dies ist keine Zugriffskontrollgrenze, sondern nur ein „den Benutzer nicht überraschen"-Standard).

Fügen Sie Folgendes zu Ihrer MCP-Client-Konfiguration hinzu (Claude Desktop, Cursor usw.):

{
  "mcpServers": {
    "gitl": {
      "command": "gitl",
      "args": ["mcp"]
    }
  }
}

Die Konfiguration wird beim Start einmalig auf dieselbe Weise geladen wie bei den normalen Befehlen (.gitl.yaml + persönliche Konfiguration + GITL_*-Umgebung, aus dem Verzeichnis, in dem gitl mcp gestartet wird). Ohne Schlüssel laufen Tool-Aufrufe im selben deterministischen Offline-Modus wie die CLI. stdout ist für das MCP-Protokoll reserviert — dort wird nie etwas für Menschen Lesbares geschrieben; Warnungen gehen an stderr.

Lizenz

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