> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superserve.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# PR Loop

> An open-source PR review loop you install into any repo — Claude Code reviews every commit from a warm Superserve sandbox, with your own credentials and branding.

PR Loop is an open-source [agent loop](https://github.com/superserve-ai/superserve/tree/main/examples/loops) that shepherds your open pull requests. Each time a commit is pushed to a PR, Claude Code — running headless inside a warm Superserve sandbox — reviews the new code against a calibrated rubric, runs your project's own tests as a verifier, posts **one** concise review, and escalates risky changes to a human. It proposes; a human merges. It never merges, force-pushes, or edits CI.

Everything is self-hosted and yours: your repo, your GitHub identity, your Claude subscription, your sandboxes, your review norms.

## How it works

Three roles, and only one of them is a sandbox:

1. **Trigger** — a GitHub Actions workflow fires on `pull_request` events (`opened`, `synchronize`, `reopened`). No idle cron.
2. **Orchestrator** — a stateless script from the published `@superserve/loops` package runs on the CI runner: it finds the repo's loop sandbox by metadata, runs one tick inside it, then pauses it.
3. **Worker sandbox** — a Firecracker microVM booted from the `superserve/claude-code` template. The repo clone, the review state, and Claude Code all live here, warm between ticks.

The review runs in a sandbox rather than on the CI runner because:

* **Warm checkout.** The repo and its dependencies are cloned once, on the first tick. Every later tick resumes the same box and skips setup entirely.
* **Isolation.** A PR diff is untrusted code. It is reviewed — and your test suite runs against it — inside an isolated microVM, never on your runner or laptop.
* **\~\$0 idle.** The box is paused between ticks; you pay for seconds of compute per review, plus your LLM tokens.

## Prerequisites

| You need                             | Where to get it                                                                                                          |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| **Superserve API key** (`ss_live_…`) | [console.superserve.ai](https://console.superserve.ai?utm_source=docs\&utm_medium=link)                                  |
| **A Claude credential**              | `claude setup-token` (Pro/Max/Team/Enterprise subscription, mints a \~1-year token) — or a metered `ANTHROPIC_API_KEY`   |
| **bun**                              | [bun.sh](https://bun.sh) — only to run the installer                                                                     |
| **GitHub access**                    | Nothing extra — reviews post as `github-actions[bot]` via the workflow's built-in token. A PAT or App is opt-in (below). |

## Install

Run inside the repo you want reviewed:

```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
bunx @superserve/loops add pr-loop
```

The installer does everything:

1. Prompts for your Superserve API key (hidden input) and — when the `claude` CLI is installed — runs `claude setup-token` for you to mint the long-lived Claude token.
2. Stores that token as a Superserve secret (`claude-oauth`) bound to `api.anthropic.com` — it is [swapped in at egress](/secrets/binding) and never enters the sandbox.
3. Sets `SUPERSERVE_API_KEY` as a GitHub Actions secret on the repo.
4. Writes `.github/workflows/loop-pr-loop.yml` — the only file added to your repo — then commits it (scoped to just that file; anything else you had staged stays staged) and pushes it after you confirm (`--yes` is the non-interactive consent).

Push a commit to any PR and it is reviewed within seconds.

<Note>
  The push only ever publishes the installer's own commit. If your branch is
  already ahead of upstream with unpublished work, the installer refuses to
  auto-push — and whenever it can't or won't push (no upstream, no write
  access, confirmation declined), it prints the exact commands to run yourself.
</Note>

<Note>
  The workflow runs the published package (`bunx @superserve/loops@stable run
      pr-loop …`) — no loop source is vendored into your repo. `@stable` is a gated
  release channel, so loop improvements roll out without you ever editing the
  file.
</Note>

For CI or scripted installs, pass credentials via env or flags instead of prompts:

```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
SUPERSERVE_API_KEY=… CLAUDE_CODE_OAUTH_TOKEN=… \
  bunx @superserve/loops add pr-loop --yes

# preview without changing anything
bunx @superserve/loops add pr-loop --dry-run
```

## Try one tick locally

No install, no repo changes — good for seeing the resolved plan and one live review first:

```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
# resolved plan only, needs no keys
bunx @superserve/loops run pr-loop --repo owner/name --dry-run

# one real review from your machine (the review still runs in a cloud sandbox)
SUPERSERVE_API_KEY=ss_live_… \
CLAUDE_CODE_OAUTH_TOKEN=… \
GITHUB_TOKEN=$(gh auth token) \
  bunx @superserve/loops run pr-loop --repo owner/name --pr 42
```

Omit `--pr` to sweep every open PR in one tick, or add `--watch=15m` to re-tick on an interval.

## Where your credentials live

| Credential         | Where it lives                   | Does it enter the sandbox?                                                                                |
| ------------------ | -------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Superserve API key | GitHub Actions secret            | No — only the orchestrator on the CI runner uses it                                                       |
| Claude token       | Superserve secret `claude-oauth` | No — the box sees a stand-in value; the real token is attached at egress, only toward `api.anthropic.com` |
| GitHub token       | Minted per run by GitHub Actions | Yes, but it is repo-scoped, least-privilege, and expires when the run ends                                |

See [Secrets](/secrets/overview) for how egress swapping works. A GitHub PAT (optional, below) gets the same treatment as the Claude token: stored as a Superserve secret, swapped at egress.

## Bring your own bot identity

By default reviews post as `github-actions[bot]` — zero GitHub credentials to create. Two opt-in upgrades:

### A custom name — machine-user PAT

Create a dedicated GitHub account (e.g. `acme-review-bot`) and mint a **fine-grained** PAT on the target repo with `Contents: Read`, `Pull requests: Read & write`, `Issues: Read & write`. Classic `repo`-scope tokens are refused — `repo` includes push and merge rights, which would void the loop's propose-only guarantee. Then install with:

```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
bunx @superserve/loops add pr-loop --github-token <PAT>
```

Reviews now post as that account. The PAT is stored as the Superserve secret `loop-github-token` and swapped at egress. This path is also how one repo's workflow reviews a *different* repo.

### A name and an avatar — your own GitHub App

A GitHub App gets you the `[bot]` badge, a profile picture, and short-lived per-repo tokens. The App — and its private key — stay yours, in your own repo's (or org's) secrets; nothing is shared.

1. **Create the App**: GitHub → **Settings → Developer settings → GitHub Apps → New GitHub App**. The name becomes the handle (`acme-pr-loop` → `acme-pr-loop[bot]`). Uncheck the webhook. Permissions: `Contents: Read-only`, `Pull requests: Read & write`, `Issues: Read & write`.
2. **Upload a logo** under Display information (this is the avatar), **generate a private key**, and **install** the App on the repo you're reviewing.
3. **Store the App credentials** as Actions secrets — repo-level, or **org** secrets so every repo inherits them:

```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
gh secret set LOOP_APP_ID --body "<your App ID>"
gh secret set LOOP_APP_PRIVATE_KEY < ~/Downloads/your-app.*.private-key.pem
```

4. **Install with `--github-app`** — the installer writes the App-token workflow for you, no YAML editing:

```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
bunx @superserve/loops add pr-loop --github-app
```

The generated workflow mints a fresh installation token each run via `actions/create-github-app-token`, scoped to that one repo and expiring within the hour, and posts reviews as your App. Because the credentials are referenced by secret name, setting `LOOP_APP_ID` / `LOOP_APP_PRIVATE_KEY` as **org** secrets once covers every future repo — install the loop into a new repo and it inherits the identity with no extra token setup.

## Make it review your way

These work with the published loop as-is — nothing to fork:

* **Review norms and the merge bar.** Each run the loop reads your repo's `CLAUDE.md` / `AGENTS.md` / `README.md` for the review conventions and what "ready to merge" means in your project. Write your team's rules there and reviews follow them.
* **The verifier's checks.** The loop runs your project's *own* tests, lint, and build — discovered from `CLAUDE.md`, `AGENTS.md`, `Makefile`, or CI config on the default branch. Nothing loop-specific to define.
* **Your own skills.** Commit them to your repo at `.claude/skills/<name>/SKILL.md`. Claude Code runs inside your cloned repo, so it discovers project skills automatically.

Deeper changes — your own rubric, MCP servers, models, tool policy — mean running the loop from source. The [loop's README](https://github.com/superserve-ai/superserve/tree/main/examples/loops/pr-loop#deeper-changes-run-from-source) covers that path.

## Rotate, revoke, uninstall

* **Rotate a credential by re-running the installer.** `add` is idempotent: it rotates the existing Superserve secrets in place and rewrites the same workflow file. The Claude token lasts about a year; when it expires, run `claude setup-token` again and re-run the installer.
* **Revoke independently.** Revoke the Claude token in your Claude account, the PAT in GitHub settings, or the Superserve API key in the [console](https://console.superserve.ai?utm_source=docs\&utm_medium=link) — each kills its own half without touching the others.
* **Uninstall** by deleting the workflow file, then kill the warm sandbox (console → Sandboxes → the box named `pr-loop`, or `Sandbox.killById`) and delete the `claude-oauth` secret.

## Safety model

* **Never merges, force-pushes, or edits `.github/workflows`.** The strongest action it takes is a review plus a `ready-to-merge` label — kept in bounds by the skill's rules and, decisively, by the least-privilege token scope below: a `contents: read` token cannot merge or push, no matter what runs in the sandbox.
* **Prompt-injection firewall.** PR content is treated as data, not instructions. The loop refuses instructions embedded in diffs or comments and only runs the project's own checks, read from the default branch — never commands suggested by the PR.
* **Least privilege.** The workflow grants `contents: read` and `pull-requests: write`, nothing else. Fork PRs are skipped by default (their token is read-only); review them via the PAT path if you want them covered.
* **Human gates.** Security, auth, payments, or core-infra changes — and PRs stuck across several runs — get a `needs-human` label and an `@`-mention instead of silent action.

<Note>
  Two cost meters, don't conflate them: pausing the sandbox makes *sandbox
  compute* roughly free between ticks, but *LLM tokens* are billed separately by
  Anthropic. A subscription token from `claude setup-token` keeps ticks off
  metered API billing.
</Note>

## See also

<CardGroup cols={2}>
  <Card title="Source and full install guide" href="https://github.com/superserve-ai/superserve/tree/main/examples/loops/pr-loop">
    The loop's code, review rubric, and the step-by-step README — from "just try
    it" to a branded bot with your own skills.
  </Card>

  <Card title="Secret binding" href="/secrets/binding">
    How credentials are swapped in at egress so they never enter the sandbox.
  </Card>

  <Card title="Claude Code sandboxes" href="/integrations/coding-agents/claude">
    Run Claude Code interactively in a Superserve sandbox.
  </Card>

  <Card title="Sandbox lifecycle" href="/sandbox/lifecycle">
    Pause, resume, and the warm-state model the loop is built on.
  </Card>
</CardGroup>
