ai-mr-comment

Go Test Release Go Report Card License: MIT

A command-line tool written in Go that generates professional GitLab Merge Request (MR) or GitHub Pull Request (PR) comments based on git diffs using AI (OpenAI, Anthropic, Gemini, Ollama, or local CLI tools — Claude Code, Gemini CLI, or Codex).

Features

  • Reads git diffs from current repo or from a file
  • Auto-detects branch diff against origin/main or origin/master when no flags are given
  • Staged-only diff (--staged) for reviewing changes before committing
  • Exclude files from the diff by glob pattern (--exclude)
  • Smart chunking (--smart-chunk) for large diffs: summarizes each file, then synthesizes a final comment
  • Optional MR/PR title generation (--title) alongside the comment, printed as a distinct section
  • Generate comments directly from a GitHub PR or GitLab MR URL (--pr) — no local checkout needed
  • Supports public github.com, GitHub Enterprise, public gitlab.com, and self-hosted GitLab instances
  • Supports OpenAI, Anthropic (Claude), Google Gemini, and Ollama APIs
  • Local CLI providers — delegate auth to locally installed CLI tools, no API key management needed:
    • claude-cli — uses the local claude binary (Claude Code session), no API key required
    • gemini-cli — uses the local gemini binary (Google OAuth), no API key required
    • codex-cli — uses the local codex binary (quiet mode), requires OPENAI_API_KEY
  • Customizable API endpoints and models via --model flag or config
  • Multiple prompt styles — default, conventional, technical, user-focused, emoji, sassy, monday, jira, commit, commit-emoji, commit-conventional, chaos, haiku, roast, intern, shakespeare, manager, yoda, excuse
  • Jira-aware template (--template=jira) — extracts ticket key from branch name and places it first so Jira auto-links
  • Commit message generation (--commit-msg) — outputs a single conventional-style line ready for git commit -m
  • quick-commit subcommand — stages all changes, generates a conventional commit message (type and scope derived from the diff), commits, and pushes in one step
  • Gitmoji support (--emoji on quick-commit) — appends a type-matched emoji to the commit subject (✨ feat, 🐛 fix, ♻️ refactor, etc.)
  • Opt-out conventional commits (--no-conventional on quick-commit) — skips conventional format enforcement for free-form messages
  • Chaos mode (--chaos) — chaotic/absurd conventional commit on quick-commit; unhinged-but-accurate MR/PR description on the root command
  • Haiku mode (--haiku) — commit description as a 5-7-5 haiku on quick-commit; full MR/PR description in haiku form on the root command
  • Roast mode (--roast) — passive-aggressive commit on quick-commit; sardonically judgmental MR/PR description on the root command
  • Fortune trailer (--fortune on quick-commit) — appends a dev-wisdom fortune-cookie quote as a commit body
  • Monday mode (--monday on quick-commit) — casual, low-energy “pre-coffee” commit message
  • Jira commit mode (--jira on quick-commit) — prefixes the commit message with the Jira ticket key extracted from the branch name
  • Emoji commit mode (--emoji-commit on quick-commit) — appends a type-matched gitmoji to the commit description
  • Sassy mode (--sassy on quick-commit) — sassy but technically accurate commit message
  • Technical mode (--technical on quick-commit) — maximum technical precision; references exact function/struct names from the diff
  • Intern mode (--intern) — written by an overly enthusiastic junior developer who is SO excited about everything; works on both root cmd and quick-commit
  • Shakespeare mode (--shakespeare) — Early Modern English, iambic cadence, dramatic flair; works on both root cmd and quick-commit
  • Manager mode (--manager) — passive-aggressive corporate non-speak, “per our earlier discussion”; works on both root cmd and quick-commit
  • Yoda mode (--yoda) — inverted syntax, object before subject, strong with this one the force is; works on both root cmd and quick-commit
  • Excuse mode (--excuse) — technically accurate but every section has a built-in justification for why it had to be this way; works on both root cmd and quick-commit
  • CI/CD gate (--exit-code) — exits with code 2 when the AI flags critical issues, enabling pipeline enforcement
  • Auto-post comments (--post) — publishes the generated comment directly to the GitHub PR or GitLab MR via API
  • Update remote PR/MR metadata (--update-title, --update-description) — writes the generated title and/or description back to GitHub or GitLab
  • Named config profiles (--profile) — switch between providers/models/templates with a single flag; define profiles in ~/.ai-mr-comment.toml under [profile.<name>]
  • Configuration file support (~/.ai-mr-comment.toml)
  • Environment variable configuration
  • Outputs to a file (--output) or the system clipboard (--clipboard=title|description|commit-msg|all); when --output is set, stdout is suppressed — output goes to the file only
  • --output writes JSON when --format=json is set — ideal for saving structured review artifacts
  • Structured JSON output for scripting and CI (--format json)
  • Verbose debug logging to stderr (--verbose) — API timing, diff stats, config details
  • Live streaming output to the terminal — tokens appear as they are generated
  • Bootstrap a config file with init-config (never edit TOML by hand again)
  • All prompt templates stored as editable files in internal/prompts/templates/ — embedded at build time, overridable at ~/.config/ai-mr-comment/templates/<name>.tmpl
  • Shell completions for bash, zsh, fish, and PowerShell (completion subcommand)
  • Shell aliases (gen-aliases) — prints amc and amc-* convenience aliases ready to source into your shell profile
  • Changelog generation (changelog) — produces a user-facing Keep a Changelog entry from a commit range, grouped by Added / Fixed / Breaking Changes etc.
  • Custom system prompt (--system-prompt) — supply an ad-hoc prompt inline or from a file (@path), overriding the active template for a single run
  • Precise token counting for Gemini and heuristic estimation for others
  • Estimated cost calculation in debug mode
  • Native binary with no runtime dependencies

Installation

Prerequisites

  • Git
  • API key for your preferred provider (OpenAI, Anthropic, or Google Gemini) — not required when using claude-cli, gemini-cli, or ollama

macOS (Homebrew)

brew tap pbsladek/tap
brew install ai-mr-comment

Or install directly in one command:

brew install pbsladek/tap/ai-mr-comment

Upgrade later with:

brew upgrade ai-mr-comment

Other Platforms

Download the latest binary for your OS from the Releases page. Release archives are published for Linux, macOS, and Windows on both x86_64 and arm64.

For Linux/macOS script installation, download and inspect scripts/install.sh from the repository, then run it directly. The script verifies the downloaded archive against the release checksums.txt (and optionally the cosign signature) before installing.

Building from Source

Requires Go 1.26+.

# Clone the repository
git clone https://github.com/pbsladek/ai-mr-comment.git
cd ai-mr-comment

# Build
make build

# The binary will be available at ./dist/ai-mr-comment
# Build and run on current diff
make test-run

# Fetch latest tags first so --version shows the correct release tag
make fetch-tags build

Docker

