// docs · v1.x

Configuration

Two-tier YAML config, environment variables, the config subcommand, and every key CommitBrief reads at runtime.

CommitBrief uses a two-tier YAML configuration with field-level merge — config.Default() skeleton → user config → repo-local config → environment variables → CLI flags. Each layer overrides the previous per-field, not whole-file.

Files

Tier Path Notes
User-level ~/.commitbrief/config.yml Defaults that apply everywhere. Override path with COMMITBRIEF_CONFIG.
Repo-local <repo>/.commitbrief/config.yml Per-repo overrides. Gitignored — .commitbrief/ is auto-added to repo .gitignore on first write.

Either file may be absent; a built-in skeleton fills the gap so a fresh commitbrief setup works without preexisting files.

The schema

version: 1                                # config schema version
provider: anthropic                       # active provider
providers:
  anthropic:
    api_key: sk-ant-...                   # secret; mode 0600 on disk
    model: claude-opus-4-8
  openai:
    api_key: sk-...
    model: gpt-4o
    pricing:                              # optional: override built-in $/1M rates (OQ-09)
      gpt-4o:
        input_per_1m: 2.50
        output_per_1m: 10.00              # omitted/zero fields keep the built-in value
        cached_input_per_1m: 1.25
  gemini:
    api_key: AIza...
    model: gemini-2.5-pro
  deepseek:
    api_key: sk-...                       # + mistral, cohere (OpenAI-compatible)
    model: deepseek-chat
  ollama:
    base_url: http://localhost:11434
    model: qwen2.5-coder:14b
  claude-cli:
    model: ""                             # ignored — host CLI manages selection
  gemini-cli:
    model: ""
  codex-cli:
    model: ""                             # ignored — host CLI manages selection
output:
  lang: en                                # supported: en | tr
  color: auto                             # auto | always | never
cache:
  enabled: true                           # false skips reads + writes entirely
  ttl_days: 7                             # entry expiry; 0 → DefaultTTL (7 days)
  max_size_mb: 0                          # on-disk cap; 0 = unlimited; >0 evicts oldest first
guard:
  secret_scan: true                       # false disables the credential scanner
  secret_patterns:                        # additive user regexes on top of the built-ins (config-file only)
    - name: Acme Internal Token
      pattern: 'acme_[A-Za-z0-9]{32}'
  injection_scan: true                    # scan a custom COMMITBRIEF.md/OUTPUT.md for prompt-injection phrasing (warn, never abort)
  token_preflight: false                  # opt-in: confirm/abort when the prompt exceeds the model's context window
review:
  flaky: true                             # deterministic flaky-test detector; false disables (= --no-flaky)
  sandbox_rerun: 0                        # opt-in flaky sandbox-rerun: re-run a flagged test N times to confirm; 0 = off (= --sandbox-rerun[=N])
  baseline: true                          # honor the user-private .commitbrief/baseline.json; false disables (= --no-baseline)
  architecture: true                      # architecture-aware review: read architecture.json into the prompt; false disables (= --no-architecture)
  architecture_file: ""                   # override the architecture.json discovery path; empty = auto-discover at repo root
cost:
  warn_threshold_usd: 0.50                # prompt-or-abort above this; <=0 disables
command:
  default: ""                             # args for a bare `commitbrief`; empty = --staged

Per-field reference

