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-cliandgemini-cliproviders 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 —--outputroutes 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 viascripts/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 checktarget. Runs every guard CI runs, in CI order, bailing on the first failure. Single entry-point for “is this push-ready?”. -
COMMITBRIEF_CONFIGenvironment variable documented. Setting it to an absolute path replaces the default~/.commitbrief/config.ymllookup — useful for ephemeral CI environments and reproducible tests.
Changed
Diff.IsMergefield andcli.warn.merge_commitcatalog 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 asgit 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.MaxInt32would 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.DiffHashandKeyMeta.SystemPromptHashcarry 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
$PATHthat typically omits/opt/homebrew/bin, soexec commitbrief --staged …silently failed to launch.install-hooknow resolves the running binary viaos.Executable+filepath.EvalSymlinksand embeds the result as a single-quoted token. Survivesbrew 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 only —
commitbrief --json | jqand--markdown > filestay 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 thelangNamesmap advertised 15 languages for which we never shipped translations —i18n.Loadsilently fell through to English, so the dry-run footer claimingLang: Deutschwas a lie.Resolvenow coerces any unsupported code (output.lang: de,--lang fr,LANG=es_ES) toenwhile preserving the originalSourcefor attribution.
Changed
-
CLI providers respect
--output. The plain-text emit path used by--cli claude/--cli gemininow routes through the sameopenOutputhelper the structured renderers use, so--cli claude --output review.mdwrites 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 invokesclaude -p -and pipes the prompt via stdin. gemini-cli stays on argv for now — upstream lacks a documented stdin shorthand. -
DefaultModelfor CLI providers is memoised + bounded. The cache-key path queriesDefaultModelon every review; before it re-shelled out to<cli> --versioneach 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
-
--cliis mutually exclusive with--jsonand--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-runnow 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 diffaccepts pathspecs and >2 args. The subcommand used to cap at two positional args, rejecting legitimategit diff <ref> -- <pathspec>invocations.MinimumNArgs(1); everything past the first arg is forwarded verbatim. -
ui.EnableANSIis now called fromExecute. 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.Scanneroveros.Stdin; the first scanner’s lookahead could swallow input meant for the next site. A single*bufio.Readeris 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
-
--yesno 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--yesto skip the guard prompt. Use the dedicated bypasses:--allow-secretsfor the scanner,--no-cost-checkfor the preflight. -
cache.max_size_mbconfig field removed. Defined in the struct and surfaced viaconfig 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 doctornow verifies that the currently selected provider has its own credentials — not just that some provider does. Closes a gap where settingprovider: openaiwhile onlyanthropic.api_keywas configured would pass doctor but fail every review. -
Localised confirm vocabulary, guard prompt, and setup wizard. Catalog drives accept-vocabulary (
y/yesin EN,e/evetin TR), the[y/N]/[e/H]suffix, the.commitbrief/guard warning, and every label incommitbrief setup.
Added
-
Rules content secret scan. The pre-send secret scanner now inspects user-authored
COMMITBRIEF.mdandOUTPUT.mdcontent 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.enabledandcache.ttl_daysare now honored. Previously defined but inert.
Fixed
-
install-hook --hook=pre-pushships a real pre-push body. Previously every hook variant got the same--stagedinvocation, which silently no-op’d at push time. The new pre-push script parses git’s per-ref stdin protocol and runscommitbrief diff <remote-sha>..<local-sha> --fail-on=criticalper ref. Push blocks on the first critical finding. -
initno 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 --forceis 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.x v0.9 commitbrief --commit HEAD~1commitbrief diff HEAD~1commitbrief --branch maincommitbrief diff maincommitbrief --pull-request main...xcommitbrief diff main...x--stagedand--unstagedunchanged. Thediffsubcommand forwards verbatim togit diff <args>, so any range git understands works. -
Single-path
--filescope flag replaced by the repeatable global--file/--dirfilter pair. -
Provider.ReviewStreamremoved 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 importingProviderneed 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
suggestionfield — 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--copyclipboard payload. -
commitbrief diff <args...>subcommand — git-diff passthrough for arbitrary historic ranges. Args forwarded verbatim togit diff --no-color --no-ext-diff. -
Global
--file/-fand--dir/-dflags — path filters applied post-parse, repeatable, work on any scope. -
commitbrief cache prunesubcommand. Bounded cleanup with defaults--keep-last 500 --older-than 7d; both windows must be satisfied for an entry to survive.--provider/--modelnarrow the candidate pool. -
Multi-line findings via
line_end(schema-additive). Finding payloads can carryline_endalongsidelineto mark spans; renderers showfile:start-endinstead offile:start. Backward-compatible. -
--copyflag — 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 caching —
Diff.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
secguardreference. 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:⊘ CRITICALon#1A1116/ border#602B38/ chip#ff6b8a⚠ HIGHon#1A1511/ border#603F2B/ chip#ffa86b● MEDIUMon#1A1A11/ border#5A5A2B/ chip#f0d050○ LOWon#11161A/ border#2B4760/ chip#6bb8ffℹ INFOon#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-hooksubcommand — one-command scaffold for a git hook runningcommitbrief --staged --fail-on=critical --quiet --no-cost-checkon every commit. Default target.git/hooks/pre-commit;--hookchoosescommit-msgorpre-push. Existing files refused unless--yes; prior content backed up to<name>.bak.<timestamp>.--uninstallremoves 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 doctorsubcommand — runs ~7 health checks against the resolved environment: git binary, config schema, COMMITBRIEF.md source, OUTPUT.md template validity, active provider credentials, cache writability,.gitignoreincludes.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-secretsbypasses 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-checkflag. commitbrief listconfig summary footer — shows active provider/model, source of COMMITBRIEF.md and OUTPUT.md, and local cache footprint.--compactflag 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 providerssubcommand 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>— callTestConnectionand report success + latency.
commitbrief configsubcommand 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 andfile:line.
- Rounded borders (
--versionoutput no longer double-prints"commitbrief version commitbrief X.Y.Z"— cobra’s default template was overridden.
Fixed
commitbrief setupno 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.mdusers are unaffected. Project review rules remain the user-editable system prompt.OUTPUT.mdis now a Gotext/templateconsumed 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--markdownand--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 --yesto overwrite OUTPUT.md with the new embedded default, or rewrite it intext/templatesyntax. - 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 strictresponse_format, GeminiResponseSchema, Ollamaformat: "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.ValidateOutputTemplatepre-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— newSourceenum value so--langoverrides are attributed correctly in dry-run output instead of being mislabeledSourceRepoConfig.- Drift-guard golden test for
--jsonoutput. Byte-exact fixture atinternal/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.%werror 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—.gitattributespins text files to LF in the working tree.
First public release. Homebrew, Scoop, and `go install` ship working.
Added
commitbrief compresswith 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:toSaved: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-runreports per-layer filter counts;listdocuments 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.
Provider matrix — OpenAI, Gemini, and Ollama join Anthropic.
Added
- OpenAI provider —
gpt-4o,gpt-4o-minivia the officialgithub.com/openai/openai-goSDK. Honors automatic prompt caching at ≥1024-token prefixes; cached tokens reported viausage.prompt_tokens_details.cached_tokens. - Google Gemini provider —
gemini-2.5-pro(2 M context),gemini-2.5-flash,gemini-1.5-flashvia the unifiedgoogle.golang.org/genaiSDK.cachedContentTokenCountsurfaced. - Ollama provider — local-only HTTP client against
/api/chatand/api/tags. No SDK, no API key.TestConnectionpings/api/tagsrather than spending inference time on a real completion. commitbrief setupnow cycles through all four providers.
Changed
- Default Gemini model bumped from
gemini-1.5-protogemini-2.5-pro.
Private repository; no public artifacts.
Walking-skeleton release — Anthropic provider, staged-diff review, cache.
Added
Commands
commitbrief init— write the team-sharedCOMMITBRIEF.mdand the per-user.commitbrief/OUTPUT.mdtemplate.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+gitCLI 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 compressis a stub; full implementation in v0.3.0.- Reviews are returned non-streaming; streaming arrives in v0.4.0.
Private repository; no public artifacts.