DocsConfiguration reference
Docs/Code review

Configuration reference

Put a .anvil.yaml file at the root of the repository. Anvil also reads .anvil.yml and .gitea/anvil.yaml, in that order, and uses the first one it finds.

For reviews and questions on a pull request, the file is read from the PR's base branch, not from the PR itself. A PR that edits .anvil.yaml (to turn reviews off, widen path filters or drop a check) is still reviewed under the rules already on the base branch, and its change applies to PRs opened after it merges. The walkthrough's "Review details" section says which file and branch were used. Every key is optional. If the file has an error (invalid YAML, or a value of the wrong type), the whole file is ignored, the defaults apply, and the walkthrough comment shows the error. @anvil configuration shows the settings in effect for a PR.

Example #

This is .anvil.example.yaml from the Anvil repository:

yaml
# Copy to .anvil.yaml at the root of a repository. Every key is optional.
profile: chill            # chill: bugs and real risks only · assertive: also maintainability, tests, docs, nits
language: en
instructions: |
  We use zod for all input validation. Server code lives in server/, never import it from app/.
request_changes_on_critical: false

path_filters:             # globs; "!" excludes. Lock files and build output are always excluded.
  - "!**/*.generated.ts"
path_instructions:
  - path: "migrations/**"
    instructions: "Every migration must be reversible and safe to run twice."
  - path: "**/*.test.ts"
    instructions: "Don't flag style in tests; check that assertions test behaviour."

auto_review:
  enabled: true
  incremental: true       # after a push, review only the new commits
  drafts: false
  base_branches: []       # e.g. ["main", "release/*"]; empty = all
  ignore_title_keywords: ["wip", "do not review"]
  ignore_authors: ["renovate"]

walkthrough:
  sequence_diagram: true
  estimate_effort: true

checks:                   # judged on every review, reported in the walkthrough and the commit status
  - name: Description explains why
    instructions: "The PR description says why the change is needed, not only what changed."
    mode: warning         # off | warning | error (error fails the `Anvil` status)

ci:
  analyze_failures: true  # explain failed CI jobs on the PR

reviews:
  fail_commit_status: false   # true: a review that errors fails the `Anvil` status
  guideline_files: true       # load AGENTS.md, CLAUDE.md, .cursorrules, copilot instructions
  nitpicks: folded            # inline | folded | off (chill always drops nits)
  routing: auto               # auto: cheap model for docs/bot PRs, mid-tier for small diffs, strongest for big or risky ones · off
  bots: light                 # dependabot, renovate, *[bot]: light | review | skip
  risky_paths: ["src/payments/**"]   # always reviewed on the strongest model (on top of migrations, auth, CI, Dockerfiles…)
  trivial_paths: ["translations/**"] # count as trivial, like docs
  # models: { light: claude-haiku-5-5, standard: claude-sonnet-5-5, deep: claude-opus-5-5 }

merge_risk_instructions: "Anything touching migrations/ is at least high."
security_risk_instructions: "Changes under server/auth/ are at least moderate."

chat:
  auto_reply: true            # answer replies in Anvil's review threads without @anvil

max_budget_usd: 2         # per agent run; can't exceed the server's MAX_BUDGET_USD

Top-level keys #

enabled #

boolean, default true. Set to false to turn off reviews and CI diagnosis for the repository. Commands that start a review still run.

yaml
enabled: false

profile #

chill or assertive, default chill. chill reports bugs, security problems and real risks, and drops nits. assertive also comments on maintainability, naming, tests, docs and style.

yaml
profile: assertive

language #

string, default en. The language Anvil writes in, as a language code or name.

yaml
language: de

instructions #

string, default empty. House rules added to every review.

yaml
instructions: |
  We use zod for all input validation.
  Server code lives in server/; never import it from app/.

request_changes_on_critical #

boolean, default false. When true, a review with at least one critical finding is posted as Request changes instead of a comment.

yaml
request_changes_on_critical: true

path_filters #

list of globs, default []. Which changed files are reviewed. Patterns without ! are includes: when there's at least one, only matching files are reviewed. Patterns starting with ! exclude. Dotfiles match.

Lock files, minified files, source maps, dist/, build/, .next/, node_modules/, vendor/ and *.snap are always excluded.

yaml
path_filters:
  - "src/**"
  - "!src/**/*.generated.ts"

path_instructions #

list of { path, instructions }, default []. Extra instructions for files that match a glob. They're added to a review when at least one changed file matches.

yaml
path_instructions:
  - path: "migrations/**"
    instructions: "Every migration must be reversible and safe to run twice."

merge_risk_instructions #

string, default empty. Extra guidance for the merge risk rating, added to every review. Use it to say what counts as risky in this repository.

yaml
merge_risk_instructions: "Anything touching migrations/ or billing/ is at least high."

security_risk_instructions #

string, default empty. Extra guidance for the security risk rating, added to every review.

yaml
security_risk_instructions: "Changes under server/auth/ or to CORS settings are at least moderate."

See Merge and security risk for the five levels.

max_budget_usd #

positive number, optional. Lowers the cost cap for each agent run on this repository, in US dollars. It can't go above the server's ceiling ($3 on this server). Questions are always capped at $1 or this value, whichever is lower.

yaml
max_budget_usd: 1.5

model #

string, optional. One Anthropic model for everything on this repository: every review tier, questions and CI diagnosis. It turns model routing into a single model; to change one tier only, use reviews.models instead.

yaml
model: claude-sonnet-5-5

auto_review #

When reviews start on their own. None of these apply to @anvil review.

