// docs · v1.x

Output formats

Cards, JSON, markdown, --copy, --compact, --verbose — every way CommitBrief renders review findings.

Updated September 24, 2026

CommitBrief renders review findings in three primary forms. The choice is driven by global output flags; if none are set and the destination is a TTY, the colored cards renderer is the default.

Cards (default TTY)

Lipgloss-styled header / status / footer with one panel per finding. Each panel is severity-coded (color of the left border) and includes the finding’s title, location, description, suggestion, and a code snippet when present.

Triggered when: TTY stdout AND no --json / --markdown flag AND --color resolves to ON.

This is the format you see in your terminal during a normal commitbrief --staged session. The output is not designed to be parsed; it is designed to be read.

Markdown

Plain markdown — no ANSI escapes, no lipgloss boxes. The same finding content rendered through the OUTPUT.md template (or its embedded default).

Triggered by --markdown, by --color=never, or by a non-TTY stdout. The bare commitbrief --staged > review.md path also produces markdown.

The template has access to .Findings (typed []Finding{Severity, File, Line, LineEnd, Title, Description, Suggestion, Language, Snippet}) plus helpers like groupBySeverity, upper, countFiles. See OUTPUT.md for the template reference.

JSON (schema v1)

Strict machine-readable form. Top-level shape:

{
  "schema": 1,
  "content": "",
  "findings": [
    {
      "severity": "high",
      "file": "internal/handlers/auth.go",
      "line": 42,
      "line_end": 56,
      "title": "Missing authorization check on admin route",
      "description": "...",
      "suggestion": "...",
      "language": "go",
      "snippet": "..."
    }
  ],
  "summary": {},
  "meta": {
    "provider": "anthropic",
    "model": "claude-opus-5-5",
    "lang": "en",
    "usage": { "input_tokens": 2105, "output_tokens": 526, "cached_input_tokens": 0 },
    "cost_usd": 0.0237,
    "latency_ms": 4123,
    "cached": false,
    "timestamp": "2026-07-26T12:00:00Z"
  }
}

Triggered by --json. Bypasses cards / markdown renderers entirely. schema is the integer 1 — not the string "v1" — and follows strict semver: additive changes (new optional fields) are allowed within the same schema major version; renames, removals, or type changes require a schema major bump. summary is a reserved placeholder and is always {} in v1; there is no per-severity count anywhere in the document except by counting findings[] yourself.

Field reference

Every top-level and required field in schema v1. The five additive-optional meta fields below this table are covered in Optional meta fields — they’re all omitempty and only appear when they have something to report.

Top-level document

FieldTypeRequired?Meaning
schemaintegerrequiredAlways 1 in schema v1.x. Parse this field first; refuse a document reporting a version you don’t understand.
contentstringrequiredEmpty on the happy path. Populated with the raw model response only when the review gracefully degrades (unparseable structured output). Vestigial — slated for removal in schema v2.
findingsarray of Findingrequired[], never null, on a clean or degraded review. Unfiltered: --min-severity never touches this array.
summaryobjectrequiredAlways {} in v1. Reserved for a future model-authored prose summary.
metaobjectrequiredProvider, cost, and timing metadata — see below.

findings[] item (Finding)

FieldTypeRequired?Meaning
severitystringrequiredOne of critical, high, medium, low, info.
filestringrequiredRepo-relative path.
lineintegerrequired1-based start line.
line_endintegeroptionalPresent only when the finding spans more than one line.
titlestringrequiredOne sentence.
descriptionstringrequired1–3 sentences: the issue and its impact.
suggestionstringrequired2–3 sentence concrete fix. An empty suggestion triggers the retry-then-degrade path rather than shipping.
languagestringoptionalPresent when the finding’s language is known.
snippetstringoptionalVerbatim diff excerpt, ≤6 lines, diff-prefixed. Always omitted for a leaks credential finding — populating it would echo the secret.

meta — base fields

FieldTypeRequired?Meaning
providerstringrequirede.g. anthropic. builtin for a leaks --json report — no model was called.
modelstringrequirede.g. claude-opus-5-5. secret-scan for leaks.
langstringrequiredOutput language code.
usage.input_tokensintegerrequired0, never omitted, on a cache hit or when the provider doesn’t report usage.
usage.output_tokensintegerrequiredSame 0-not-null rule as input_tokens.
usage.cached_input_tokensintegerrequiredSame 0-not-null rule.
cost_usdnumberrequired0 on a cache hit, for Ollama, and for any CLI-tool-backed provider.
latency_msintegerrequiredCall latency in milliseconds.
cachedbooleanrequiredWhether this document is a cache replay rather than a live call.
timestampstringrequiredRFC 3339.

