Configuration
Per-repo configuration lives in .postil.yaml (also .postil.yml or .postil.json). Every knob has a working default; an empty file is a valid file.
Precedence
From strongest to weakest:
- CLI flags
- Environment variables
.postil.{yaml,yml,json}.coderabbit.yaml(compatibility read)- Built-in defaults
Migrating from CodeRabbit costs nothing: leave the existing.coderabbit.yaml in place and Postil maps the overlapping settings (ignore patterns, severity thresholds, review toggles). Add a .postil.yaml later to use Postil-specific features; it wins wherever both define a value. Use postil config to print the resolved configuration with the provenance of every value.
Full reference
# .postil.yaml — every key, with defaults
enabled: true # disable reviews for this repo entirely
ignore: # globs excluded from review
- "vendor/**"
- "**/*.lock"
- "dist/**"
severityThreshold: info # drop findings below: info | warn | error
minConfidence: 0.6 # drop findings below this confidence
maxFindings: 20 # hard cap per review; excess counted as suppressed
reviewer:
tone: "direct, specific, no praise, no filler" # free-form, passed to the model
focus: # steer attention; free-form, passed to the model
- correctness
- security
review:
onClean: skip # skip = stay silent on clean PRs (default) | comment
gate:
failOn: error # the gate fails at/above this severity
onError: block # block (fail closed, default) | advisory
# advisory fails open on provider outages only
model:
name: deepseek/deepseek-v4-pro
cascade: # fallbacks, tried in order on provider errors
- qwen/qwen3-coder
apiBase: https://openrouter.ai/api/v1
consensus: 1 # run the first N of [name + cascade], keep only
# findings they agree on (must be >= 1)Gate behavior on operational errors
gate.onError controls what happens when a review cannot complete — a provider outage, an exhausted key, model output that fails validation. The default, block, fails the gate: an unreviewed head is not a passing head. Setting it to advisory lets the gate pass on provider outages only, for repos that prefer fail-open over a blocked merge queue when the model endpoint is down. Findings the model did produce still gate normally.
Repo guardrails
Drop repo-specific merge rules in .postil/guardrails.md (plain Markdown, one rule per bullet or heading) and Postil injects them into the review prompt. A change that violates one is reported as a guardrail finding that quotes the rule it breaks — see the envelope schema.
# .postil/guardrails.md
- Every new API route must enforce org-scoped authorization.
- Database migrations must be reversible.
- No direct writes to the billing tables outside src/billing/.Environment variables
| Variable | Meaning |
|---|---|
POSTIL_API_KEY | LLM API key; falls back to OPENROUTER_API_KEY |
POSTIL_API_BASE | OpenAI-compatible base URL (default https://openrouter.ai/api/v1) |
REVIEW_MODEL | Model id (default deepseek/deepseek-v4-pro) |
REVIEW_MODEL_CASCADE | Comma-separated fallback models |
GITHUB_TOKEN | Token for GitHub API access (--forge github; required for remote reviews) |
GITHUB_API_URL | GitHub API base URL for GitHub Enterprise Server (default https://api.github.com) |
GITLAB_TOKEN | Token for GitLab API access (--forge gitlab) |
GITLAB_API_URL | GitLab API base URL for self-managed instances (default https://gitlab.com/api/v4) |
BITBUCKET_TOKEN | Token for Bitbucket API access (--forge bitbucket); sent as a bearer token, or as the password for basic auth when BITBUCKET_USER is also set |
BITBUCKET_USER | Username for Bitbucket app-password (basic) auth; when set, BITBUCKET_TOKEN is used as the password |
BITBUCKET_API_URL | Bitbucket API base URL (default https://api.bitbucket.org/2.0) |
AZURE_DEVOPS_TOKEN | Personal access token for Azure DevOps (--forge azure) |
AZURE_DEVOPS_API_URL | Azure DevOps API base URL (default https://dev.azure.com) |
Each remote forge reads its own token plus an optional base-URL override for self-managed or enterprise instances. Only the variables for the forge you target are required. Unlike some self-hosted reviewers, Postil never silently substitutes a different provider: if the configured model cannot be reached with the configured credentials, the review fails with exit code 2 and a precise error. postil doctor runs the same checks standalone.
Trying changes safely
Do not tune thresholds against live PRs. Run postil plan with the candidate file to see what it would have changed on your recent reviews.