code_review.yaml
The optional review pipeline file. Every field, type, and default, plus custom reviewers, the description stage, the gatekeeper, budgets, and permissions.
Add a gatekeeper:
1 ellipsis:2 version: v13 kind: code_review4 name: Backend review56 budget:7 run: 15.00
1 ellipsis:2 version: v13 kind: code_review4 name: Backend review56+filter:7+ name: gatekeeper8+ claude:9+ model: claude-opus-510+ system: |11+ Approve only findings a staff engineer would raise in review.12+13 budget:14 run: 15.00
Drop the daily and weekly caps:
1 ellipsis:2 version: v13 kind: code_review4 name: Backend review56 budget:7 run: 15.008− day: 100.009− week: 400.00
1 ellipsis:2 version: v13 kind: code_review4 name: Backend review56 budget:7 run: 15.00
Move the reviewer to a stronger model and raise the run cap:
1 ellipsis:2 version: v13 kind: code_review4 name: Backend review56 review:7 - name: bugs8 claude:9− model: claude-sonnet-510 system: |11 Find the bugs in this change before they reach production.1213 budget:14− run: 10.00
1 ellipsis:2 version: v13 kind: code_review4 name: Backend review56 review:7 - name: bugs8 claude:9+ model: claude-opus-510 system: |11 Find the bugs in this change before they reach production.1213 budget:14+ run: 25.00
code_review.yaml is the optional file that customizes what the built-in review does: which pull requests it watches, which agents run at each stage, what a review may spend, and what its sandboxes may touch. No file is needed to enable reviews; the toggle alone runs the built-in pipeline everywhere.
The pipeline file
A committed file is an overlay onto the built-in pipeline. Every field except ellipsis is optional, so the file declares only what it changes; a file that sets only budget: still runs the full built-in review. The merge rules:
- A stage list replaces that stage wholesale. Declaring
review:replaces the built-in reviewer; declaringdescription:replaces the built-in description agent; declaringfilter:adds a gatekeeper the built-in pipeline does not run. There is no append. - An unset stage inherits the built-in one. A file with no
review:runs the built-in reviewer. - An explicitly empty stage disables it.
description: []never touches the pull request description;review: []runs no reviewers. permissions:,environment:, andbudget:merge field by field, so a file that only changes the image keeps the built-in reviewers.- Declaring
pull_requests:makes its filters authoritative. A pull request the governing file does not match gets no review at all.
Where you commit the file decides what it governs, and a repository's own file replaces the organization-wide one outright. Which PRs get reviewed works that through. Unknown fields are rejected, so a misspelled key fails validation when the file syncs rather than being ignored.
The default pipeline
With the toggle on and no file committed, this is what runs, written out as YAML:
ellipsis:
version: v1
kind: code_review
name: Code review
description: Built-in incremental pull request review pipeline.
pull_requests:
for:
users: true # every human, and every bot except the
bots: # two highest-volume dependency bots
include: true
exclude:
- dependabot[bot]
- renovate[bot]
description:
name: pr-description
budget: 2.00
claude:
model: claude-haiku-4-5-20251001
system: |
Maintain the summary section of this pull request's description:
what the change does and where, in thirty seconds. Fold new
commits into the existing summary rather than appending a
changelog. Skip the update when nothing a reader cares about
changed.
review:
- name: bugs
claude:
model: claude-opus-5
system: |
Find the bugs in this change before they reach production.
Read the diff, then read enough of the surrounding code to know
whether each change is correct. Cover correctness, edge cases,
error handling, concurrency, security, regressions in behavior
callers depend on, and data or deploy hazards. Skip style,
formatting, and naming. If you cannot name the input or state
that produces a failure, it is not a finding. Keep every
comment to a few sentences, and when the fix is a concrete
edit to the lines you anchored on, put it in suggested_fix
instead of describing it.
filter: [] # no gatekeeper
budget:
run: 10.00pre_review and post_review are empty too. The system prompts above are abridged; the shipped ones are longer. Each prompt is the reviewing brain only: Ellipsis tells every stage which commit range to read and how its output is delivered, so a prompt never restates the scope and never instructs an agent to post to GitHub.
Custom reviewers
A reviewer is a name, the same claude block an automation uses, and optionally its own permissions, environment, skills, budget, and pull_requests. Declaring review: replaces the built-in bugs reviewer, so a pipeline that wants a specialist beside a general pass declares both:
ellipsis:
version: v1
kind: code_review
name: Backend review with a migration specialist
pull_requests:
repositories: [api-repo]
review:
- name: correctness
claude:
model: claude-opus-5
system: |
Find the bugs in this change before they reach production. Read
the diff, then read enough of the surrounding code to know
whether each change is correct. Cover correctness, edge cases,
error handling, concurrency, security, and regressions in
behavior callers depend on. Skip style and formatting.
- name: migration-safety
claude:
model: claude-opus-5
system: |
Review database migrations for production safety. Check for
locking that blocks writes on large tables, missing backfills
for new non-null columns, and rollout ordering that breaks if
the migration and the code deploy out of order. A migration
that is safe as written gets a one-line confirmation.
pull_requests:
paths: ["**/migrations/**"]
budget:
run: 15.00When someone adds a non-null column to a large table, both reviewers run and migration-safety lands its finding on the changed line of migrations/0042_add_column.py:
Adding a NOT NULL column with a default rewrites the whole table under an ACCESS EXCLUSIVE lock; on a table this size that blocks writes for minutes. Add the column nullable, backfill in batches, then set NOT NULL in a follow-up migration.
On a pull request that touches no migration, only correctness runs and the specialist costs nothing. Reviewers run in parallel, each in its own sandbox. Identical findings from different reviewers collapse into one, and Ellipsis posts the rest as one review, highest severity first, at most 30 inline comments. A pipeline may declare at most 8 reviewers, every stage agent's name must be unique across the file, and a reviewer with no model runs on your account default model.
Pull request descriptions
The description stage keeps a summary of the change at the top of the pull request body. The built-in pr-description agent runs on every push, reads the whole pull request, and rewrites the summary to describe it as it now stands; it can also conclude the current summary still holds and skip the write, or that the pull request should carry no summary, which removes the block. Ellipsis applies the result the moment the stage settles, before the reviewers start.
The summary lives in a marked block, and Ellipsis only ever rewrites between its own markers, so your text above and below survives every update:
Fixes #4821. Deploying this behind the `rest_periods` flag.
<!-- ELLIPSIS_HIDDEN -->
> [!IMPORTANT]
> Adds rest-period validation to shift assignment in `scheduling/rest_period.py`.
>
> - Assigning a shift within 8 hours of a worker's previous shift end now
> returns `409` with a `rest_period_violation` code.
>
> This description was created by Ellipsis for 4f2c1ab. It will
> automatically update as commits are pushed.
<!-- ELLIPSIS_HIDDEN -->
## Test plan
- [ ] verified against the staging scheduleEllipsis reads the live body immediately before writing, so an edit you made while the agent worked is carried back rather than reverted. Delete the block and it comes back on the next push. A failed update never costs you the review.
Declaring description: replaces the built-in agent; it takes exactly one agent as a mapping. Write only the summary text in its prompt: Ellipsis owns the markers, the callout, and the footer, and instructs the agent not to edit the pull request itself. description: [] turns the stage off; it does not remove summaries already written.
description:
name: pr-description
budget: 2.00
claude:
model: claude-haiku-4-5-20251001
system: |
Summarize this pull request for the reviewer who has to approve it.
Open with one sentence: what the change does and which modules it
touches. Then short grouped bullets naming real functions and files
in backticks. Call out any schema change in its own bullet.Gatekeeper
A gatekeeper is one agent that judges every reviewer finding against the code before anything posts. It is off by default: one careful reviewer leaves a second pass nothing to arbitrate, and a second frontier-model read doubles a review's cost and latency. Add one when you run several eager reviewers of your own.
Declare it under filter:, exactly one agent as a mapping. It supplies its own system prompt; there is no built-in gatekeeper prompt to inherit. A file that sets only filter: keeps the built-in reviewer and adds the gate in front of it:
ellipsis:
version: v1
kind: code_review
name: Reviewed behind a gate
filter:
name: gatekeeper
claude:
model: claude-opus-5
system: |
Approve only findings a staff engineer would raise in review.
Reject style opinions, anything a linter catches, and any claim
you have not verified against the surrounding code. Merge two
findings about the same defect into the clearer one.Nothing is deleted. Every proposed finding appears on the reviews dashboard with its verdict and the gatekeeper's reason, and the posted review states the counts, for example "Ran 2 review agents producing 5 comments where 2 were posted". A pipeline with no gatekeeper says so in the posted review. filter: [] is accepted and identical to unset.
Budgets
budget:
run: 25.00
day: 100.00
week: 400.00budget.run caps one review end to end: every stage agent of one pass, together. Each agent gets its declared budget if it set one; the agents that did not split the remainder evenly. An agent that hits its share stops where it is, and the review still posts with the findings written by then, headed "Incomplete review" and stating that the remaining lines were not checked. Those commits count as covered, so raise budget.run when reviews of large diffs stop early.
budget.day and budget.week are trailing windows over everything this pipeline spent, checked before a review starts. A pipeline at or over a cap reviews nothing until the window rolls; the skipped commits stay uncovered, so the next review covers all of them. This is the guard against a push storm. The caps are per pipeline, so an organization-wide file's caps are one pool shared by every repository it governs; a repository that needs its own pool needs its own file.
Review spend draws from the same account balance as sessions and counts toward your account-wide limits. Each review's cost is on the dashboard, with a per-stage breakdown, and on the API. See spend limits.
Permissions
A stage agent never posts to GitHub. It hands its output to Ellipsis, and Ellipsis posts the one review, authored by the Ellipsis bot, as a comment-only review anchored to the commit it reviewed. Enabling code review means exactly this: Ellipsis reads your code and writes pull request comments. It pushes no commits and merges nothing.
Every stage runs as an ordinary agent session with its own short-lived GitHub token. permissions.github narrows that token the same way it does for any agent, down to read_only, and because delivery goes through Ellipsis, a reviewer works correctly on a fully read-only token. Pipeline-level permissions: and environment: apply to every stage; a stage's own blocks merge on top. The scoping fields are documented once, in the permissions reference.
All fields
| Key | Type | Default | Meaning |
|---|---|---|---|
ellipsis | mapping | required | Identity: kind, version, name, description, enabled, metadata. |
pull_requests | mapping | all pull requests, humans and bots | Which pull requests the pipeline watches. Declaring it makes it authoritative. |
permissions | mapping | platform defaults | Pipeline-wide token scoping, merged into every stage agent. |
environment | mapping | platform defaults | Pipeline-wide environment defaults, merged into every stage agent. |
pre_review | list of stage agents | none | Context agents that run before the reviewers. Any one can cancel the review, which counts as coverage. |
description | one stage agent, or [] | the built-in description agent | Keeps the pull request summary current. [] disables it. |
review | list of stage agents | the built-in reviewer | The reviewers. At most 8. |
filter | one stage agent, or [] | none | The gatekeeper. Off unless declared. |
post_review | list of stage agents | none | Agents that run after the review posts. Their failures never affect the posted review. |
budget | mapping | run: 10.00 | Spend caps in USD. |
ellipsis
| Field | Type | Default | Meaning |
|---|---|---|---|
kind | literal code_review | required | Marks the file as a review pipeline. Without it the file parses as an automation and fails on the stage keys. |
version | string | v1 | Config schema version. Only v1 is supported. |
name | string | unset | Display name in the reviews dashboard. |
description | string | unset | Display description. |
enabled | boolean | true | false marks the file inactive, so Ellipsis continues to the organization-wide file, then the built-in pipeline. |
metadata.labels | list of strings | [] | Freeform tags. |
metadata.annotations | map of strings | {} | Freeform key-value metadata. |
pull_requests
Matched on every head advance of a pull request. All declared filters must pass; an omitted filter passes everything. Matching rules and worked examples are in Which PRs get reviewed.
| Field | Type | Default | Meaning |
|---|---|---|---|
repositories | repository filter | all | The watch set. Valid only in the .ellipsis repository's copy. A bare list is shorthand for include; exclude-only means all except those. An include entry may be {name, base, head, draft, labels, paths} to narrow the filters for that repository. |
base | list of strings | [] (all) | Target branch patterns: an exact name, a prefix glob like release/*, or the literal default. |
head | list of strings | [] (all) | Source branch patterns, same forms. |
draft | boolean | unset (either) | true reviews only drafts; false only non-drafts. |
labels | list of strings | [] (all) | At least one must be present, matched exactly including case. |
paths | list of strings | [] (all) | Changed-file globs over the full pull request file set. Include-only. |
for | account selector | humans and bots | Gates on the pull request author. users and bots each take true, a list of logins, false, or an include-minus-exclude mapping; a side omitted inside for: is false. |
permissions
The same fields as an automation's permissions: block. Each stage agent may declare its own, merged field by field onto this one.
| Field | Type | Default | Meaning |
|---|---|---|---|
ellipsis | true, "all", or a resource map | true | The sandbox's Ellipsis API token. A map narrows it per resource; false is rejected. |
github.permissions | read_only or a scope map | installation permissions | Narrows the GitHub token every stage session gets, such as {contents: read, pull_requests: write}. Enforced by GitHub when the token is minted. |
github.repositories | list of strings | all installation repositories | Narrows which repositories the token may touch. |
environment
The same fields as an automation's environment: block, with identical semantics: repositories, variables, compute, image, and hooks. Each is documented in the environments reference. Each stage agent may declare its own, merged field by field onto this one. The pull request's own repository is always cloned, so repositories lists only extra context.
Stage agents
Every entry in pre_review, description, review, filter, and post_review runs as its own agent session:
| Field | Type | Default | Meaning |
|---|---|---|---|
name | string | required | Unique across the whole file. Attributes findings and titles the stage in the dashboard. |
claude.system | string, {file} ref, or a list of both | unset | The agent's instructions. Ellipsis adds the commit range and delivery instructions; nothing else fills an empty prompt, so write one for every stage agent. |
claude.model | string | your account default model | The model this agent runs on. |
claude.effort | low, medium, high, xhigh, max | model default | Reasoning effort. |
claude.fallback_model | string | unset | Used when the primary model is overloaded. |
claude.max_turns | integer > 0 | uncapped | Hard cap on agent turns. |
claude.settings | {path, repository} | unset | A Claude Code settings.json in a repository, applied to the session. |
permissions | mapping | the pipeline's | This agent's token scoping, merged onto the pipeline-level block. |
environment | mapping | the pipeline's | This agent's overrides, merged onto the pipeline-level block. |
skills | list of {path, repository} | [] | Claude Code skills installed for this agent, each a repository directory containing a SKILL.md. |
budget | number (USD) | split evenly | This agent's per-session cap. Agents without one split what budget.run has left. |
pull_requests | mapping | unset (all) | This agent's own narrowing: base, head, and paths only. A filtered-out agent costs nothing. |
budget
| Field | Type | Default | Meaning |
|---|---|---|---|
run | number (USD) | 10.00 | Caps one review: every stage agent of one pass, together. |
day | number (USD) | 1,000.00 | This pipeline's trailing 1-day spend cap. |
week | number (USD) | 10,000.00 | This pipeline's trailing 7-day spend cap. |
The day and week defaults are the platform ceilings; a value above the ceiling is lowered to it. When every stage agent declares its own budget, their sum must fit under budget.run.