No Go toolchain required. The image includes git so all diff and commit commands work. Published image: pwbsladek/ai-mr-comment on Docker Hub. Release images are published as multi-arch Linux manifests for amd64 and arm64. FIPS variant tag: pwbsladek/ai-mr-comment:<version>-fips.

If you build locally, log in to DHI first (base images are pulled from dhi.io):

docker login dhi.io
# Build the image
make docker-build

# Scan for fixable critical/high CVEs
make docker-scout

# Run against the current repo diff (mounts PWD, passes API keys from env)
make docker-run ARGS="--provider openai"

# Run quick-commit
make docker-quick-commit ARGS="--dry-run"

# Pull a specific version (replace v0.18.1 with the version you want)
docker pull pwbsladek/ai-mr-comment:v0.18.1
docker pull pwbsladek/ai-mr-comment:v0.18.1-fips

# Or use docker directly
docker run --rm -it \
  -v "$(pwd):/repo" -w /repo \
  -e OPENAI_API_KEY \
  pwbsladek/ai-mr-comment:v0.18.1 --provider openai

Mounting your config file:

docker run --rm -it \
  -v "$(pwd):/repo" -w /repo \
  -v "$HOME/.ai-mr-comment.toml:/home/nonroot/.ai-mr-comment.toml:ro" \
  -e OPENAI_API_KEY \
  pwbsladek/ai-mr-comment:v0.18.1

Fetching a PR/MR by URL (no repo mount needed):

docker run --rm \
  -e OPENAI_API_KEY \
  -e GITHUB_TOKEN \
  pwbsladek/ai-mr-comment:v0.18.1 --pr https://github.com/owner/repo/pull/42

Note: --clipboard is not available inside a container. Use --output or --format json instead to capture the output.

Configuration File

The tool looks for .ai-mr-comment.toml in your home directory or the current directory.

Generating the config file

Run init-config to write a fully-commented template to ~/.ai-mr-comment.toml:

ai-mr-comment init-config

# Write to a custom path instead
ai-mr-comment init-config --output ./ai-mr-comment.toml

The command refuses to overwrite an existing file. Remove the old file first if you want to regenerate it.

# Choose which provider to use: "openai", "anthropic", "gemini", "ollama", "claude-cli", "gemini-cli", or "codex-cli"
provider = "anthropic"

# === Anthropic Settings ===
anthropic_api_key = "xxxx"
anthropic_model = "claude-sonnet-4-6"
anthropic_endpoint = "https://api.anthropic.com/"
# Other Anthropic models: claude-opus-4-7, claude-opus-4-6, claude-haiku-4-5-20251001

# === Claude CLI Settings ===
# No API key needed — auth is delegated to the local claude CLI process.
# Requires Claude Code to be installed (https://claude.ai/code).
# claude_cli_path = ""              # auto-detected: ~/.claude/local/claude, then PATH
claude_cli_model = "claude-sonnet-4-6"

# === OpenAI Settings ===
openai_api_key = "xxxx"
openai_model = "gpt-5.5"
openai_endpoint = "https://api.openai.com/v1/"
# Other OpenAI models: gpt-5.5-pro, gpt-5.4, gpt-5.4-pro, gpt-5.4-mini, gpt-5.4-nano, gpt-5.3-codex

# === Gemini Settings ===
gemini_api_key = "xxxx"
gemini_model = "gemini-2.5-flash"
# Other Gemini models: gemini-3.1-pro-preview, gemini-3-flash-preview, gemini-3.1-flash-lite, gemini-2.5-pro, gemini-2.5-flash-lite

# === Gemini CLI Settings ===
# No API key needed — auth is delegated to the local gemini CLI process (Google OAuth).
# Requires the Gemini CLI to be installed (https://github.com/google-gemini/gemini-cli).
# gemini_cli_path = ""              # auto-detected from PATH
gemini_cli_model = "gemini-2.5-flash"

# === Codex CLI Settings ===
# No API key needed — auth is delegated to the local codex CLI process.
# Requires the OpenAI Codex CLI to be installed (https://github.com/openai/codex).
# codex_cli_path = ""               # auto-detected from PATH
# codex_cli_model = ""              # uses codex default when empty

# === Ollama Settings ===
ollama_model = "llama3.2"
ollama_endpoint = "http://localhost:11434/api/generate"

# === GitHub / GitHub Enterprise ===
github_token = "xxxx"       # or set GITHUB_TOKEN env var (required for private repos)
# github_base_url = ""      # set for GitHub Enterprise, e.g. https://github.mycompany.com

# === GitLab / Self-Hosted GitLab ===
gitlab_token = "xxxx"       # or set GITLAB_TOKEN env var (required for private projects)
# gitlab_base_url = ""      # set for self-hosted GitLab, e.g. https://gitlab.mycompany.com

# === Template Settings ===
# Options: default, conventional, technical, user-focused, emoji, sassy, monday,
#          jira, commit, commit-emoji, commit-conventional,
#          chaos, haiku, roast, intern, shakespeare, manager, yoda, excuse
template = "default"

# === Named Profiles ===
# Switch with: ai-mr-comment --profile <name>
# A profile overrides any top-level setting for that invocation only.

[profile.fast]
provider     = "openai"
openai_model = "gpt-5.4-nano"
template     = "conventional"

[profile.openai]
provider     = "openai"
openai_model = "gpt-5.5"

[profile.anthropic]
provider        = "anthropic"
anthropic_model = "claude-opus-4-7"
template        = "technical"

[profile.gemini]
provider     = "gemini"
gemini_model = "gemini-2.5-flash"

[profile.claude-cli]
provider         = "claude-cli"
claude_cli_model = "claude-sonnet-4-6"

[profile.gemini-cli]
provider          = "gemini-cli"
gemini_cli_model  = "gemini-2.5-flash"

[profile.codex-cli]
provider = "codex-cli"

[profile.local]
provider     = "ollama"
ollama_model = "llama3.2"

Example Output

Text mode (--title):

── Title ────────────────────────────────

feat: Add user authentication system


── Description ──────────────────────────

## Summary

Adds a complete user authentication system using JWT tokens and bcrypt password hashing. Required to protect API endpoints and support user identity across sessions.

## Key Changes

- Added user model with bcrypt password hashing
- Implemented JWT authentication middleware
- Created login and registration API endpoints
- Added comprehensive unit tests for auth logic

## Why These Changes

Provides a secure foundation for user identity, allowing protected access to API resources.

JSON mode (--format json):

{
  "title": "feat: Add user authentication system",
  "description": "## Key Changes\n\n- Added user model...",
  "comment": "## Key Changes\n\n- Added user model...",
  "provider": "openai",
  "model": "gpt-5.5"
}

description and comment carry the same value; comment is kept for backwards compatibility. When --exit-code is set, a "verdict": "PASS" or "verdict": "FAIL" field is also included.

Commit message mode (--commit-msg --format json):

{"commit_message":"feat(auth): add JWT refresh token support"}

Usage

