// changelog

Changelog

Every released version of CommitBrief and what shipped in it.

API freeze. CLI surface, JSON schema v1, and rules formats are now under strict semver. `claude-cli` + `gemini-cli` promoted to stable.

Highlights

v1.0.0 is the API freeze checkpoint. From here on, CLI flag surface, JSON schema v1, the COMMITBRIEF.md / OUTPUT.md formats, and public config keys all follow strict semver. Breaking changes wait for v2.x.

If you’re upgrading from anywhere on the v0.x line, the migration guide in the CLI repo collects every breaking change since v0.9.x.

Added

  • claude-cli and gemini-cli providers promoted to stable. README documents both alongside the four API providers; the v0.9.0 “experimental” disclaimer is gone. The plain-text emit pipeline closed the last reliability gaps — --output routes correctly, the host CLI’s version is memoised + bounded, and the prompt transport for claude-cli switched to stdin so ARG_MAX is no longer a ceiling.

  • gosec security scan + make security-check. Static security analysis runs on every push to main and on a weekly schedule (.github/workflows/security.yml). Local devs get the same wrapper via scripts/security-scan.sh. The exclusion set (G304/G306/G301/G204/G101/G122) is documented inline with one-paragraph rationale per rule. High-confidence findings (G115 etc.) fail the scan.

  • README “Stability” section. Declares the v1.0.0 API freeze scope and links to the v0.x → v1.0 migration guide.

  • BENCHMARKS.md baseline snapshot. Captures diff-pipeline and cache-hit numbers at the v1.0.0-rc.1 freeze point. Used as a regression detector — a future 2× slowdown is the trigger for an investigation.

  • make check target. Runs every guard CI runs, in CI order, bailing on the first failure. Single entry-point for “is this push-ready?”.

  • COMMITBRIEF_CONFIG environment variable documented. Setting it to an absolute path replaces the default ~/.commitbrief/config.yml lookup — useful for ephemeral CI environments and reproducible tests.

Changed

  • Diff.IsMerge field and cli.warn.merge_commit catalog key removed. The merge-commit warning was retired with the scope- flag collapse in v0.9.0 — commitbrief diff <merge-sha> gives first-parent semantics with no special prompt (same as git diff <merge-sha>). Library consumers reading the field need to drop it.

Fixed

  • Gemini provider hardens int→int32 conversion for max-output tokens. A value above math.MaxInt32 would silently wrap to negative; now bounded to [1, math.MaxInt32] with the default falling back to 4096. Found via gosec G115 during the v1.0.0-rc.1 security audit.

  • KeyMeta.DiffHash and KeyMeta.SystemPromptHash carry real SHA-256 digests. Pre-v1.0.0-rc.1 the diff hash stored the first 16 hex chars of the composite cache key (NOT a diff hash) and the system-prompt hash was always empty. Both fields now match what the configuration docs advertise.

  • Generated git hooks embed the absolute path to commitbrief. macOS GUI git clients (Tower, GitHub Desktop, Fork, JetBrains IDEs) run hooks with a stripped $PATH that typically omits /opt/homebrew/bin, so exec commitbrief --staged … silently failed to launch. install-hook now resolves the running binary via os.Executable + filepath.EvalSymlinks and embeds the result as a single-quoted token. Survives brew upgrade (which swaps the keg symlink target).

CLI splash logo on every run — 16×16 half-block rendering of the CommitBrief mark, alongside wordmark and OSC 8 hyperlinks.

Added

  • CLI splash logo on every run. A 16×16 half-block rendering of the CommitBrief mark — same gradient + arrow as the favicon and web logo — shown alongside the wordmark, tagline, and OSC 8 hyperlinks to Home / Docs / GitHub / Sponsor / Author.

    Printed to stderr onlycommitbrief --json | jq and --markdown > file stay uncorrupted — and gated on a TTY-capable stderr so redirected CI logs don’t fill with raw 24-bit color escapes. The wordmark line embeds the resolved build version (version.Version), so it always matches the running binary.

CLI provider polish — stdin transport for claude-cli, `compress --dry-run`, locale narrow to {en, tr}.

⚠️ Breaking

  • Locale surface narrowed to {en, tr}. Pre-v0.9.2 the langNames map advertised 15 languages for which we never shipped translations — i18n.Load silently fell through to English, so the dry-run footer claiming Lang: Deutsch was a lie. Resolve now coerces any unsupported code (output.lang: de, --lang fr, LANG=es_ES) to en while preserving the original Source for attribution.

