EN · RU

Documentation

The full usage reference for gitl v0.6.2. Requires git in PATH; Go 1.22+ only for go install / building from source.

Install

# 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

# Go toolchain
go install github.com/akomyagin/gitl/cmd/gitl@latest

Or download a signed release binary from GitHub Releases — every release is cosign-signed (keyless) and covered by SLSA L3 build provenance; the verification steps are in VERIFY.md.

Commands & flags

# AI review of a commit range — streams tokens to the terminal in real time
GITL_API_KEY=sk-... gitl review HEAD~5..HEAD

# no key = deterministic offline review (heuristic risk, no network call)
gitl review HEAD~5..HEAD

# review staged (not yet committed) changes before `git commit`
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
gitl review pr/42

# machine-readable output for CI + risk gating
gitl review HEAD~5..HEAD --format=json
gitl review HEAD~5..HEAD --fail-on=high   # exit code 2 on high risk

# estimate cost without making an API call
gitl review HEAD~5..HEAD --dry-run

# cap the estimated cost of a run
gitl review HEAD~5..HEAD --max-cost-usd=0.50

# skip the on-disk LLM cache (always call the model)
gitl review HEAD~5..HEAD --no-cache

# disable streaming (non-interactive, buffered output)
gitl review HEAD~5..HEAD --no-stream

# suppress the informational offline-mode notice on stderr
# (also via GITL_QUIET=1 or output.quiet: true)
gitl review HEAD~5..HEAD --quiet

# changelog from last tag (or full history if no tags) — no LLM by default
gitl changelog
gitl changelog v1.2.0..HEAD --format=json

# AI changelog: rewrites the grouped result as release-note prose; falls back
# to the deterministic changelog without a key — never fails
GITL_API_KEY=sk-... gitl changelog --ai

# activity summary for the last N days — no LLM
gitl digest --days=14

# multi-repo digest: runs in parallel; one unreachable repo doesn't fail the rest
gitl digest --repos=../service-a,../service-b --format=json

# interactive TUI viewer for digest (requires a TTY)
gitl digest --days=14 --tui

# write a commented starter .gitl.yaml to the repo root
gitl init

gitl version
gitl --help

All three commands support --format=md|text|json. A custom review system prompt is set via config only (prompt.system_template_file); there is no --system-template flag — see Custom templates.

Exit codes

CodeMeaning
0ok — risk below the --fail-on threshold (or no gate set)
1tool/runtime error — git, LLM, or config failure
2the --fail-on risk gate triggered — CI can branch on exactly this

Shell completions

gitl ships cobra-generated completions for bash, zsh, fish, and PowerShell. Homebrew installs bash/zsh/fish completions automatically (release archives also carry them under completions/). Otherwise:

# 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 with fixed value sets — --format (md|text|json), --fail-on (never|low|medium|high), and --provider — complete their allowed values.

Configuration

The fast path: gitl init writes a commented starter .gitl.yaml to the repo root (refusing to overwrite an existing one without --force; --output writes elsewhere).

Two levels, merged by priority: flag > env > .gitl.yaml (repo) > ~/.config/gitl/config.yaml (personal). The repo-level .gitl.yaml is committed as a shared team policy (risk threshold, excluded paths, changelog categories). Without a key, gitl runs in deterministic offline mode.

In offline mode — or when a real model omits a valid risk block and gitl falls back to the heuristic — the risk header is annotated with *(heuristic)* (and "heuristic": true in --format=json), so a deterministic score is never mistaken for a model's own judgement.

Providers (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)

When reviewing interactively (md or text format on a TTY), gitl streams tokens to the terminal as they arrive. Streaming is on by default and switches off automatically in CI (non-TTY stdout), with --format=json, and when a custom output.template_file is configured (the template needs the complete response, so the review is buffered and rendered through it instead).

Streaming is currently implemented only for the OpenAI-compatible provider (openai / ollama / azure_openai). With the native anthropic or gemini provider, gitl transparently produces the same review as a single buffered response regardless of output.stream / --no-stream.

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

Color (output.color)

On an interactive terminal, gitl review colorizes the risk level in the header (HIGH red, MEDIUM yellow, LOW green). Color switches off automatically when stdout is not a TTY and never appears in --format=json output. Precedence, highest first:

  1. NO_COLOR env var set (any value, even empty) — color off (no-color.org);
  2. output.color: false in config (or GITL_OUTPUT_COLOR=false) — color off;
  3. stdout is not a TTY — color off;
  4. otherwise — color on.

Quiet mode (output.quiet)

Without an API key, review prints an informational "using deterministic offline review" notice to stderr on every run (and changelog --ai prints an analogous fallback notice). Suppress it with any of:

  1. the --quiet flag on review / changelog;
  2. the GITL_QUIET env var set (any value, even empty);
  3. output.quiet: true in config (or GITL_OUTPUT_QUIET=true).

--quiet only silences the informational banner: errors, the rendered review/changelog on stdout, and the --fail-on gate are never affected.

LLM response cache (cache)

gitl review caches model responses on disk (SHA-256 of provider + model + prompt) under ~/.cache/gitl/review/ (XDG-compliant). Identical diffs reuse the cached result instantly, with no API call or cost.

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

Disable per-call with --no-cache. In --format=json every review artifact carries additive run metadata: duration_ms (wall-clock of the run) and cache: { "hit": bool, "tier": "none|local|tiered" } — tier reports the configured cache topology, not which backend served a particular hit.

Shared remote cache (cache.remote) — opt-in

