Skip to content

OUTPUT md

Muhammet Şafak edited this page May 28, 2026 · 2 revisions

Home / Output / OUTPUT.md

OUTPUT.md

A per-user Go text/template that controls how findings are formatted locally. Applied to the parsed findings JSON to produce the markdown output for --markdown and --output <file>.md. Never sent to the LLM.

Where it lives

CommitBrief looks in this order (first hit wins):

  1. <repo-root>/.commitbrief/OUTPUT.md — per-repo override.
  2. <user-home>/.commitbrief/OUTPUT.md — per-user default.
  3. Embedded default at internal/rules/output.md.

A repo-local OUTPUT.md is gitignored by default (the .commitbrief/ directory is added to the repo .gitignore on first use). This makes OUTPUT.md a personal preference rather than a team artifact.

Scaffolding

commitbrief init

Writes the embedded default to <repo>/.commitbrief/OUTPUT.md. See Init command for force/skip semantics.

Format

Plain Go text/template. The template data is:

type TemplateData struct {
    Findings []Finding
}

type Finding struct {
    Severity    string
    File        string
    Line        int
    LineEnd     int
    Title       string
    Description string
    Suggestion  string
    Language    string
    Snippet     string
}

Inside the template, .Findings is a typed slice over which you range:

{{ range .Findings }}
- **{{ upper .Severity }}** {{ .File }}:{{ .Line }} — {{ .Title }}
  {{ .Description }}
  > {{ .Suggestion }}
{{ end }}

Available functions

Exposed via render.TemplateFuncs():

Function Signature Purpose
upper string → string strings.ToUpper.
lower string → string strings.ToLower.
groupBySeverity []Finding → map[Severity][]Finding Bucket findings by severity. Keys: critical, high, medium, low, info.
countFiles []Finding → int Count distinct files touched by the finding set.

The set is the public template contract (ADR-0014 §2); additions are allowed in v1.x, removals require a schema bump.

All built-in text/template actions also work — range, if, with, len, printf, etc.

Pre-send validation

If you write a custom OUTPUT.md and the template is malformed, CommitBrief catches it before any provider call (ADR-0014 §5). Three checks run on load:

  1. Parse — text/template syntax check.
  2. Empty-findings execute — template runs against an empty []Finding{}.
  3. Sample-findings execute — template runs against a synthetic sample of one finding per severity.

A failure aborts the run with: OUTPUT.md template is invalid at <path>:\n <error>\n\nThe pipeline did not contact the provider. Fix the template, or run 'commitbrief init --yes' to overwrite it with the default.

The embedded default is presumed-valid via the release-check script, so the runtime guard fires only on user-written templates.

Example

Minimal grouping-by-severity template:

{{ $bucketed := groupBySeverity .Findings }}
# Review summary

Files touched: {{ countFiles .Findings }}

{{ with index $bucketed "critical" }}
## Critical
{{ range . }}
- **{{ .File }}:{{ .Line }}** — {{ .Title }}
  {{ .Description }}
  > {{ .Suggestion }}
{{ end }}
{{ end }}

{{ with index $bucketed "high" }}
## High
{{ range . }}
- **{{ .File }}:{{ .Line }}** — {{ .Title }}
{{ end }}
{{ end }}

What OUTPUT.md does NOT do

  • It does NOT affect the LLM prompt or the review behavior at all.
  • It does NOT affect --json output (the JSON schema is fixed).
  • It does NOT apply to the cards renderer (that has its own lipgloss-styled layout).
  • It does NOT apply to CLI-tool-backed providers (claude-cli / gemini-cli emit pre-formatted text directly).

See also

Clone this wiki locally