Changed

  • CLI providers respect --output. The plain-text emit path used by --cli claude / --cli gemini now routes through the same openOutput helper the structured renderers use, so --cli claude --output review.md writes to the file instead of silently dropping the destination.

  • CLI provider prompt transport switched to stdin for claude-cli. Large diffs were hitting the platform ARG_MAX limit (~128KB), surfacing as argument list too long. claude-cli now invokes claude -p - and pipes the prompt via stdin. gemini-cli stays on argv for now — upstream lacks a documented stdin shorthand.

  • DefaultModel for CLI providers is memoised + bounded. The cache-key path queries DefaultModel on every review; before it re-shelled out to <cli> --version each time and could hang a pipeline behind a misbehaving host CLI. sync.Once + 5-second timeout cap the cost at one short subprocess per Backend.

Added

  • --cli is mutually exclusive with --json and --markdown. CLI-provider output is pre-formatted plain text; combining it with a structured renderer either re-flows the formatting or parses prose as JSON. Cobra rejects the pairing before any provider call.

  • dry-run now reports output tokens, context window, and cost estimate. Mirrors the verbose footer of a real review so users can decide whether to fire the request without having to.

  • commitbrief compress --dry-run. Runs the LLM compression call and prints the Result block (sizes, savings, per-review saved $) but does NOT replace COMMITBRIEF.md or write a backup. Mutually exclusive with --out.

Fixed

  • commitbrief diff accepts pathspecs and >2 args. The subcommand used to cap at two positional args, rejecting legitimate git diff <ref> -- <pathspec> invocations. MinimumNArgs(1); everything past the first arg is forwarded verbatim.

  • ui.EnableANSI is now called from Execute. On legacy Windows consoles VT100 escape mode must be opted into before any ANSI codes are written; we shipped the helper but never invoked it at the entry point.

  • Shared interactive stdin across the review pipeline. Guard, secret scanner, and cost preflight used to each instantiate their own bufio.Scanner over os.Stdin; the first scanner’s lookahead could swallow input meant for the next site. A single *bufio.Reader is now plumbed through all three.

Removed

  • Dead i18n keys cleaned up. ~10 unreferenced keys from earlier revisions. New CI guard (make i18n-check) fails on the first unreferenced key so the catalog can’t grow stale again.

Safety scope narrowing — `--yes` no longer bypasses secret scanner or cost preflight.

⚠️ Breaking

  • --yes no longer bypasses the secret scanner or cost preflight. Previously, --yes (intended to auto-answer the .commitbrief/ pre-send guard) also silently approved any flagged credential and any above-threshold cost estimate — a footgun for CI users wiring --yes to skip the guard prompt. Use the dedicated bypasses: --allow-secrets for the scanner, --no-cost-check for the preflight.

  • cache.max_size_mb config field removed. Defined in the struct and surfaced via config get/set, but no code ever read it — cache eviction is TTL-based. Setting it now errors as an unknown field. Remove the line from your config.

Changed

  • Active provider doctor check. commitbrief doctor now verifies that the currently selected provider has its own credentials — not just that some provider does. Closes a gap where setting provider: openai while only anthropic.api_key was configured would pass doctor but fail every review.

  • Localised confirm vocabulary, guard prompt, and setup wizard. Catalog drives accept-vocabulary (y/yes in EN, e/evet in TR), the [y/N] / [e/H] suffix, the .commitbrief/ guard warning, and every label in commitbrief setup.

Added

  • Rules content secret scan. The pre-send secret scanner now inspects user-authored COMMITBRIEF.md and OUTPUT.md content in addition to the diff. Rules join the system prompt verbatim, so a credential pasted into either file would leak just as surely as one in a diff. Embedded defaults are skipped.

  • cache.enabled and cache.ttl_days are now honored. Previously defined but inert.

Fixed

  • install-hook --hook=pre-push ships a real pre-push body. Previously every hook variant got the same --staged invocation, which silently no-op’d at push time. The new pre-push script parses git’s per-ref stdin protocol and runs commitbrief diff <remote-sha>..<local-sha> --fail-on=critical per ref. Push blocks on the first critical finding.

  • init no longer aborts on the first existing file. Existing files are now skipped with a per-file log line and the missing sibling is still written.

  • init --force is now a real flag. Previously the docs promised it but the CLI returned “unknown flag”.

CLI-as-provider (claude-cli, gemini-cli), `commitbrief diff` subcommand, per-finding suggestions, progress UI.