# Generate comment for the full branch diff (auto-detects merge base with origin/main)
ai-mr-comment

# Generate comment for staged changes only
ai-mr-comment --staged

# Exclude generated or vendored files
ai-mr-comment --exclude "vendor/**" --exclude "*.sum"

# Use smart chunking for large diffs (summarizes per-file, then combines)
ai-mr-comment --smart-chunk

# Use a specific provider and template
ai-mr-comment --provider anthropic --template technical

# Override the model for a single run
ai-mr-comment --model gpt-5.5

# Generate comment for a specific commit range
ai-mr-comment --commit "HEAD~3..HEAD"

# Pipe a diff through stdin
git diff | ai-mr-comment --file=- --plain
gh pr diff 42 | ai-mr-comment --quiet

# Generate a comment from a GitHub PR URL (no local checkout needed)
ai-mr-comment --pr https://github.com/owner/repo/pull/42

# Generate a comment from a GitLab MR URL
ai-mr-comment --pr https://gitlab.com/group/project/-/merge_requests/5

# Generate a comment from a GitHub Enterprise or self-hosted GitLab URL
# (set github_base_url / gitlab_base_url in config or env)
GITHUB_BASE_URL=https://github.mycompany.com \
  ai-mr-comment --pr https://github.mycompany.com/owner/repo/pull/42

GITLAB_BASE_URL=https://gitlab.mycompany.com \
  ai-mr-comment --pr https://gitlab.mycompany.com/group/project/-/merge_requests/5

# Generate a title and comment together (shown as separate sections)
ai-mr-comment --title

# Output structured JSON for CI/scripting
# Always includes title, description, provider, and model fields
ai-mr-comment --format json

# Generate only a git commit message (conventional commits style)
ai-mr-comment --commit-msg --staged

# Generate a commit message as JSON
ai-mr-comment --commit-msg --format json | jq -r '.commit_message'

# Copy the description to clipboard
ai-mr-comment --clipboard=description

# Copy the title to clipboard
ai-mr-comment --title --clipboard=title

# Copy a commit message to clipboard
ai-mr-comment --commit-msg --clipboard=commit-msg

# Gate CI on AI review — exits 2 if critical issues are detected
ai-mr-comment --exit-code --pr https://github.com/owner/repo/pull/42

# Generate and immediately post the comment back to the PR/MR
ai-mr-comment --pr https://github.com/owner/repo/pull/42 --post

# Generate and update the actual PR/MR title and description
ai-mr-comment --pr https://github.com/owner/repo/pull/42 --update-title --update-description

# Save JSON review to a file (for artifact upload in CI)
ai-mr-comment --format json --output /tmp/review.json --pr https://github.com/owner/repo/pull/42

# Enable verbose debug logging to stderr (API timing, diff stats, config)
ai-mr-comment --verbose

# Show token and cost estimation without calling the API
ai-mr-comment --debug

# Print the exact prompt/request for agent debugging without calling the API
git diff | ai-mr-comment --file=- --print-prompt
git diff | ai-mr-comment --file=- --print-request | jq .

# Preview planned work without calling the provider or writing files
git diff | ai-mr-comment --dry-run --file=-

# Inspect changed files and diff stats without spending tokens
ai-mr-comment --changed-files
ai-mr-comment --summary-only --format=json | jq .

# Inspect resolved config, tokens, git state, and local CLI binaries
ai-mr-comment doctor
ai-mr-comment config-dump --format=json | jq .

# Apply a built-in preset
ai-mr-comment --preset ci --pr https://github.com/owner/repo/pull/42
ai-mr-comment --preset local-fast --file=-
ai-mr-comment --preset security
ai-mr-comment changelog --preset release-notes --commit="v1.2.0..HEAD"

# Override the system prompt for a single run (inline)
ai-mr-comment --system-prompt="Focus only on security vulnerabilities."

# Override the system prompt from a file
ai-mr-comment --system-prompt=@~/prompts/security-review.txt

# Chaos mode — unhinged but accurate MR/PR description
ai-mr-comment --chaos

# Haiku mode — entire description as 5-7-5 haikus
ai-mr-comment --haiku

# Roast mode — sardonically judgmental but correct
ai-mr-comment --roast

# Generate a user-facing changelog entry from the last 10 commits
ai-mr-comment changelog --commit="HEAD~10..HEAD"

# Generate a changelog entry for a release range, output as JSON
ai-mr-comment changelog --commit="v1.2.0..HEAD" --format=json

# Print shell aliases (amc, amc-qc, amc-cl, …) and add to profile
ai-mr-comment gen-aliases >> ~/.zshrc

# Or evaluate on every shell start to always stay up to date
# eval "$(ai-mr-comment gen-aliases)"

# Generate shell completion script
ai-mr-comment completion bash >> ~/.bash_completion
ai-mr-comment completion zsh > ~/.zsh/completions/_ai-mr-comment

# Bootstrap a config file (writes ~/.ai-mr-comment.toml)
ai-mr-comment init-config

# Use a named profile (provider/model/template preset)
ai-mr-comment --profile fast
ai-mr-comment --profile anthropic --title

Agent and Pipe Integration

ai-mr-comment can be used as a Unix-style filter:

git diff | ai-mr-comment --file=- --plain
git show HEAD | ai-mr-comment commit-message --file=-
gh pr diff 42 | ai-mr-comment review --quiet
git diff | ai-mr-comment verdict --file=-

For structured agent input, pass JSON on stdin:

printf '%s' '{
  "title": "Add auth flow",
  "description": "Implements token refresh",
  "branch": "feat/AUTH-123-refresh",
  "diff": "diff --git a/auth.go b/auth.go\n+..."
}' | ai-mr-comment review --input=json --quiet

Agent-oriented commands:

ai-mr-comment review --file=-
ai-mr-comment title --file=-
ai-mr-comment commit-message --file=-
ai-mr-comment verdict --file=-
ai-mr-comment estimate --file=-

Machine-friendly output modes:

ai-mr-comment --quiet
ai-mr-comment --plain
ai-mr-comment --stream=jsonl
ai-mr-comment --print-prompt
ai-mr-comment --print-request
ai-mr-comment --dry-run
ai-mr-comment --summary-only

Exit codes are stable for automation: 0 success/pass, 1 tool or runtime error, 2 AI verdict fail, 3 no diff/input, 4 invalid usage.