Optional meta fields

Every field below is omitempty: it is absent unless it has something to report, so a clean review’s JSON is byte-for-byte what it was before these shipped, and the schema stays 1.

FieldRequiresMeaning
meta.baselinedRequires v1.8.0 or laterFindings removed by the baseline.
meta.suppressedRequires v1.8.0 or laterFindings removed by an inline commitbrief-ignore.
meta.retry_countRequires v1.13.0 or laterHow many structured-output repair retries the call needed. Live calls only — a cache replay reports neither this nor degrade_reason.
meta.degrade_reasonRequires v1.13.0 or laterWhy the pipeline fell back to plain markdown, when it did (e.g. malformed-json).
meta.filtered_commitsRequires v1.15.0 or laterHow many commits’ patches make up the reviewed diff, when a commit filter walked history.

--verbose surfaces retry_count and degrade_reason as two footer lines as well, which is what makes retries and degrades comparable across models.

A leaks --json report uses this same document with meta.provider: "builtin" and cost_usd: 0 — there was no model call — which is why guard --from-json consumes it without any new plumbing.

CLI-tool-backed providers — plain text passthrough

claude-cli, gemini-cli, and codex-cli emit pre-formatted plain text from the host CLI, not structured findings. The cards renderer is skipped; the host CLI’s output is streamed verbatim to stdout (or to --output <file>). --json and --markdown are rejected upfront when paired with a CLI provider — cobra error before any work runs. See CLI providers.

Output destinations

FlagEffect
--output <path> (-o)Write the rendered output to a file. Applies to cards, markdown, JSON, AND plain-text emit (CLI providers).
--copyCopy a finding summary to the system clipboard via OSC 52 (works over SSH) plus native tools (pbcopy / wl-copy / xclip / xsel / clip.exe). Payload format per finding: [<icon> <SEVERITY>] <path>:<line>\n<title>\n\n<description>\n\n→ <suggestion>, joined with \n---\n\n. Description and suggestion are flattened to single paragraphs and the diff snippet is left out.
--compactDense one-line-per-finding output: [icon] SEVERITY • file:line — title. Works in cards and markdown modes.
--min-severity <level>Display-only filter: hide findings below <level> in the rendered output (cards, markdown, --copy). --json stays complete and --fail-on still evaluates the full set. See Severity.
--verbose (-v)Append a footer with provider / model / tokens / cost / latency.
--quiet (-q)Suppress stderr info messages (progress, rule-source hints).

--json is a renderer choice, not a destination choice; the JSON still goes to stdout (or --output <file>). Combine flags freely:

commitbrief --staged --json --output review.json --quiet

Color resolution

Default --color=auto:

  • TTY stdout + no NO_COLOR env + no COMMITBRIEF_NO_COLOR env + TERM not set to dumb → color ON.
  • Otherwise → color OFF.

--color=always forces ON, except that NO_COLOR / COMMITBRIEF_NO_COLOR still turn color off (TERM=dumb does not override it); --color=never forces OFF unconditionally. Color OFF in cards mode falls back to markdown.

Suggesting a commit message

--suggest-commit adds a second step after the review: a free-form provider call that prints one Conventional Commit message for the staged diff to stdout.

commitbrief --staged --suggest-commit
  • Read-only. It suggests; you commit. CommitBrief never writes to git or the working tree.
  • Staged scope only. Works with --staged or the default run; rejected with --unstaged, the diff subcommand, and with --json / --markdown / --output (the suggestion is plain stdout, not part of the structured or file output).
  • Any provider. API providers return the message via a free-form path (no JSON contract for this one call); CLI-tool providers emit it directly.
  • The message follows Conventional Commits (type(scope): subject plus an optional body). Your COMMITBRIEF.md rules govern the critique, not the message wording.
  • The suggestion is a fresh call each run (not cached); the review itself still uses the cache.

The colored splash logo prints to stderr at the start of every invocation, gated on a TTY-capable stderr. It is NOT part of stdout — commitbrief --json | jq and commitbrief > out stay clean. To suppress it entirely, set NO_COLOR=1 in the environment.

See also