⚠️ Breaking

  • Scope flags collapsed into commitbrief diff <args...>. --commit <hash>, --branch <name>, and --pull-request <range> are gone. Replacement table:

    v0.xv0.9
    commitbrief --commit HEAD~1commitbrief diff HEAD~1
    commitbrief --branch maincommitbrief diff main
    commitbrief --pull-request main...xcommitbrief diff main...x

    --staged and --unstaged unchanged. The diff subcommand forwards verbatim to git diff <args>, so any range git understands works.

  • Single-path --file scope flag replaced by the repeatable global --file/--dir filter pair.

  • Provider.ReviewStream removed from the provider interface. Streaming has been dead since ADR-0014 took the review path off it in v0.6.0; the plumbing is now gone. Third-party packages importing Provider need to drop the field.

Added

  • CLI-tool-backed providers — claude-cli, gemini-cli (experimental). Drive the user’s locally-installed Claude Code or Gemini CLI as the review backend via subprocess. No API key when the host CLI is already authenticated. Cost is whatever the user’s CLI subscription bills. Cache key includes the host CLI version so upgrades cleanly invalidate prior entries.

  • Per-finding suggestion field — required actionable remediation. Every finding carries a 2–3 sentence concrete fix recommendation alongside title/description. Rendered in Cards (chevron-prefixed paragraph), OUTPUT.md (→ {{ .Suggestion }} block), JSON ("suggestion", required), and the --copy clipboard payload.

  • commitbrief diff <args...> subcommand — git-diff passthrough for arbitrary historic ranges. Args forwarded verbatim to git diff --no-color --no-ext-diff.

  • Global --file / -f and --dir / -d flags — path filters applied post-parse, repeatable, work on any scope.

  • commitbrief cache prune subcommand. Bounded cleanup with defaults --keep-last 500 --older-than 7d; both windows must be satisfied for an entry to survive. --provider/--model narrow the candidate pool.

  • Multi-line findings via line_end (schema-additive). Finding payloads can carry line_end alongside line to mark spans; renderers show file:start-end instead of file:start. Backward-compatible.

  • --copy flag — pushes a plain-text summary of the findings onto the system clipboard via OSC 52 escape (works over SSH) and native shellout (pbcopy / wl-copy / xclip / xsel / clip.exe).

  • Progress animation during the review pipeline — four-stage tree with breathing-dot animation. Three operating modes: animated (TTY + colors), plain (CI logs), silent (--quiet).

Changed

  • Tightened snippet contract in the system prompt so findings stop showing invented code excerpts — max 6 lines, verbatim from the diff, no hunk headers, omit when not materially clarifying.
  • Severity chip glyphs swapped to emoji for stronger visual cues: 💥 CRITICAL, 🚨 HIGH, ⚡ MEDIUM, 📌 LOW, 💡 INFO.
  • Diff aggregate cachingDiff.AddedLines() / DeletedLines() switched to O(1) memoized reads.

Finding card visual overhaul — per-severity themes, fixed-width panels, sign-aligned wrapping.

Changed

  • Finding card design ported verbatim from the maintainer’s secguard reference. Replaces the v0.8.0 visual layer end-to-end. Each severity now ships its own dark theme — panel background, border, accent color, chip label:

    • ⊘ CRITICAL on #1A1116 / border #602B38 / chip #ff6b8a
    • ⚠ HIGH on #1A1511 / border #603F2B / chip #ffa86b
    • ● MEDIUM on #1A1A11 / border #5A5A2B / chip #f0d050
    • ○ LOW on #11161A / border #2B4760 / chip #6bb8ff
    • ℹ INFO on #11181A / border #2B5560 / chip #6be0e0

    Diff lines render as full-row strips with sign-column padding so removed/added/context lines read as colored bands.

  • Fixed inner content width of 96 columns. Long descriptions and snippets wrap to panel-bg-filled continuation rows via lipgloss Width() instead of expanding the card past the terminal edge. Diff lines wrap with the sign-column preserved, so -/+ continuation rows stay aligned.

  • Border blends with panel background via BorderBackground(bg) so the rounded corners share the severity-tinted bg — the card reads as one continuous block.

  • Code-fence noise removed. Snippet rendering no longer wraps the excerpt in literal triple-backtick fences. The diff-coloured strips already mark the region as code.

Quality & diagnostics. `doctor`, `install-hook`, secret scanner, cost preflight, `--fail-on`, `--compact`.

