Review scopes
How to scope a CommitBrief review — staged, unstaged, arbitrary diff ranges, commit-level filters by author and date, path allow/deny filters, and the three-layer ignore pipeline.
A review needs a diff. CommitBrief gives you four sources for that diff plus two layers of filtering on top.
The default — staged changes
commitbrief
commitbrief --staged # explicit
commitbrief -s # short form
Reviews git diff --cached. This is the default when no scope
flag is set — picked because it lines up with the pre-commit
moment.
Working-tree changes
commitbrief --unstaged
commitbrief -u
Reviews git diff (working tree vs the index). Useful when you
have edits you have not staged yet.
--staged and --unstaged are mutually exclusive — passing both
is a cobra-level error before any work begins.
Historic ranges — commitbrief diff
For anything outside the working tree, use the diff subcommand.
The positional arguments are forwarded verbatim to
git diff --no-color --no-ext-diff <args>, so anything git diff
accepts works.
| Invocation | Equivalent | What it reviews |
|---|---|---|
commitbrief diff HEAD |
git diff HEAD |
Working tree vs HEAD. |
commitbrief diff HEAD~3 HEAD |
git diff HEAD~3 HEAD |
The last three commits’ net change. |
commitbrief diff main feature |
git diff main feature |
One branch vs another. |
commitbrief diff main...feature |
git diff main...feature |
Three-dot range — feature’s changes since branching off main (PR style). |
commitbrief diff <merge-sha> |
git diff <merge-sha> |
First-parent diff of a merge commit. |
commitbrief diff HEAD -- '*.go' |
git diff HEAD -- '*.go' |
Filter by git pathspec after --. |
At least one positional argument is required.
Commit filters (v1.15.0)
The three scopes above all produce one diff. Commit filters
produce a set of commits instead — “everything Alice touched
since June”, “every commit whose message mentions payment” —
and review the concatenation of their patches (ADR-0035).
git diff has no author or date options; those are git log
options. So setting any of these flags switches diff acquisition
to a commit walk, which is why they cannot be combined with
--staged / --unstaged: the index has no commits yet.
| Flag | Matches |
|---|---|
--author |
author name or email, case-insensitive substring; repeatable, OR’d |
--committer |
committer name or email; repeatable, OR’d |
--start-date YYYY-MM-DD |
author date on or after this day (inclusive) |
--end-date YYYY-MM-DD |
author date on or before this day (inclusive — unlike git’s bare --until, which stops at that day’s midnight and silently drops it) |
--text |
the commit message, plus commits unique to a branch whose name contains the text |
commitbrief --author alice --author bob # either person's commits
commitbrief --author [email protected] # name or email
commitbrief --start-date 2026-01-01 # on or after (inclusive)
commitbrief --text payment # message OR branch name
commitbrief diff main..develop --author alice # bound the walk to a range
Different kinds are AND’d, multiple values of one kind are
OR’d: --author alice --author bob --start-date 2026-06-01
means “(Alice or Bob) and since June”.
The revision range walked is HEAD by default, or the range you
give a subcommand. The resulting diff is the concatenation of
the matching commits’ patches, not a cumulative range diff — so
a file changed in three of them appears three times, and no
unmatched commit’s work leaks in.
Branch-name matching is best-effort by nature: a squash- or rebase-merged branch no longer owns its commits, so nothing will be found for it.
Two modifiers
--max-commits N (default 200) caps the selection and always
reports truncation rather than silently reviewing a subset.
--merges keeps merge commits, which the walk excludes by
default. Neither starts a walk — passing one on a review with no
commit filter set is a usage error, since there is nothing to
modify. (On leaks and
map, which always walk history,
--max-commits is an ordinary bound.)
Where they apply
Available on the default review, diff,
summary, dry-run, the
MCP review tool,
guard, leaks, and
map.
They are rejected by commit, which
describes the staged index and therefore has no commits, and by
remote pr, whose diff comes from
gh pr diff rather than local git.
commitbrief map --author alice is the fastest way to check a
filter before paying for a review — it draws the graph with the
matches highlighted and the rest dimmed as context.
Path filters — --file and --dir
Repeatable filter flags that compose on top of any scope:
commitbrief --staged -f src/main.go -f src/util.go
commitbrief --unstaged -d database/seeder -d app/Models
commitbrief diff HEAD~3 HEAD --dir docs
--file <path>(-f) matches a file path exactly (the diff’sb/path relative to repo root). Renamed files match on either the new path or the old path.--dir <path>(-d) matches any file whose path begins with the given directory plus a slash.database/seeddoes not matchdatabase/seedother/*.- Both flags repeat. Multiple instances are unioned — a file matching any one of them is kept.
- They combine:
--file foo.go --dir handlers/keepsfoo.goAND everything underhandlers/.
Path filters apply after the ignore layers below.
Glob patterns (v1.7.0)
Both flags also accept gitignore-style glob patterns, not just exact
paths (ADR-0026). A value containing *, ?, or [ is compiled as
a glob; the slash decides how it anchors:
- Slash-less patterns match the basename at any depth —
--file '*.go'keeps every changed.gofile, anywhere in the tree. - Slash-bearing patterns are anchored to the repo root —
--file 'internal/**/*.ts'matches only underinternal/, and--dir 'app/**'scopes to theapp/subtree.
commitbrief --staged --file '*.go' # any Go file, any depth
commitbrief --staged --file 'internal/**/*.ts' # root-anchored
commitbrief diff main...feature --dir 'app/**' # globbed directory scope
Quote the pattern so your shell doesn’t expand * before
CommitBrief sees it.
Backward compatible: a value with no glob metacharacter keeps
its exact pre-v1.7 behavior — --file src/main.go still matches that
one path (and its rename pair). An invalid glob errors clearly up
front instead of silently mis-filtering.
Denylists — --exclude-file and --exclude-dir (v1.15.0)
The inverse of --file / --dir. They share the exact same
matching rules — literal path or gitignore-style glob — and are
applied after the allowlist, so an exclusion always wins:
commitbrief --staged --exclude-file '*_test.go' # everything but tests
commitbrief --staged --dir internal --exclude-dir internal/cli
commitbrief diff main...feature -d 'app/**' --exclude-file '*.generated.ts'
Both repeat, both accept globs, and an invalid pattern errors before any provider call — same as the allowlist.
Use the pair when the set you want is “this subtree, minus one
corner of it”. Reaching for .commitbriefignore instead makes the
exclusion permanent and team-wide; these flags are per-run.
The three-layer filter pipeline
The full pipeline that decides which files reach the LLM:
- Built-in ignore patterns — hardcoded into the binary. Lock
files (
*.lock,go.sum,package-lock.json, …), vendored code (vendor/**,node_modules/**), generated code (*.pb.go,*.gen.go), mocks, build artefacts, editor detritus, and binary blobs (*.png,*.zip,*.pdf). .commitbriefignore— repo-local gitignore-syntax overlay. Drop a file at the repo root. Glob syntax is the same as.gitignore;*,**, and a leading!to re-include a previously-excluded path all work.--file/--dirpath allowlists from the command line, then--exclude-file/--exclude-dirdenylists on top of whatever survived.
Later layers can override earlier ones. To force review on a path the built-in layer would exclude:
# .commitbriefignore
!vendor/**
The ! re-inclusion overrides the built-in vendor/** pattern.
Inspecting filter behavior
commitbrief dry-run reports the per-layer counts:
Commits (walked): 50
Commits (matched): 12
Files (input): 12
built-in ignore filtered: 3
.commitbriefignore net filtered: 1
--file/--dir path filter: 2
--exclude-file/--exclude-dir: 1
Files (review): 5
A negative .commitbriefignore net filtered means a !pattern
reverted a built-in exclusion. The two Commits lines appear only
when a commit filter made the run walk
history; commitbrief map shows which commits those were.
Mutually exclusive scope flags
Cobra enforces these mutex groups before any pipeline work runs:
| Mutually exclusive | Why |
|---|---|
--staged × --unstaged |
Two scopes for the same run is ambiguous. |
--staged / --unstaged × any commit filter |
A commit filter walks history; the index has no commits. |
--provider × --cli |
Only one backend can serve a review. |
--cli × --json × --markdown |
CLI providers emit pre-formatted plain text; you cannot also ask for JSON. |
See also
- Commit graph — map — see exactly which commits a filter selected, before paying for a review.
- Review a GitHub PR —
commitbrief remote prreviews a pull request and posts findings back to GitHub. - Output formats — how findings render once a scope is fixed.
- Severity and CI gating —
--fail-onand exit codes. - Configuration — where flags slot into the broader config surface.