Key Type Default What it does
enabled boolean true Review new and updated PRs automatically
incremental boolean true After a push, review only the new commits
drafts boolean false Also review draft PRs (and titles starting with WIP or Draft:)
base_branches list of globs [] Only review PRs into these branches. Empty means all
ignore_title_keywords list of strings ["wip", "do not review"] Skip PRs whose title contains one of these (case-insensitive)
ignore_authors list of strings [] Skip PRs opened by these users
yaml
auto_review:
  base_branches: ["main", "release/*"]
  ignore_authors: ["renovate"]

walkthrough #

Key Type Default What it does
sequence_diagram boolean true Include a Mermaid sequence diagram
estimate_effort boolean true Include the review effort estimate (1 to 5)
yaml
walkthrough:
  sequence_diagram: false

checks #

list, default []. Pre-merge checks written in plain language and judged on every review. See Pre-merge checks.

Key Type Default What it does
name string required Shown in the walkthrough and the commit status
instructions string required What must be true for the check to pass
mode off, warning or error warning error fails the Anvil commit status when the check fails
yaml
checks:
  - name: Migrations are reversible
    instructions: "Every new file in migrations/ has a working down migration."
    mode: error

ci #

Key Type Default What it does
analyze_failures boolean true Explain failed CI jobs on the PR in a comment
yaml
ci:
  analyze_failures: false

reviews #

Key Type Default What it does
fail_commit_status boolean false When a review errors (the agent fails twice, the checkout fails), set the Anvil status to failure instead of a warning, so a required anvil status blocks merging until a review succeeds
guideline_files boolean true Load AGENTS.md, CLAUDE.md and .cursorrules (at the root and in every changed directory) and .github/copilot-instructions.md from the base branch into the review. See Guideline files
nitpicks inline, folded or off folded Where nit findings go: inline comments like other findings, one collapsed Nitpicks section in the walkthrough, or nowhere. The chill profile always drops them
routing auto or off auto Pick the model and effort per pull request (see Model routing). off reviews everything on the strongest model at full effort
models {light, standard, deep} server defaults The model for each routing tier. Unset tiers use the server's REVIEW_MODEL_LIGHT (claude-haiku-5-5), REVIEW_MODEL_STANDARD (claude-sonnet-5-5) and REVIEW_MODEL (claude-opus-5-5)
risky_paths list of globs [] Extra paths that always get the deep tier, on top of the built-in list
trivial_paths list of globs [] Extra paths that count as trivial, like docs: a PR touching only these gets a light review
bots light, review or skip light Pull requests from dependency bots (dependabot, renovate, any *[bot] account): a light review, a normal one, or none
yaml
reviews:
  fail_commit_status: true
  nitpicks: inline

Model routing #

Every review is routed to one of three tiers before it starts. The tier, and why, is in the walkthrough footer, on the review page and in the run list.

Tier When Model (default) Effort Turns
light Only docs, images, licences or whitespace changed (plus trivial_paths); or a bot PR under 800 changed lines claude-haiku-5-5 low 8
standard Up to 200 changed lines in up to 10 files, nothing risky claude-sonnet-5-5 medium 40
deep Anything bigger: medium effort up to 800 lines and 30 files, full effort above that claude-opus-5-5 medium or REVIEW_EFFORT (high) MAX_TURNS
deep Any risky path, at any size, whoever the author: migrations and .sql, auth, sessions, tokens, secrets, permissions, crypto, payments and billing, Dockerfiles and compose files, CI workflows, .env*, plus risky_paths claude-opus-5-5 REVIEW_EFFORT (high) MAX_TURNS
deep @anvil full review claude-opus-5-5 REVIEW_EFFORT (high) MAX_TURNS

Only files in scope count (lock files and build output are always filtered out). For an incremental review, the tier comes from the new commits only. The assertive profile keeps small diffs on the deep tier at medium effort. When a light or standard review fails (runs out of turns or budget, or returns unusable output), it is rerun once on the deep tier instead of failing; both runs show in the run list.

yaml
reviews:
  routing: auto
  bots: skip                      # don't review dependabot/renovate at all
  risky_paths: ["src/ledger/**"]
  models:
    standard: claude-opus-5-5     # small diffs on Opus too, at medium effort

chat #

Key Type Default What it does
auto_reply boolean true Answer replies in review threads Anvil started without needing @anvil. Replies that start with someone else's @mention are left alone
yaml
chat:
  auto_reply: false

agents #

What Anvil's code-changing agents may do. Read from .anvil.yaml on the pull request's base branch, so a pull request can't change these for itself. See Agents that change code.

Key Type Default What it does
enabled boolean true Allow @anvil fix, fix ci, docstrings, tests, simplify, resolve conflicts and recipes
push new_branch, pr_branch or off new_branch Where a change goes: a new anvil/fix-<pr>-<n> branch with a pull request into the PR's branch, a commit on the PR's branch, or only a patch in the comment
command string none Check command run after the change (pnpm test); the agent can run it too. Needs AGENTS_COMMANDS=local on the server
command_timeout_s number, 10 to 1800 600 Kill the check command after this many seconds
max_files number, 1 to 200 25 Refuse a change that touches more files
max_budget_usd number max_budget_usd, else the server's cap Spending cap per task; can't exceed the server's MAX_BUDGET_USD
max_turns number, 5 to 200 60 Turn limit per task
autofix_ci boolean false Run fix ci by itself when CI fails on a pull request
autofix_max_attempts number, 1 to 5 1 Automatic attempts per pull request
recipes list [] Prompts run with @anvil run <name>: name, prompt, optional command
yaml
agents:
  push: pr_branch
  command: pnpm test
  autofix_ci: true
  recipes:
    - name: changelog
      prompt: Add an entry for this pull request to CHANGELOG.md under "Unreleased".

Unknown keys are kept and ignored, so a file written for a newer version of Anvil still works.