Added

  • commitbrief install-hook subcommand — one-command scaffold for a git hook running commitbrief --staged --fail-on=critical --quiet --no-cost-check on every commit. Default target .git/hooks/pre-commit; --hook chooses commit-msg or pre-push. Existing files refused unless --yes; prior content backed up to <name>.bak.<timestamp>. --uninstall removes the hook only when the embedded marker is present.
  • --fail-on=<severity> flag — CI-actionable exit code gate. Accepted values: critical, high, medium, low, info, any, none. The rendered review prints before the exit code is decided.
  • commitbrief doctor subcommand — runs ~7 health checks against the resolved environment: git binary, config schema, COMMITBRIEF.md source, OUTPUT.md template validity, active provider credentials, cache writability, .gitignore includes .commitbrief/. Per-check ✓/⚠/✗ glyphs; exit 1 on any failure.
  • Pre-send secret scanner. Eight patterns ship by default (AWS, GitHub, GitLab, OpenAI, Anthropic, JWT, Stripe, PEM private key). Only + prefixed (newly added) lines are scanned; the matched substring is never echoed to stderr or any cached payload. --allow-secrets bypasses with an info notice.
  • Cost preflight — before each fresh provider call, estimates cost from prompt tokens × per-model pricing. Above cost.warn_threshold_usd (default $0.50), prompts the user on a TTY or aborts non-interactively. New --no-cost-check flag.
  • commitbrief list config summary footer — shows active provider/model, source of COMMITBRIEF.md and OUTPUT.md, and local cache footprint.
  • --compact flag for one-line-per-finding rendering — [icon] SEVERITY • file:line — title.

Changed

  • Diff-colored snippets — when a finding includes a code excerpt with - / + prefixed lines, the renderer colors removals red and additions green; context stays muted.
  • High-contrast card text — adaptive foreground (near-white on dark terminals, near-black on light) fixes legibility against severity-tinted backgrounds.

Multi-provider UX. `providers` and `config` subcommands; rich finding panel polish.

Added

  • commitbrief providers subcommand for multi-provider workflows without hand-editing YAML.
    • providers list — every configured + registered provider, marking the active one and showing model + masked API-key fingerprint (or base URL for Ollama).
    • providers use <name> — flip the active default; preserves every API key, model, and base URL across the switch.
    • providers test <name> — call TestConnection and report success + latency.
  • commitbrief config subcommand for one-line edits.
    • config show — dump the merged config as YAML with API keys masked.
    • config get <key> — read a single field by dotted path.
    • config set <key> <value> — write a single field with type coercion and validation (booleans, integers with bounds, enums, registered providers).

Changed

  • Rich finding panels — visual polish of the Cards Stage B layout from v0.6.0:
    • Rounded borders (╭ ╮ ╰ ╯) replace square corners.
    • Severity-tinted backgrounds via lipgloss.AdaptiveColor.
    • Severity icons prefix the badge — critical, high, medium, low, info.
    • Bullet separator () between badge and file:line.
  • --version output no longer double-prints "commitbrief version commitbrief X.Y.Z" — cobra’s default template was overridden.

Fixed

  • commitbrief setup no longer wipes previously-configured API keys. Running setup a second time to add another provider used to overwrite the entire config from defaults; the wizard now loads the existing config and layers the new provider on top.

Structured findings JSON. OUTPUT.md becomes a Go template — breaking change.

⚠️ Breaking — OUTPUT.md semantics (ADR-0014)

  • COMMITBRIEF.md users are unaffected. Project review rules remain the user-editable system prompt.
  • OUTPUT.md is now a Go text/template consumed locally, not a format instruction embedded in the LLM prompt. The model produces structured findings JSON under a fixed schema; the renderer applies your OUTPUT.md to those findings for --markdown and --output <file>.md. Pre-0.6.0 OUTPUT.md files written as natural-language instructions fail the pre-send validation guard.
  • Migration: run commitbrief init --yes to overwrite OUTPUT.md with the new embedded default, or rewrite it in text/template syntax.
  • Severity vocabulary expanded to five levels (was three): critical, high, medium, low, info.
  • Old local cache entries auto-invalidated because the system prompt SHA is part of the cache key.

Added

  • Structured findings JSON contract between LLM and renderer. Every provider uses its native structured-output mechanism: Anthropic tools, OpenAI strict response_format, Gemini ResponseSchema, Ollama format: "json".
  • Retry-once + graceful degrade. Unparseable LLM output triggers one retry; second failure degrades to plain-text with a stderr warning. Cache entries record the fallback mode.
  • Per-finding Cards layout (Stage B). Each finding renders as a lipgloss-bordered panel coloured by severity. Empty case shows a single green-checkmark “No findings. Looks good.” panel.
  • render.ValidateOutputTemplate pre-send guard — malformed templates fail with a clear error pointing at the file.

