A code review is a `kind: code_review` file that names which pull requests to review and a list of reviewers, each a [session](/docs/sessions) with its own prompt, model, [environment](/docs/environments), and [budget](/docs/budgets). Each push the file admits gets at most one review on the pull request, combining every reviewer's findings.

## Review every push

<span id="quick-start" />

[Install the Ellipsis GitHub App](https://app.ellipsis.dev/) on your repository, then commit this file to its default branch:

```yaml title=".ellipsis/code-review.yaml"
ellipsis:
  kind: code_review
  name: code-review

pull_requests:
  draft: false

reviewers:
  - name: bugs
    claude_code:
      prompt: Find bugs in this pull request.
      model: claude-opus-5-5
  - name: i18n
    paths: ['frontend/**']
    claude_code:
      prompt: Flag user-facing strings that bypass the translation layer.
      model: claude-sonnet-5-5

budget:
  session: 3
```

Open a pull request to see it work. Each push starts the reviewers whose `paths` match the new commits, and one review from `ellipsis-dev[bot]` lands with their comments. A reviewer only sees commits it has not reviewed before, and a comment on a line outside those commits is held back. A push with nothing new for any reviewer starts nothing. Every review, with each reviewer's comments and session, is listed under Code Review in the dashboard.

## Configure a review

A file holds up to 8 reviewers, each with a unique `name`, and a repository holds one file. `pull_requests` takes the same filters as a pull request [trigger](/docs/agents/triggers#pull-requests). A reviewer takes the same `environment`, `skills`, and `permissions` blocks as an [agent session](/docs/agents/schema); its `budget` takes only `session`.

A file in the `.ellipsis` repository reviews every repository its `pull_requests.repositories` filter admits; a file in a repository reviews that repository and wins over the organization file. A file that breaks a limit or does not parse fails the sync, keeps the last good version running, and shows the error in the Ellipsis config check on the pull request.

## What happens when a reviewer fails

A review posts at most 30 comments per reviewer and 60 per review. A reviewer that returns more than 30 fails and contributes nothing; comments past 60 are kept with the review but not posted. When no reviewer has a comment, nothing is posted. A reviewer that fails or runs out of budget contributes nothing; the review still posts with the other reviewers' comments, and that reviewer covers the same commits again on the next push. When no reviewer finishes, nothing is posted and nothing is marked reviewed. When GitHub rejects the review, the review ends with status `failed`, nothing posts, and every reviewer covers the same commits again on the next push.

## Fields

| Field | Type | Meaning |
| --- | --- | --- |
| `ellipsis` | `object`, required | Identifies the file. |
| `ellipsis.kind` | `string`, required | `code_review`. One of `code_review`. |
| `ellipsis.name` | `string` | A name for the file, unique within the account. |
| `ellipsis.description` | `string` | Description shown in the dashboard. |
| `ellipsis.enabled` | `boolean` | `false` pauses the file. Default `true`. |
| `ellipsis.metadata` | `object` | `labels` and `annotations` for your own use. |
| `ellipsis.metadata.labels` | `list of string` | Short tags. |
| `ellipsis.metadata.annotations` | `map of string` | Free text values by key. |
| `pull_requests` | `object` | Which pull requests to review. The same filters as a pull request [trigger](/docs/agents/triggers#pull-requests) without `on`. Default every pull request by a human author. |
| `pull_requests.repositories` | `list of string or object` | Repository names, or an object with `include` and `exclude` lists. Default every installed repository. |
| `pull_requests.repositories.include` | `list of string` | Repository names to match. Default every repository of the installation, including ones added later. |
| `pull_requests.repositories.exclude` | `list of string` | Repository names to skip, applied after `include`. |
| `pull_requests.base` | `list of string` | Base branches to match. Exact names, prefixes ending in `*`, and `default`. |
| `pull_requests.head` | `list of string` | Head branches to match. Exact names, prefixes ending in `*`, and `default`. |
| `pull_requests.draft` | `boolean` | `true` matches only draft pull requests, `false` only ready ones. Default both. |
| `pull_requests.labels` | `list of string` | Labels match when any listed label is present. |
| `pull_requests.paths` | `list of string` | Globs of changed files to match. `!` patterns aren't allowed. Default every change. |
| `pull_requests.for` | `object` | Which authors count. |
| `pull_requests.for.users` | `boolean, list of string, or object` | People. `true` is everyone, a list is those logins, `false` is no one, and an object sets `include` and `exclude`. Default `true`. |
| `pull_requests.for.users.include` | `boolean or list of string` | `true` is everyone, a list is those logins, `false` is no one. Default `true`. |
| `pull_requests.for.users.exclude` | `list of string` | Logins to skip, applied after `include`. |
| `pull_requests.for.bots` | `boolean, list of string, or object` | Bots. `true` is every bot, a list is those logins, `false` is none, and an object sets `include` and `exclude`. Default `false`. |
| `pull_requests.for.bots.include` | `boolean or list of string` | `true` is everyone, a list is those logins, `false` is no one. Default `true`. |
| `pull_requests.for.bots.exclude` | `list of string` | Logins to skip, applied after `include`. |
| `pull_requests.for.teams` | `list of string` | GitHub team slugs of the installed organization, such as `platform` for `@org/platform`. The author must also be on one of them. Bots never are. |
| `reviewers` | `list of object`, required | 1 to 8 reviewers. Each runs as its own session on every push with a change in its range. |
| `reviewers[].name` | `string`, required | Unique within the file. Heads the reviewer's section of the posted review. |
| `reviewers[].paths` | `list of string` | Glob patterns. The reviewer runs only when a changed file in its range matches. Default every change. |
| `reviewers[].claude_code` | `object` | Runs the session with [Claude Code](/docs/harnesses/claude). Exactly one of `claude_code` or `codex`. |
| `reviewers[].claude_code.prompt` | `string` | The task. |
| `reviewers[].claude_code.model` | `string`, required | A Claude Code model from [Models](/docs/models#current-support). |
| `reviewers[].claude_code.effort` | `string` | Reasoning effort, where the model supports it. One of `low`, `medium`, `high`, `xhigh`, `max`. |
| `reviewers[].claude_code.max_turns` | `integer` | The most turns the agent can take on each message, a whole number above 0. |
| `reviewers[].claude_code.fallback_model` | `string` | The model Claude Code switches to when `model` is overloaded. Default none. |
| `reviewers[].claude_code.settings` | `object` | A Claude Code `settings.json` in a repository, applied below the settings Ellipsis manages. Hooks stay disabled. |
| `reviewers[].claude_code.settings.path` | `string`, required | Path of the file, relative to the repository root. |
| `reviewers[].claude_code.settings.repository` | `object` | Where `path` resolves. Default the repository this file lives in. |
| `reviewers[].claude_code.settings.repository.name` | `string`, required | The repository name, without the owner. |
| `reviewers[].claude_code.settings.repository.owner` | `string` | The GitHub owner. Default your account. |
| `reviewers[].claude_code.settings.repository.ref` | `string` | Branch, tag, or commit. Default the default branch. |
| `reviewers[].codex` | `object` | Runs the session with [Codex](/docs/harnesses/codex). Exactly one of `claude_code` or `codex`. |
| `reviewers[].codex.prompt` | `string` | The task. |
| `reviewers[].codex.model` | `string`, required | `gpt-6-astra`, `gpt-6-sol`, `gpt-6-luna`, or `gpt-5.6-sol`. |
| `reviewers[].codex.effort` | `string` | Reasoning effort. GPT-6 Astra doesn't accept `none`. Default `medium`. One of `none`, `low`, `medium`, `high`, `xhigh`, `max`. |
| `reviewers[].environment` | `string or object` | A saved environment name or an inline environment; see the [Environment schema reference](/docs/environments/schema). Default the built-in basic environment. |
| `reviewers[].permissions` | `object` | GitHub and Ellipsis access, as in an agent session. Default the full session token and the default GitHub access; see [Permissions](/docs/permissions). |
| `reviewers[].permissions.ellipsis` | `boolean or object` | Ellipsis API access for the session token. `true` grants everything a session token can do; a map narrows it per resource. Default `true`. |
| `reviewers[].permissions.github` | `object` | GitHub access for the session token. |
| `reviewers[].permissions.github.permissions` | `string or object` | `read_only`, or a map of GitHub permission names to levels. Default the installation's full permissions. |
| `reviewers[].permissions.github.repositories` | `list of string` | Repositories the token may reach. Default every repository of the installation. |
| `reviewers[].skills` | `list of object` | Skills from a repository, for Codex; see [Add a Codex skill](/docs/agents/schema#add-a-codex-skill). Up to 10. Default none. |
| `reviewers[].skills[].path` | `string`, required | Directory holding `SKILL.md`, relative to the repository root. |
| `reviewers[].skills[].repository` | `object` | Where `path` resolves. Default the repository this file lives in. |
| `reviewers[].skills[].repository.name` | `string`, required | The repository name, without the owner. |
| `reviewers[].skills[].repository.owner` | `string` | The GitHub owner. Default your account. |
| `reviewers[].skills[].repository.ref` | `string` | Branch, tag, or commit. Default the default branch. |
| `reviewers[].budget` | `object` | Spend limit for this reviewer. |
| `reviewers[].budget.session` | `number` | The most this reviewer may spend per run, in US dollars. Default `budget.session`. |
| `budget` | `object` | Spend limits every reviewer inherits. |
| `budget.session` | `number` | The per-run cap every reviewer inherits, in US dollars. Default the account's default session budget; any value is clamped to the account and platform ceiling. See [Budgets](/docs/budgets). |
