Gates
[[gates]] lists the commands that must pass before you are asked to review a
change. Each [[gates]] table is one gate; they run in order, user gates before
project gates. For intentional failures, manual /review --skip-gates opens
gate-free review and /commit --skip-gates bypasses only that invocation's
final publication gates
(Committing). Neither
changes the configured gates for later turns or commits.
[[gates]]
name = "check"
paths = ["**/*.rs", "Cargo.toml"]
command = ["cargo", "check", "--all-targets"]
[[gates]]
name = "test"
modes = ["code"]
paths = ["**/*.rs"]
command = ["cargo", "test"]
retry_limit = 2
[[gates]]
name = "fmt"
paths = ["**/*.rs"]
command = ["cargo", "fmt", "--check"]
retry_limit = 1
[[gates]]
name = "docs"
paths = ["**/*.md"]
command = ["yucky", "--check", "{files}"]
| Key | Meaning | Default |
|---|---|---|
name | Shown in status lines and to the model. | Required |
paths | Globs over the files the turn changed; the gate runs when any matches. * stops at /, ** does not. | Any path |
command | Shell string or executable-and-arguments array, run in the worktree. Exit 0 passes. {files}: see below. | Required |
retry_limit | Failures the model may fix on its own before the review opens with the failure attached. | 3 |
An array runs directly, without a shell: its first string is the executable and
all remaining strings are literal arguments. No variable expansion, globbing,
pipes, or redirection occurs. Use a string, such as
command = "cargo test 2>&1 && echo passed", when you need sh -c. Both forms
capture stdout and stderr; direct execution needs no 2>&1.
Arrays must contain a nonempty executable, only strings, and no NUL bytes.
{files} must occupy a whole argument and cannot appear in the executable.
modes optionally restricts a gate to code, design, or both. Omission is
unrestricted. Explicit empty lists, unknown or wrong-case names, and non-string
values are configuration errors. Repeated valid modes are deduplicated in stable
order. The mode allowlist and path globs must both match. Quick and recorded
review turns count as code; plan turns are read-only and run no gates.
[[gates]]
name = "design-check"
modes = ["design"]
paths = ["designs/**/*.md"]
command = "check-designs {files}"
check-designs represents your own project command. Leave shared checks such as
Markdown formatting unscoped. Existing gates need no edits and remain
unrestricted. Final publication selects modes from accepted unpublished work,
not the session's current mode.
A gate's files are the changed paths its paths match, or every changed path
when it has none, less any that were deleted. In an array, each {files}
argument expands to those paths as separate literal arguments. In a shell
string, they are each quoted for the shell. HEPH_GATE_FILES holds them one per
line in both forms. A gate that uses {files} and has no files is skipped. See
Checking only the changed files.
A gate may run for up to thirty minutes; its output streams into the
conversation as it arrives and is given to the model whole when it fails.
CARGO_TARGET_DIR is set to the project's shared target directory when
[worktree] shared_target is on (the default).
Gates need no permission, but do acquire matching execution locks.
Array commands match exec(program) args(...); strings match
shell(<expanded command>), after file expansion in both cases.
Acceptance Gates explains when they run and what the model
sees.