Scope expansion. Every review scope advertised in `list` works end-to-end; JSON output locked at schema v1.

Added

  • --commit <hash> review scope with merge-commit handling: when the requested hash has two or more parents, the diff is taken against the first parent only and a stderr warning suggests --pull-request <target>...<feature> for full branch comparison.
  • --branch <target> and --pull-request <target>...<feature> review scopes — backend was already wired; this release adds the integration test coverage.
  • Mutually exclusive scope flags. Passing two scope flags at once (--staged --unstaged) fails before the pipeline runs.
  • lang.SourceCLIFlag — new Source enum value so --lang overrides are attributed correctly in dry-run output instead of being mislabeled SourceRepoConfig.
  • Drift-guard golden test for --json output. Byte-exact fixture at internal/render/testdata/json/v1.golden; any rename, type change, or removal trips the test.

Changed

  • CLI user-facing strings routed through i18n.Catalog.T(). Sixteen new keys cover the action paths (init, review, compress, setup); Turkish translations ship for every key. %w error wrappers and tabular dry-run output stay English by design.
  • JSON schema v1 policy documented. Additive changes are not a version bump; renames, removals, or type changes require schema version 2 + a CHANGELOG entry. Shape unchanged from v0.4.0: {schema, content, findings, summary, meta}.

Fixed

  • Windows golden-file test now passes regardless of core.autocrlf.gitattributes pins text files to LF in the working tree.

First public release. Homebrew, Scoop, and `go install` ship working.

Added

  • commitbrief compress with three embedded prompts (light, balanced, aggressive). Atomic apply via temp + rename, backup at .commitbrief/backups/COMMITBRIEF-<timestamp>.md, refuses to apply when the result isn’t smaller. --out <path> writes elsewhere without touching the original.

Changed

  • Verbose footer relabels Cost: to Saved: on local cache hits (no provider call was made; the figure is what would have been spent).
  • Token line distinguishes provider prompt cache (provider cached: N) from CommitBrief’s local response cache (local cache hit).
  • dry-run reports per-layer filter counts; list documents the three-layer filtering pipeline.
  • Release pipeline goes live — Homebrew tap and Scoop bucket auto-publish.

Tests

Cumulative coverage rose from 64.7% → 77.8%. ~36 new tests across compress, render, CLI integration, provider streaming, and git dispatcher paths.

v0.2.0

May 17, 2026 prerelease permalink ↗

Provider matrix — OpenAI, Gemini, and Ollama join Anthropic.

Added

  • OpenAI providergpt-4o, gpt-4o-mini via the official github.com/openai/openai-go SDK. Honors automatic prompt caching at ≥1024-token prefixes; cached tokens reported via usage.prompt_tokens_details.cached_tokens.
  • Google Gemini providergemini-2.5-pro (2 M context), gemini-2.5-flash, gemini-1.5-flash via the unified google.golang.org/genai SDK. cachedContentTokenCount surfaced.
  • Ollama provider — local-only HTTP client against /api/chat and /api/tags. No SDK, no API key. TestConnection pings /api/tags rather than spending inference time on a real completion.
  • commitbrief setup now cycles through all four providers.

Changed

  • Default Gemini model bumped from gemini-1.5-pro to gemini-2.5-pro.

Private repository; no public artifacts.

v0.1.0

May 16, 2026 prerelease permalink ↗

Walking-skeleton release — Anthropic provider, staged-diff review, cache.

Added

Commands

  • commitbrief init — write the team-shared COMMITBRIEF.md and the per-user .commitbrief/OUTPUT.md template.
  • commitbrief setup [--local] — interactive provider + API key wizard.
  • Review scopes: --staged (default), --unstaged, --file, --commit, --pull-request, --branch.
  • commitbrief dry-run — pipeline preview without an API call.
  • commitbrief list — markdown command reference.

Core modules

  • Hybrid go-git + git CLI access; unified-diff parser; three-layer ignore matcher; pre-send guard for .commitbrief/**; provider abstraction with Anthropic + mock implementations; SHA-256 response cache (7-day TTL); two-tier YAML config with field-level merge; English + Turkish i18n catalogs; terminal/markdown/JSON renderers; ldflags-injected version metadata.

Known limitations

  • Only the Anthropic provider is implemented; OpenAI/Gemini/Ollama land in v0.2.0.
  • commitbrief compress is a stub; full implementation in v0.3.0.
  • Reviews are returned non-streaming; streaming arrives in v0.4.0.

Private repository; no public artifacts.