Dotted path Type Default Notes
provider string anthropic Active provider. Must match a registered provider name.
providers.<name>.api_key string "" Provider API key. Not used by ollama, claude-cli, gemini-cli.
providers.<name>.model string "" Provider-specific model. Empty → provider’s DefaultModel().
providers.<name>.base_url string (provider default) Override the API endpoint. Used by ollama (http://localhost:11434) and the OpenAI-compatible providers.
providers.<name>.pricing.<model>.input_per_1m float (built-in) Override the input rate ($/1M tokens) for one model. Zero/omitted → built-in snapshot.
providers.<name>.pricing.<model>.output_per_1m float (built-in) Override the output rate ($/1M tokens).
providers.<name>.pricing.<model>.cached_input_per_1m float (built-in) Override the cached-input rate ($/1M tokens).
output.lang string en AI output language — any recognized language (e.g. en, tr, fr, de, ja). The CLI interface localizes only for en/tr (English otherwise), so --lang fr gives a French review with an English interface. Resolution: --lang → repo → user → English; invalid/empty falls through. Validated by config set.
output.color string auto auto / always / never. --color flag overrides.
cache.enabled bool true false skips both reads and writes.
cache.ttl_days int 7 Days until expiry. 0 → 7 days. Cannot be negative.
cache.max_size_mb int 0 On-disk cache cap in MiB. 0 = unlimited. When >0, each write past the cap evicts the oldest entries first (the just-written entry is never evicted). Cannot be negative. Inspect with cache stats / cache inspect.
guard.secret_scan bool true false disables the credential scanner.
guard.secret_patterns list [] Additive user regexes (name + pattern) layered on top of the eight built-ins (v1.7.0). Built-ins always run and can’t be shadowed; an invalid regex aborts before the provider call. Config-file only — config set rejects it. See Safety and cost.
guard.injection_scan bool true When true (v1.7.0), a custom COMMITBRIEF.md/OUTPUT.md is scanned for prompt-injection phrasing; a match prints a non-blocking warning and the review continues. See Safety and cost.
guard.token_preflight bool false Opt-in (v1.4.0). When true, a review whose estimated prompt exceeds the model’s context window prompts (TTY) or aborts (non-TTY) before the paid call. See Safety and cost.
review.flaky bool true Deterministic flaky-test detector (v1.7.0). When true, a provider-free pre-pass flags timing/randomness anti-patterns in changed tests and merges them into the findings. false (or per-run --no-flaky) disables it. API providers only. See Flaky-test detector.
review.sandbox_rerun int 0 Opt-in sandbox-rerun confirmation for the flaky detector (v1.12.0). 0 = off; >0 re-runs each statically flagged test in isolation that many times and classifies it (mixed → confirmed flaky, all-fail → real failure, all-pass → demoted to info). Per-run --sandbox-rerun[=N] overrides (bare flag = 5). Reserved no-op until a test runner is bound. See Flaky-test detector.
review.baseline bool true Honor the user-private .commitbrief/baseline.json (v1.8.0). When true, findings recorded by --update-baseline are dropped from later runs so only new ones surface. false (or per-run --no-baseline) ignores the baseline. The file is gitignored and never propagates — it can’t weaken CI or hide a bug from review. See Signal control.
review.architecture bool true Architecture-aware review (v1.11.0). When true, the repo’s architecture.json (the archlint config) is read and a summary of its layers + allowed/forbidden import edges is folded into the review prompt. false (or per-run --no-architecture) skips it. A one-way read — CommitBrief never lints or enforces. See Architecture-aware review.
review.architecture_file string "" Override the architecture.json discovery path (relative to the repo root, or absolute). Empty = auto-discover at the repo root.
cost.warn_threshold_usd float 0.50 Cost ceiling. 0 or negative disables.
command.default string "" Argument string applied to a bare commitbrief (no args) — e.g. --unstaged --cli gemini. Bypassed the moment any flag or subcommand is passed. Empty = built-in --staged. Whitespace-split; no shell quoting.

Per-model pricing override

The cost preflight, the verbose footer, and cached-cost figures use a built-in $/1M-token rate snapshot for each model. When that snapshot drifts — or you have a negotiated rate — override it per-model under providers.<name>.pricing.<model>:

providers:
  anthropic:
    pricing:
      claude-opus-4-8:
        input_per_1m: 12.00          # your negotiated input rate
        output_per_1m: 60.00
        cached_input_per_1m: 1.20

Each field is independent: zero or omitted fields fall back to the built-in value, so a partial override is fine. The override shows up in commitbrief config show and flows straight into the cost preflight estimate. Resolved in v1.2.0 (OQ-09).

Customizing the bare command — command.default (v1.3.0)

A bare commitbrief (no arguments) defaults to commitbrief --staged. Set command.default to an argument string and that bare invocation behaves as if you had typed those arguments instead:

command:
  default: "--unstaged --cli gemini"

Now a plain commitbrief reviews your unstaged changes through the gemini-cli provider. It is expanded git-alias style before argument parsing, and applies only to the truly bare invocation — the moment you pass any explicit flag or subcommand (commitbrief --staged, commitbrief diff …), the default is bypassed entirely. An empty or unset value keeps the built-in --staged behavior.

Because the value usually starts with -, pass -- first when setting it from the CLI (or just hand-edit config.yml):

commitbrief config set -- command.default "--unstaged --cli gemini"
commitbrief config get command.default

Environment variables

CommitBrief reads these at startup; they override config file values but lose to CLI flags.

Variable Effect
ANTHROPIC_API_KEY Sets providers.anthropic.api_key.
OPENAI_API_KEY Sets providers.openai.api_key.
GEMINI_API_KEY Sets providers.gemini.api_key.
DEEPSEEK_API_KEY Sets providers.deepseek.api_key.
MISTRAL_API_KEY Sets providers.mistral.api_key.
COHERE_API_KEY Sets providers.cohere.api_key.
OLLAMA_HOST Sets providers.ollama.base_url.
COMMITBRIEF_CONFIG Override the user-level config path (absolute).
LANG / LC_ALL No longer used for language selection (language is config-driven: --lang → repo → user → English). May still affect other locale behavior.
NO_COLOR Force color OFF regardless of output.color / --color.
COMMITBRIEF_NO_COLOR CommitBrief-specific equivalent of NO_COLOR.

Editing config

Three ways:

1. Interactive — commitbrief setup

Rewrites the active provider’s block (non-destructive for others). --local writes to the repo-local file. See First-time setup.

2. Programmatic — commitbrief config

commitbrief config show                 # YAML dump, API keys masked
commitbrief config get cache.ttl_days   # read one field
commitbrief config set provider openai  # write one field
commitbrief config set providers.openai.model gpt-4o-mini

Type coercion + validation: booleans accept true/false/yes/no/1/0/on/off (case-insensitive); integers are bounds-checked (no negatives for cache settings); output.color is enum-validated against auto/always/never; provider is validated against the registered factory list. version is rejected — it’s managed by migrations.

3. Hand-edit

Edit the YAML files directly. Hand-edits are loaded atomically on the next CLI invocation; no daemon to restart. File mode is 0600; the parent directory is 0700.

Inspecting the merged config

commitbrief config show

Dumps the resolved config as YAML with API keys masked. Useful for “is this what I think it is?” sanity checks.

commitbrief providers list

Shows every configured + registered provider, marks the active one, displays the model and a masked API-key fingerprint (or the base URL for Ollama).

Dry-run

To see how a real review would resolve all of the above — diff fetch + filter + rules + prompt + cache-key compute — without making a provider call:

commitbrief dry-run --staged --verbose

Reports per-layer filter counts, the merged rules source, the resolved language, the estimated tokens + cost, and the cache key that would be looked up.

Permissions

  • ~/.commitbrief/config.yml is written 0600. The directory is 0700.
  • <repo>/.commitbrief/config.yml is written 0600; the .commitbrief/ directory is 0700. The repo’s .gitignore is updated to include .commitbrief/ if not already present.

API keys are masked when printed by commitbrief config show and commitbrief providers list; they never appear in logs.

See also

  • Review rulesCOMMITBRIEF.md and OUTPUT.md (separate from config.yml).
  • Providers — per-provider config fields.
  • Safety and costguard.secret_scan and cost.warn_threshold_usd in depth.