Off by default, BYO-backend: gitl never hosts a service and makes no network request to any cache until you configure one. Useful for CI cold starts — a shared HTTP KV endpoint lets one runner reuse another's review of the same diff.

cache:
  enabled: true
  ttl_hours: 24
  remote:                     # opt-in shared cache for CI cold starts
    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

The local disk cache stays the first tier: reads check disk, then the remote (a remote hit is backfilled to disk); writes go to both. The protocol is a dumb key-value store over HTTP: GET {url}/{key} → 200 with the JSON entry or 404 = miss; PUT {url}/{key} with the JSON entry → any 2xx = stored. If token_env names an env var with a non-empty value, both requests carry Authorization: Bearer. Keys are 64-char hex SHA-256 strings.

Safety contract: any remote failure silently degrades to the local cache — it never fails the review. Entries contain only the model's response, keyed by an opaque hash: no diff and no prompt text ever reach the remote cache.

Risk trend (policy.risk_log_enabled)

Every gitl review run appends its risk outcome to a local JSONL log (~/.local/share/gitl/risk-history.jsonl; %AppData%\gitl\ on Windows). gitl digest reads it back and shows a per-repo "Risk trend (last N days)" section — review count by level, high-risk direction, and the last few reviews. In --format=json it's the optional risk_trend field. Reviews are correlated with a repository by its origin remote URL (falling back to the worktree path).

The history is local to your machine — it does not persist across CI runners, so the trend is a feature for local developer use, not for CI.
policy:
  risk_log_enabled: false   # opt out (config only, no CLI flag)

Custom templates

Three independent, config-only overrides (no CLI flags):

prompt:
  system_template_file: "./review-policy.md"             # path relative to CWD
  changelog_system_template_file: "./changelog-policy.md"
output:
  template_file: "./review-output.tmpl"
Trust note: these keys can be set by a repo-level .gitl.yaml, so running gitl review against a cloned repository you don't control can point it at a template inside that same repository. text/template here can't read arbitrary files or execute code, but treat an untrusted repo's .gitl.yaml with the same caution you'd give its .git/hooks or build scripts.

CI integrations

GitHub Action

The Action AI-reviews a pull request's commits and posts a sticky comment with the risk score, optionally blocking merge above a threshold. It builds gitl from source (go install at a pinned version).

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
          fail-on: high                               # optional: block merge on high risk

Key points:

Gitea Actions (experimental)

The same action.yml runs on Gitea Actions — the platform is detected at run time via the GITEA_ACTIONS=true variable, and the sticky comment is posted through Gitea's REST API with curl instead of the gh CLI.

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

Requirements: Actions enabled, a recent act_runner (node24-capable), and a runner image providing bash, git, curl, jq and node. The REST-call path was verified end-to-end against a real Gitea instance; the surrounding act_runner CI context is still experimental — bug reports from real instances are very welcome.

GitLab CI (experimental)

gitl ships a GitLab CI/CD component mirroring the GitHub Action: it reviews the merge request's range and creates/updates a sticky MR note. On gitlab.com, include it as a catalog component:

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

On a self-hosted GitLab instance, consume the template via include:remote straight from GitHub:

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

Setup — two CI/CD variables (both masked, never in YAML): GITL_API_KEY (optional; without it gitl runs the offline review) and GITL_GITLAB_TOKEN (project access token or PAT, api scope, Reporter+, for posting the MR note — the CI_JOB_TOKEN fallback is usually not authorized for the Notes API). The REST calls and component YAML were verified against a real GitLab CE instance; a live pipeline run is still experimental.

Bitbucket Pipelines (experimental)

The Bitbucket integration is a Pipe — a self-contained Docker image (alkom68/gitl-review-pipe on Docker Hub, published since v0.5.2) that resolves the PR range, runs gitl review --format=json, and creates/updates a sticky PR comment.

# bitbucket-pipelines.yml
pipelines:
  pull-requests:
    '**':
      - step:
          name: gitl review
          clone:
            depth: full   # the default depth-50 clone may not contain the PR base
          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

Setup — two secured repository/workspace variables: GITL_API_KEY (optional) and GITL_BITBUCKET_TOKEN (an access token with the pullrequest:write scope; alternatively GITL_BITBUCKET_USER + GITL_BITBUCKET_APP_PASSWORD for Basic auth). The pipe executes nothing fetched at run time — the binary and scripts are baked into the versioned image. The in-container flow was verified against a mock of the Bitbucket API; the live-pipeline path is still experimental.

Pre-commit hook

gitl ships a pre-commit framework hook so that gitl review --staged --quiet runs before every commit — locally, offline, and at zero cost by default.

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

then run pre-commit install. The framework builds the gitl binary itself (language: golang) and caches the environment, so the build cost is paid once. To opt into a blocking hook with a cost cap:

hooks:
  - id: gitl-review
    args: [--fail-on=high, --max-cost-usd=0.05]

A plain git hook works too:

# .git/hooks/pre-commit  (chmod +x)
#!/usr/bin/env bash
set -euo pipefail
gitl review --staged --quiet || true
# to block the commit on high risk instead:
#   gitl review --staged --quiet --fail-on=high

MCP server

gitl mcp runs gitl as a Model Context Protocol stdio server, for using gitl interactively inside an agent session (Claude Desktop, Cursor, Windsurf, etc.) instead of shelling out. It exposes two tools:

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

Config is loaded once at startup the same way as the plain commands. Without a key, tool calls run in the same deterministic offline mode as the CLI. stdout is reserved for the MCP protocol; warnings go to stderr.