Options

  • --pr <URL>: GitHub PR or GitLab MR URL — fetches diff and metadata remotely, no local checkout needed. Works with github.com, GitHub Enterprise, gitlab.com, and self-hosted GitLab. Mutually exclusive with --staged, --commit, and --file.
  • --commit <COMMIT>: Specific commit or range
  • --staged: Diff staged changes only (git diff --cached); mutually exclusive with --commit
  • --exclude <PATTERN>: Exclude files matching glob pattern (e.g. vendor/**, *.sum). Can be repeated.
  • --smart-chunk: Split large diffs by file, summarize each, then synthesize a final comment
  • --title: Generate a concise MR/PR title alongside the comment; printed as a distinct ── Title ── section in text mode. When --format=json is used, title is always generated automatically (no need for --title). Mutually exclusive with --commit-msg.
  • --commit-msg: Generate a single-line git commit message instead of a full MR/PR description. Output is clean text or {"commit_message":"..."} in JSON mode. Mutually exclusive with --title.
  • --multi-line: Generate a multi-line commit message (subject + blank line + markdown body) when used with --commit-msg or quick-commit. GitHub and GitLab use this format to pre-fill the PR/MR title and description automatically.
  • --exit-code: Exit with code 2 when the AI detects critical issues (bugs, security vulnerabilities, data loss risks). Mutually exclusive with --commit-msg.
  • --post: Post the generated comment back to the GitHub PR or GitLab MR via API (requires --pr). Uses the same token as diff fetching.
  • --update-title: Update the GitHub PR title or GitLab MR title with the generated title (requires --pr). Mutually exclusive with --commit-msg.
  • --update-description: Update the GitHub PR body or GitLab MR description with the generated description (requires --pr). Mutually exclusive with --commit-msg and --title-only.
  • --dry-run: Print the resolved plan and diff stats without calling the provider, writing output files, copying to clipboard, posting comments, or updating PR/MR metadata.
  • --changed-files: Print changed file paths and exit without calling the provider.
  • --summary-only: Print diff stats and changed files and exit without calling the provider.
  • --file <FILE>: Read diff from file instead of git. Use --file=- to read from stdin.
  • --output <FILE>: Write output to file instead of stdout — suppresses all terminal output. Writes JSON when --format=json is set; writes the commit message when --commit-msg is set.
  • --clipboard <WHAT>: Copy to system clipboard — title, description (or comment), commit-msg, or all (title + description separated by a blank line)
  • --format <FORMAT>: Output format — text (default) or json
  • --input <FORMAT>: Input format — text (default) or json for structured agent input (title, description, branch, diff)
  • --quiet: Force strict JSON output on stdout for agents and scripts
  • --plain, --no-decorate: Suppress text section headers and decorative separators
  • --stream=jsonl: Emit JSON Lines events (start, token, done) instead of decorated text
  • --print-prompt: Print the resolved system prompt and exit without calling the provider
  • --print-request: Print the resolved provider request as JSON and exit without calling the provider
  • --preset <NAME>: Apply built-in defaults: ci (JSON + exit-code + technical), local-fast (Ollama + plain), security (security-focused technical review), or release-notes (user-focused title/description).
  • --provider <PROVIDER>: Provider (openai, anthropic, gemini, ollama, claude-cli, gemini-cli, codex-cli)
  • --model <NAME>: Override the model for this run (e.g. gpt-5.5, claude-opus-4-7, gemini-3.1-pro-preview)
  • -t, --template <NAME>: Template style — default, conventional, technical, user-focused, emoji, sassy, monday, jira, commit, commit-emoji, commit-conventional, chaos, haiku, roast, intern, shakespeare, manager, yoda, excuse (commit, commit-emoji, and commit-conventional require --commit-msg; style templates cannot be combined with --commit-msg)
  • --system-prompt <TEXT|@FILE>: Override the system prompt for this run. Pass the prompt inline (--system-prompt="Focus on security") or read it from a file with an @ prefix (--system-prompt=@review.txt). Mutually exclusive with --template.
  • --chaos: Generate a chaotic, dramatically over-the-top MR/PR description (still technically accurate). Mutually exclusive with --template, --system-prompt, --commit-msg.
  • --haiku: Generate the entire MR/PR description as a sequence of haikus (5-7-5). Mutually exclusive with --template, --system-prompt, --commit-msg.
  • --roast: Generate a technically accurate but sardonically judgmental MR/PR description. Mutually exclusive with --template, --system-prompt, --commit-msg.
  • --profile <NAME>: Activate a named config profile defined under [profile.<name>] in ~/.ai-mr-comment.toml. Overrides top-level provider, model, template, and other settings for this run only.
  • --debug: Show precise token usage and cost estimation without calling the generation API
  • --verbose: Print detailed debug lines to stderr — config file path, diff stats, template source, streaming decision, and per-API-call timing and response size
  • --version: Print version, commit SHA, and repository URL in key=value format and exit
  • -h, --help: Print help

Diagnostics

doctor and its alias config-dump inspect local readiness without making a live provider request:

ai-mr-comment doctor
ai-mr-comment doctor --provider openai
ai-mr-comment doctor --preset local-fast --format=json

Use check when you want a live provider ping.

Subcommands

  • quick-commit [flags]: Stage all changes, generate an AI commit message, commit, and push in one step. See Quick Commit below.
  • publish [flags]: Generate and sync a PR/MR title, description, managed summary comment, labels, and reviewers in one step. See Publish below.
  • changelog [flags]: Generate a user-facing changelog entry from a commit range or diff file. See Changelog below.
  • gen-aliases [--shell bash|zsh] [--output FILE]: Print amc and amc-* shell aliases to stdout. See Shell Aliases below.
  • models [--provider <NAME>]: List known model names for a provider.
  • init-config [--output <PATH>]: Write a default config file to ~/.ai-mr-comment.toml (or the given path). Refuses to overwrite an existing file.
  • completion [bash|zsh|fish|powershell]: Print a shell completion script to stdout.

GitHub & GitLab Integration (--pr)

Point --pr at any GitHub pull request or GitLab merge request URL to generate a comment without needing the repository checked out locally.

# GitHub (public)
ai-mr-comment --pr https://github.com/owner/repo/pull/42

# GitLab (public)
ai-mr-comment --pr https://gitlab.com/group/project/-/merge_requests/5

Authentication

Public repos and projects work without a token (subject to API rate limits). For private repos set the token via environment variable or config file:

Platform Env var Config key
GitHub / GitHub Enterprise GITHUB_TOKEN github_token
GitLab / Self-Hosted GitLab GITLAB_TOKEN gitlab_token

Self-Hosted Instances

For GitHub Enterprise or self-hosted GitLab, pass the instance base URL. The SDKs automatically append the correct API path (/api/v3/ for GitHub, /api/v4/ for GitLab).

Environment variables:

# GitHub Enterprise
GITHUB_BASE_URL=https://github.mycompany.com \
  ai-mr-comment --pr https://github.mycompany.com/owner/repo/pull/42

# Self-hosted GitLab
GITLAB_BASE_URL=https://gitlab.mycompany.com \
  ai-mr-comment --pr https://gitlab.mycompany.com/group/project/-/merge_requests/5

Config file (.ai-mr-comment.toml):

github_base_url = "https://github.mycompany.com"
gitlab_base_url = "https://gitlab.mycompany.com"

Templates

Select a template with -t / --template. All templates receive the branch name as context (useful for ticket key extraction).

All built-in templates live in internal/prompts/templates/ in the repository and are embedded into the binary at build time. You can override any template by placing a file at ~/.config/ai-mr-comment/templates/<name>.tmpl.

Name Description
default Professional description with Summary, Key Changes, Why, Checklist, Notes
conventional Conventional Commits body with optional BREAKING CHANGE and Refs
technical Deep technical focus — Summary, Implementation Details, Rationale, Testing Strategy
user-focused Non-technical perspective — What’s New, Why Important, Impact
emoji Fun emoji-rich format with Summary section
sassy Dry-wit tone, technically accurate
monday Casual “pre-coffee” tone
jira Puts the Jira ticket key from the branch name first so Jira auto-links; includes Summary section
commit Single-line conventional commit message (requires --commit-msg)
commit-emoji Single-line gitmoji-style commit message (requires --commit-msg)
commit-conventional Full Conventional Commits message with optional body, BREAKING CHANGE footer, and Refs (requires --commit-msg)
chaos Chaotic, dramatically over-the-top description (still technically accurate)
haiku Entire description as a sequence of haikus
roast Sardonically judgmental, dry-wit tone
intern Overly enthusiastic junior-developer energy
shakespeare Shakespearean Early Modern English
manager Passive-aggressive corporate non-speak
yoda Inverted Yoda syntax
excuse Technically accurate with built-in excuses for every decision

Jira Integration

The jira template extracts the ticket key from your branch name (e.g. feat/ABC-123-add-loginABC-123) and places it at the very start of the description so Jira’s branch/commit linking picks it up automatically.

ai-mr-comment --template jira --staged
# Output starts with: "ABC-123 Add login endpoint\n\n## Key Changes..."

This works because the current branch name is automatically prepended to the diff context for all local git operations (not --file or --pr).

Custom System Prompt

Use --system-prompt to replace the active template prompt for a single run — no template file needed.

# Inline prompt
ai-mr-comment --system-prompt="Focus only on security vulnerabilities."

# Read from a file (@ prefix)
ai-mr-comment --system-prompt=@~/prompts/security-review.txt

# Works on the changelog subcommand too
ai-mr-comment changelog --commit="v1.2.0..HEAD" \
  --system-prompt="List only breaking changes in one sentence each."

--system-prompt and --template are mutually exclusive — use one or the other per run.

When --exit-code is also set, the verdict preamble is still prepended on top of the custom prompt (same behaviour as with templates).

Commit Messages

Use --commit-msg to generate a single conventional-style commit message instead of a full PR description.

# Print the message (text mode)
ai-mr-comment --commit-msg --staged

# JSON output — single key, pipeline-friendly
ai-mr-comment --commit-msg --format json
# {"commit_message":"feat(auth): add JWT refresh token support"}

# Pipe directly into git commit
git commit -m "$(ai-mr-comment --commit-msg --staged)"

# Copy to clipboard
ai-mr-comment --commit-msg --staged --clipboard=commit-msg

# Gitmoji style
ai-mr-comment --commit-msg --template commit-emoji --staged

# Multi-line message: subject + blank line + markdown body
# GitHub/GitLab use this to pre-fill the PR/MR title and description
ai-mr-comment --commit-msg --multi-line --staged

# Use it with quick-commit too
ai-mr-comment quick-commit --multi-line

--commit-msg and --title are mutually exclusive. In JSON mode, the response contains only commit_message (no description or title fields).

Quick Commit

quick-commit is a one-command shortcut for the full stage → AI message → commit → push workflow.

# Full workflow
ai-mr-comment quick-commit

# Preview the generated message without touching git
ai-mr-comment quick-commit --dry-run

# Generate a long multi-section commit body
ai-mr-comment quick-commit --long

# Aim for a specific body length
ai-mr-comment quick-commit --body-lines=32

# Commit but skip the push
ai-mr-comment quick-commit --no-push

# Open the generated message in your editor before committing
ai-mr-comment quick-commit --edit

# Force conventional commit type and scope
ai-mr-comment quick-commit --type fix --scope api

# Apply a message template style
ai-mr-comment quick-commit --message-template detailed
ai-mr-comment quick-commit --message-template release
ai-mr-comment quick-commit --message-template ticket

# Stage only tracked modified/deleted files
ai-mr-comment quick-commit --tracked-only

# Append a DCO signoff trailer from git user config
ai-mr-comment quick-commit --signoff

# Use a specific provider or model
ai-mr-comment quick-commit --provider anthropic --model claude-opus-4-7

# Use a named profile
ai-mr-comment quick-commit --profile anthropic

# Force a breaking-change commit (feat!) for a major version bump
ai-mr-comment quick-commit --breaking

# Append a type-matched gitmoji to the subject
ai-mr-comment quick-commit --emoji
# e.g. feat(cli): add flag ✨

# Skip conventional commits format — free-form message
ai-mr-comment quick-commit --no-conventional

# Chaos mode — random funny/absurd conventional commit (great for pipeline trigger commits)
ai-mr-comment quick-commit --chaos
# e.g. ci(gremlins): ask nicely that the gremlins stop eating the cache

# Haiku mode — commit description as a 5-7-5 haiku about the diff
ai-mr-comment quick-commit --haiku
# e.g. feat(auth): tokens flow in / sessions find their rightful home / login works at last

# Roast mode — technically accurate but passive-aggressively judgmental
ai-mr-comment quick-commit --roast
# e.g. refactor(naming): rename 'x' to something a human might understand

# Fortune trailer — appends a dev-wisdom quote as a commit body
ai-mr-comment quick-commit --fortune
# commit subject + blank line + "The best code is the code you didn't have to write."

# Combine chaos + fortune for maximum vibes
ai-mr-comment quick-commit --chaos --fortune

# Monday mode — casual, low-energy "pre-coffee" commit
ai-mr-comment quick-commit --monday
# e.g. chore(deps): update the packages, it is what it is

# Jira mode — prefix with ticket key extracted from branch name
ai-mr-comment quick-commit --jira
# e.g. feat(auth): ABC-123 add JWT refresh token support

# Emoji-commit mode — append a type-matched gitmoji to the description
ai-mr-comment quick-commit --emoji-commit
# e.g. feat(auth): add refresh token rotation ✨

# Sassy mode — accurate but with attitude
ai-mr-comment quick-commit --sassy
# e.g. fix(auth): handle the edge case that definitely should have been handled

# Technical mode — maximum precision, references exact names from the diff
ai-mr-comment quick-commit --technical
# e.g. refactor(api): replace O(n²) scan with hash-map lookup in resolveUser

# Intern mode — SO excited about this commit!!
ai-mr-comment quick-commit --intern
# e.g. feat(auth): add the login thing everyone was asking about!!

# Shakespeare mode — hark, the diff doth speak
ai-mr-comment quick-commit --shakespeare
# e.g. fix(parser): hark, the null doth crash our noble code no more

# Manager mode — per our earlier alignment session
ai-mr-comment quick-commit --manager
# e.g. feat(auth): action item from last sprint re: token refresh, going forward

# Yoda mode — inverted syntax, strong with this commit it is
ai-mr-comment quick-commit --yoda
# e.g. fix(cache): stale data, purge we must

# Excuse mode — it happened for reasons, there were constraints
ai-mr-comment quick-commit --excuse
# e.g. fix(parser): handle empty input, which apparently nobody tested before

# JSON output — only commit_message is printed, all status lines suppressed
ai-mr-comment quick-commit --format json
# {"commit_message":"feat(cli): add login endpoint"}

Steps performed:

  1. git add . — stages all changes by default; --tracked-only uses git add -u
  2. Reads the staged diff; prepends branch name for ticket key context
  3. Calls AI with the conventional commits prompt
  4. Optionally edits, signs off, and commits the generated message
  5. git push --set-upstream origin <branch> — works for new branches too
Flag Description
--dry-run Generate and print the message, skip all git operations
--no-push Commit but skip the push
--edit Open the generated commit message in $GIT_EDITOR, $VISUAL, or $EDITOR before committing
--type Force a conventional commit type (feat, fix, docs, style, refactor, test, chore, perf, ci, build, or revert)
--scope Force a conventional commit scope
--message-template Apply a commit message template style: short, detailed, release, or ticket
--include-untracked Explicitly stage tracked and untracked changes, matching the default behavior
--tracked-only Stage only tracked modified/deleted files with git add -u
--signoff Append a Signed-off-by: trailer using local git user.name and git user.email
--breaking Force feat! conventional commit type to signal a breaking change (major version bump)
--multi-line Generate a multi-line message (subject + body) that pre-fills the PR/MR title and description
--long Generate a longer multi-section body; implies --multi-line
--body-lines Target body line count for long multi-line commits; implies --multi-line
--emoji Append a type-matched gitmoji to the subject (✨ feat, 🐛 fix, ♻️ refactor, 💥 breaking, etc.)
--no-conventional Skip conventional commits format — AI generates a free-form message instead
--chaos Generate a random funny/absurd conventional commit (ignores the real diff; great for pipeline trigger commits)
--haiku Write the commit description as a 5-7-5 haiku about the actual diff
--roast Technically accurate but passive-aggressively judgmental commit message
--fortune Append a dev-wisdom fortune-cookie quote as a commit body (git log shows it as a trailer)
--monday Casual, low-energy “pre-coffee” tone; accurate but undemanding
--jira Prefix the message with the Jira ticket key extracted from the branch name
--emoji-commit Append a type-matched gitmoji to the commit description
--sassy Sassy but technically accurate commit message
--technical Maximum technical precision; references exact function/struct names from the diff
--intern Overly enthusiastic junior-developer commit message
--shakespeare Commit description in Shakespearean Early Modern English
--manager Passive-aggressive corporate non-speak commit message
--yoda Commit description in Yoda’s inverted syntax
--excuse Technically accurate commit message with a built-in excuse
--format json Output {"commit_message":"..."} only; suppress status lines
--provider Override the AI provider
--model Override the model
--profile Activate a named config profile

Publish

publish is the one-shot remote PR/MR workflow. It generates a title and description, updates the remote title/body, preserves manual description text by syncing only a managed section, and creates or updates one managed summary comment.

# Existing GitHub PR or GitLab MR
ai-mr-comment publish --pr https://github.com/owner/repo/pull/42

# Add labels, request reviewers, and mark the title as Draft: if the generated text looks risky
ai-mr-comment publish \
  --pr https://gitlab.com/group/project/-/merge_requests/5 \
  --auto-labels \
  --label=release-notes \
  --reviewer=12345 \
  --draft-if-risky

# From a local branch: find an existing PR/MR or create one from origin
ai-mr-comment publish

# Preview without writing remote changes
ai-mr-comment publish --pr https://github.com/owner/repo/pull/42 --dry-run --format=json
Flag Description
--pr Existing GitHub PR or GitLab MR URL. If omitted, publish uses the current branch and origin remote to find or create a PR/MR
--no-update-title Skip updating the remote title
--no-update-description Skip updating the remote PR body / MR description
--replace-description Replace the full description instead of syncing the managed ai-mr-comment section
--post-summary Create or update one managed summary comment. Defaults to true; use --post-summary=false to disable
--auto-labels Apply simple labels inferred from changed files and generated text, such as docs, tests, ci, dependencies, or security
--label Add an explicit label. Can be repeated or comma-separated
--reviewer Request a reviewer. GitHub uses usernames; GitLab uses numeric user IDs
--draft-if-risky Prefix the generated title with Draft: when generated text indicates high risk
--dry-run Generate and print the planned remote changes without writing them
--format text (default) or json

Changelog

changelog generates a user-facing changelog entry from any diff source. Output follows the Keep a Changelog format, grouped under the headings that apply: Added, Changed, Deprecated, Removed, Fixed, Security, Breaking Changes.

# Last 10 commits (Makefile default)
make changelog

# Specific release range
ai-mr-comment changelog --commit="v1.2.0..HEAD"

# From a diff file
ai-mr-comment changelog --file=my.diff --provider=anthropic

# JSON output for CI pipelines
ai-mr-comment changelog --commit="v1.2.0..HEAD" --format=json

# Write directly to a file
ai-mr-comment changelog --commit="v1.2.0..HEAD" --output=CHANGELOG.md

# Override the prompt for a custom format
ai-mr-comment changelog --commit="v1.2.0..HEAD" \
  --system-prompt="List only breaking changes."
Flag Description
--commit Commit or commit range (e.g. v1.2.0..HEAD)
--file Read diff from a file instead of git
--format text (default) or json ({"changelog":"...","provider":"...","model":"..."})
--output Write output to a file instead of stdout
--provider AI provider override
--model Model override
--profile Activate a named config profile
--system-prompt Override the changelog system prompt

Shell Aliases

gen-aliases prints a block of ready-to-source shell alias definitions.

# Append once to your profile
ai-mr-comment gen-aliases >> ~/.zshrc

# Or evaluate on every shell start (always up-to-date)
eval "$(ai-mr-comment gen-aliases)"

# Write directly to a file
ai-mr-comment gen-aliases --output=~/.bashrc

# Via make
make gen-aliases

Aliases defined:

Alias Expands to
amc ai-mr-comment
amc-staged ai-mr-comment --staged
amc-commit ai-mr-comment --commit-msg --staged
amc-commit-multi ai-mr-comment --commit-msg --multi-line --staged
amc-title ai-mr-comment --title
amc-json ai-mr-comment --format=json
amc-debug ai-mr-comment --debug
amc-chaos ai-mr-comment --chaos
amc-haiku ai-mr-comment --haiku
amc-roast ai-mr-comment --roast
amc-intern ai-mr-comment --intern
amc-shakespeare ai-mr-comment --shakespeare
amc-manager ai-mr-comment --manager
amc-yoda ai-mr-comment --yoda
amc-excuse ai-mr-comment --excuse
amc-conventional ai-mr-comment --template=conventional
amc-emoji ai-mr-comment --template=emoji
amc-jira ai-mr-comment --template=jira
amc-monday ai-mr-comment --template=monday
amc-sassy ai-mr-comment --template=sassy
amc-technical ai-mr-comment --template=technical
amc-user ai-mr-comment --template=user-focused
amc-qc ai-mr-comment quick-commit
amc-qc-dry ai-mr-comment quick-commit --dry-run
amc-qc-edit ai-mr-comment quick-commit --edit
amc-qc-local ai-mr-comment quick-commit --no-push
amc-qc-tracked ai-mr-comment quick-commit --tracked-only
amc-qc-signoff ai-mr-comment quick-commit --signoff
amc-qc-fix ai-mr-comment quick-commit --type=fix
amc-qc-docs ai-mr-comment quick-commit --type=docs
amc-qc-detailed ai-mr-comment quick-commit --message-template=detailed
amc-qc-release ai-mr-comment quick-commit --message-template=release
amc-qc-ticket ai-mr-comment quick-commit --message-template=ticket
amc-qc-breaking ai-mr-comment quick-commit --breaking
amc-qc-chaos ai-mr-comment quick-commit --chaos
amc-qc-haiku ai-mr-comment quick-commit --haiku
amc-qc-roast ai-mr-comment quick-commit --roast
amc-qc-fortune ai-mr-comment quick-commit --fortune
amc-qc-monday ai-mr-comment quick-commit --monday
amc-qc-jira ai-mr-comment quick-commit --jira
amc-qc-emoji ai-mr-comment quick-commit --emoji-commit
amc-qc-sassy ai-mr-comment quick-commit --sassy
amc-qc-technical ai-mr-comment quick-commit --technical
amc-qc-intern ai-mr-comment quick-commit --intern
amc-qc-shakespeare ai-mr-comment quick-commit --shakespeare
amc-qc-manager ai-mr-comment quick-commit --manager
amc-qc-yoda ai-mr-comment quick-commit --yoda
amc-qc-excuse ai-mr-comment quick-commit --excuse
amc-cl ai-mr-comment changelog
amc-models ai-mr-comment models
amc-init ai-mr-comment init-config
Flag Description
--shell bash (default) or zsh — both use identical alias syntax
--output Also write aliases to this file

Local CLI Providers

Three providers delegate AI calls and authentication to a locally installed CLI tool — no API key management in ai-mr-comment is required. These are useful on machines where auth is handled by the CLI’s own session (SSO, OAuth, Claude Code session).

claude-cli — Claude Code

Delegates to the claude binary. Auth is managed by Claude Code — no ANTHROPIC_API_KEY needed.

provider = "claude-cli"
claude_cli_model = "claude-sonnet-4-6"

Binary lookup order:

  1. claude_cli_path in config (if set)
  2. ~/.claude/local/claude
  3. claude on $PATH
Key Description Default
claude_cli_path Explicit path to the claude binary auto-detected
claude_cli_model Model passed via --model claude-sonnet-4-6

gemini-cli — Google Gemini CLI

Delegates to the gemini binary. Auth uses Google OAuth — no GEMINI_API_KEY needed.

Install: npm install -g @google/gemini-cli

provider = "gemini-cli"
gemini_cli_model = "gemini-2.5-flash"
Key Description Default
gemini_cli_path Explicit path to the gemini binary auto-detected via $PATH
gemini_cli_model Model passed via --model gemini-2.5-flash

codex-cli — OpenAI Codex CLI

Delegates to the codex binary in quiet/non-interactive mode. Still requires OPENAI_API_KEY but handles its own session and approval flow.

Install: npm install -g @openai/codex

provider = "codex-cli"
# codex_cli_model = ""   # leave empty to use codex default
Key Description Default
codex_cli_path Explicit path to the codex binary auto-detected via $PATH
codex_cli_model Model passed via --model empty (codex default)

Profiles

All three have built-in profiles:

ai-mr-comment --profile claude-cli
ai-mr-comment --profile gemini-cli
ai-mr-comment --profile codex-cli

Named Profiles

Define named profiles in ~/.ai-mr-comment.toml under [profile.<name>] sections. Each profile can override any top-level setting — provider, model, template, endpoint, etc.

provider        = "anthropic"
anthropic_model = "claude-sonnet-4-6"
template        = "default"

[profile.fast]
provider     = "openai"
openai_model = "gpt-5.4-nano"
template     = "conventional"

[profile.openai]
provider     = "openai"
openai_model = "gpt-5.5"
template     = "technical"

[profile.anthropic]
provider        = "anthropic"
anthropic_model = "claude-opus-4-7"
template        = "technical"

[profile.gemini]
provider     = "gemini"
gemini_model = "gemini-3.1-pro-preview"
template     = "technical"

[profile.local]
provider     = "ollama"
ollama_model = "llama3.2"

[profile.claude-cli]
provider         = "claude-cli"
claude_cli_model = "claude-sonnet-4-6"

[profile.gemini-cli]
provider         = "gemini-cli"
gemini_cli_model = "gemini-2.5-flash"

[profile.codex-cli]
provider = "codex-cli"

Activate a profile by passing --profile <name> to any command:

# Quick review with the fast profile
ai-mr-comment --profile fast

# Deep technical review with Anthropic Opus
ai-mr-comment --profile anthropic --title

# Generate a changelog with Gemini Pro
ai-mr-comment changelog --profile gemini --commit="v1.2.0..HEAD"

# Commit with Ollama (no API key needed)
ai-mr-comment quick-commit --profile local --dry-run

# Use Claude CLI session auth (no API key needed)
ai-mr-comment --profile claude-cli

# Use Gemini CLI with Google OAuth (no API key needed)
ai-mr-comment --profile gemini-cli

# Use Codex CLI
ai-mr-comment --profile codex-cli

Run ai-mr-comment init-config to generate a config file pre-populated with the standard profiles above.

CI/CD Usage

Three flags are designed specifically for pipeline integration:

--exit-code — Gate merges on AI review

Instruct the AI to output a VERDICT: PASS or VERDICT: FAIL line before its review. If FAIL, the process exits with code 2, failing your pipeline step.

# Fail the pipeline if the AI detects critical issues
ai-mr-comment --exit-code --pr "$PR_URL"
echo $?  # 0 = PASS, 2 = FAIL, 1 = tool error

# JSON includes the verdict field for downstream processing
ai-mr-comment --exit-code --format json --pr "$PR_URL" | jq .verdict

GitHub Actions example:

- name: AI Code Review
  run: ai-mr-comment --exit-code --pr "$"
  env:
    OPENAI_API_KEY: $
    GITHUB_TOKEN: $
  # Step fails (exit 2) if AI detects critical issues

--post — Auto-post comments to PRs/MRs

After generating the comment, post it directly to the PR or MR via the GitHub/GitLab API. Uses the same token as diff fetching — no extra setup needed.

# Generate and post in one step
ai-mr-comment --pr "$PR_URL" --post

# Combine with exit-code: review, post, and gate in one command
ai-mr-comment --exit-code --post --pr "$PR_URL"

GitHub Actions example:

- name: AI Review & Comment
  run: ai-mr-comment --post --pr "$"
  env:
    OPENAI_API_KEY: $
    GITHUB_TOKEN: $

--output with --format json — Save review artifacts

Write the full JSON review to a file. Useful for artifact upload, audit trails, or passing data between pipeline jobs.

# Write JSON to file
ai-mr-comment --format json --output review.json --pr "$PR_URL"

# Upload as artifact (GitHub Actions)
# - uses: actions/upload-artifact@v4
#   with: { name: ai-review, path: review.json }

# Read in a later job
cat review.json | jq -r '.description'
cat review.json | jq -r '.verdict'  # when --exit-code was used

When --commit-msg is set, --output writes the commit message (with a trailing newline) rather than JSON.

Streaming Output

When running interactively (stdout is a TTY), the tool streams tokens directly to the terminal as the model generates them, so you see the comment appear word by word rather than waiting for the full response.

Streaming is automatically disabled and the output is fully buffered when:

  • --format json is set (the full response is needed before encoding)
  • --smart-chunk is set (multi-stage summarise + synthesise calls)
  • --output <file> is set (writing to a file)
  • stdout is not a TTY (piped output, CI, redirected to file)

If a streaming call fails mid-flight, the tool transparently falls back to a standard buffered request and outputs the full comment normally.

Token & Cost Estimation

When running with the --debug flag, the tool provides a detailed breakdown of the expected usage:

  • Gemini: Uses official SDK token counting (100% accurate).
  • OpenAI/Anthropic/Ollama: Uses a conservative character-based heuristic (~3.5 chars per token).
  • Cost: Calculates estimated input cost in USD based on current model pricing (Ollama is free).

Development

Project Structure

  • cmd/ai-mr-comment/: Executable entry point
  • internal/app/: Cobra command orchestration and embedded prompt templates
  • internal/: Internal packages for config, providers, remote hosts, git diffs, prompts, estimates, and commit helpers
  • testdata/: Sample git diffs for testing
  • dist/: Compiled binaries (after build)

Testing

# Run unit tests
make test

# Run deterministic compiled-binary e2e smoke tests
make test-e2e-smoke

# Run deterministic Docker smoke tests
make docker-smoke

# Run all provider integration tests (provider tests skip when keys are missing)
make test-integration

# Run one provider integration lane
make test-integration-openai
make test-integration-gemini
make test-integration-anthropic

# Run Ollama-only integration tests (CPU-friendly small model)
OLLAMA_ENDPOINT=http://127.0.0.1:11434/api/generate \
OLLAMA_MODEL=llama3.2:1b \
make test-integration-ollama

# Run fuzz tests (30s per target)
make test-fuzz

# Run response-quality evals on curated diff fixtures (promptfoo)
make eval-quality

# Run writing-quality evals for commit messages + PR title/description
make eval-quality-writing

# Install/update pinned eval dependencies only
make eval-quality-deps

# Run linter
make lint

CI coverage on PRs includes unit/lint checks plus deterministic binary e2e smoke checks. Docker smoke also runs when DHI registry credentials are available to pull the hardened base images. Provider e2e tests run after merge to main or by manual dispatch when credentials are available. Long Ollama integration + promptfoo quality eval lanes run from a separate manual workflow: Ollama Integration (Manual). Open GitHub Actions, select that workflow, then click Run workflow.

Response Quality Evals

make eval-quality runs end-to-end evals against fixture diffs in evals/ and scores the generated review for recall, severity coverage, actionability, and false positives. In CI, evals write a compact JSON report to evals/promptfoo-results.json and print a short summary. CI uses serialized eval calls and extended per-test timeout for CPU models (PROMPTFOO_MAX_CONCURRENCY=1, PROMPTFOO_EVAL_TIMEOUT_MS=300000).

Prerequisites:

  • Node.js + npm
  • A reachable model provider (defaults to local Ollama)
  • Built binary (handled automatically by make eval-quality)
  • Pinned eval dependencies (including promptfoo) are installed from evals/package-lock.json

Useful overrides:

  • AMC_EVAL_PROVIDER (default ollama)
  • AMC_EVAL_MODEL (default llama3.2:1b)
  • AMC_EVAL_TEMPLATE (default technical)
  • AMC_EVAL_FLAGS (additional CLI flags)
# Example: run evals against local Ollama 1B model
AMC_EVAL_PROVIDER=ollama AMC_EVAL_MODEL=llama3.2:1b make eval-quality

# Example: run commit + PR writing evals against local Ollama 8B model
AMC_EVAL_PROVIDER=ollama AMC_EVAL_MODEL=llama3.1:8b AMC_EVAL_TEMPLATE=default make eval-quality-writing

# Open the latest promptfoo report UI
make eval-quality-view

Dependency Updates

Dependabot opens grouped PRs weekly (Monday) for Go modules, npm packages in evals/, and GitHub Actions.

To approve and auto-merge all open Dependabot PRs at once:

gh pr list --author "app/dependabot" --json number --jq '.[].number' | \
  xargs -I {} gh pr merge {} --auto --squash

--auto queues each PR to merge once all required status checks pass. Requires auto-merge to be enabled in the repo settings. Drop --auto and use --squash alone to merge immediately without waiting for CI.

Shell Completions

# Install bash completions
make install-completion-bash

# Install zsh completions
make install-completion-zsh

# Or generate manually for any shell
ai-mr-comment completion [bash|zsh|fish|powershell]

Contributing

Commit Convention

This project uses Conventional Commits to drive automatic semantic versioning. Every commit merged to main must follow the format:

<type>[optional scope]: <description>
Type Description Version bump
fix: Bug fix patch (0.0.x)
feat: New feature minor (0.x.0)
feat!: or BREAKING CHANGE: footer Breaking change major (x.0.0)
chore:, docs:, ci:, test:, refactor:, style:, perf: Non-functional none

Examples:

fix: handle empty diff gracefully
feat: add clipboard output support
feat!: redesign config file format
chore: update dependencies

Release Process

Merging to main automatically creates a version tag (e.g. v0.2.0) based on the commits since the last release — no GitHub Release is created yet.

When ready to publish a release:

  1. Go to GitHub → Releases → Draft a new release
  2. Pick the pre-created tag from the dropdown
  3. Click Publish release — GoReleaser builds and attaches signed binaries automatically
  4. Release workflow dispatches the source tarball metadata to pbsladek/homebrew-tap for Homebrew validation/update automation

License

MIT

Acknowledgements

This project is a Go rewrite of mr-comment originally created by Robert Kozak.