# Review Pull Requests on a Cloudflare Workers Project

Yes. An agent checks out the pull request, runs the template linter, its tests and wrangler deploy --dry-run in its sandbox, and posts one review on bindings.

[Run this on Rush](https://cloud.getrush.ai/run/review-pull-requests/cloudflare-workers/), in a Project that has your repository.

## What the agent does

The agent reads the repository's own review guide before the diff, because cloudflare/templates ships one. `AGENTS.md` lists the order to check a template pull request in: `package.json` fields, the README's `<!-- dash-content-start -->` and `<!-- dash-content-end -->` markers with the deploy button above them, at least five tests, `pnpm run check:templates` passing, and a build that compiles. It also names the two logic bugs that recur in reviews, a special-path check placed after the upstream `fetch` so it never runs, and a binding read from `globalThis` instead of the `env` parameter. `CONTRIBUTING.md` adds the `cloudflare` object the dashboard reads: `label`, at most three `products`, `categories` limited to `starter`, `storage` and `ai`, and `preview_image_url` and `preview_icon_url` that only the Cloudflare team can supply.

Then it runs what CI runs. `.github/workflows/pull-request.yaml` does `pnpm -w check`, `pnpm -w test`, installs Chromium and runs `pnpm test:e2e`, with no secrets and a 20-minute timeout. The root `package.json` pins `pnpm@10.2.0`, `turbo` 2.6.1, `vitest` 4.1.10, `@playwright/test` 1.57.0 and `syncpack` 13.0.4; `check` chains `syncpack lint`, `templates lint .`, the npm lockfile check, `turbo run check cf-typegen --force` and `prettier . --check`, then `git diff --exit-code` so a generated file that changed fails the run. `turbo.json` makes `check` depend on `build`, and each template's `check` script is `tsc && wrangler deploy --dry-run`, as in `d1-template`, `to-do-list-kv-template` and `d1-starter-sessions-api-template`. The agent runs the root `check` and `test`, then `pnpm test` and `pnpm run check` inside the touched template, and `pnpm test:e2e` filtered to that template's spec under `playwright-tests/`.

The linter in `cli/src/lint.ts` is read in full so the review quotes its rules rather than guessing at them: `wrangler.json` or `wrangler.jsonc` must exist and `wrangler.toml` must not; `compatibility_date` must be `2025-10-08`; `observability` must be `{ enabled: true }`; `upload_source_maps` must be `true`; `name` must equal the directory name and the `package.json` name; `scripts.deploy` and `scripts.dev` must exist; `.gitignore` must contain `node_modules` and `.wrangler`; and the README markers must appear once each, in order. `.syncpackrc.json` pins every dependency to an exact version except `@cloudflare/workers-types`, which keeps a caret, with named exceptions for templates that need Workers types v5. A pull request that bumps `wrangler` in one template and not the others fails `syncpack lint`, and the review says so with the line.

With the checks run, the diff is read for bindings, request limits and runtime compatibility. Bindings: a `kv_namespaces`, `d1_databases` or Durable Object entry in `wrangler.json` must match the name the code reads from `env`, tests must reach it through `cloudflare:test`, as `d1-starter-sessions-api-template/test/index.spec.ts` does with `env`, `createExecutionContext`, `waitOnExecutionContext` and `SELF`, and a service binding needs a stub Worker in `vitest.config.ts` as `AGENTS.md` shows. Request limits: a proxy template like `x402-proxy-template`, whose tests run under `node:test` and check that a `/./premium/secret` path is not proxied, is read for the order of its path check and its upstream fetch. Compatibility: a `compatibility_flags` change, a new `nodejs_compat` dependency or a Workers API behind a newer runtime is checked against the `compatibility_date` the linter enforces. One GitHub review is posted per run, quoting the linter, `pnpm test`, `wrangler deploy --dry-run` and the Playwright spec, separating blocking issues from suggestions, with file and line on every finding. The agent pushes nothing.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Review this pull request on the Cloudflare Workers templates monorepo. Check it out, run pnpm install, then pnpm -w check and pnpm -w test from the root, and in each template the diff touches run pnpm test and pnpm run check (tsc and wrangler deploy --dry-run), plus pnpm test:e2e for that template's spec in playwright-tests after pnpm exec playwright install --with-deps chromium. Read AGENTS.md and CONTRIBUTING.md first and apply their checklist. Look for a wrangler config that fails cli/src/lint.ts (compatibility_date, observability, upload_source_maps, name matching package.json, wrangler.toml instead of json), bindings declared in wrangler.json that the code never reads or reads from globalThis, tests that number fewer than five or skip a binding, a path or auth check placed after the upstream fetch, dependency versions that break syncpack's exact pinning, and README markers or the deploy button out of place. Post one GitHub review that quotes each command's result, separates blocking issues from suggestions, and cites file and line for every finding. Do not push commits.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app/pull/42"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a review on the pull request. The summary quotes `pnpm -w check` with any linter line it printed, `pnpm -w test` from turbo, the touched template's `vitest` run and `wrangler deploy --dry-run`, and the Playwright spec result. Findings follow in the order `AGENTS.md` prescribes, each with file and line and marked blocking or suggestion, and a binding finding names both the `wrangler.json` entry and the `env` property the code uses.

The transcript keeps the install, every command and its output, the `dist` or `.wrangler` artifacts turbo produced, and the Playwright trace for the spec when it retried, so a reviewer can see why `wrangler deploy --dry-run` rejected a config rather than take the review's word for it.

Before merging, a maintainer confirms the dashboard-facing fields, since `preview_image_url`, `preview_icon_url` and `publish` are theirs to set, re-runs the template's tests on the branch, and dismisses suggestions that do not hold. A linter failure, a binding mismatch or fewer than five tests is blocking by default; a README wording change is not.

## Run it on every pull request opened

Create an automation in the Project with a `github` trigger on `pull_request.opened` and `pull_request.synchronize`, `branch_patterns` set to `main`, and this prompt. Each fire adds the pull request after the prompt, so every template submission and every push to it gets its own sandbox, its own turbo run and its own review. Only pull requests by an owner, member or collaborator fire the trigger, which matches this repository's own `Pull Request` workflow running without secrets for outside contributors.

Mark the automation `read_only`, since the review only reads and comments. The review is the result on the pull request and the run is listed in the Project. `max_runs_per_hour`, 1 to 30, bounds a busy day across dozens of templates; a fire past the cap is skipped as `rate_limited` and that pull request is reviewed on its next push.

## Why run it on Rush?

A template pull request fails for reasons the diff does not show: a `compatibility_date` one day off, a `wrangler.toml` where the linter wants JSON, a KV binding the test pool cannot find, a version that breaks syncpack across forty other templates. The repository encodes all of that in `cli/src/lint.ts`, `.syncpackrc.json` and `turbo.json`, and running it needs pnpm, workerd and Chromium. On Rush the agent runs the full `check` in its own sandbox and keeps the output, so the review quotes the linter's own line instead of paraphrasing the contributing guide.

One sandbox per pull request keeps reviews parallel when several templates land in a week, each with its own `.wrangler` state, and nothing is pushed to the contributor's branch. The maintainer gets findings ordered the way `AGENTS.md` asks, with the evidence attached, and the contributor sees the same output they would get from `pnpm run check` locally.

## Frequently asked questions

### Does it run every template's tests?

`pnpm -w test` runs `turbo run test` across the workspace with `--passWithNoTests`, as CI does, and the agent runs the touched template's own `pnpm test` and `pnpm run check` on top. The Playwright suite is filtered to the touched template's spec in `playwright-tests/`, since the full suite starts a dev server per template.

### Can it fix the linter findings itself?

`pnpm run fix` would, and `AGENTS.md` describes pushing fixes to the pull request's branch, but this prompt forbids pushing. The review quotes the exact linter line and names `pnpm -w fix:templates` as the command the author runs. Ask for a fix run separately if you want the agent to push.

### What about templates that need a container or Postgres?

`containers-template`, `grpc-container-template` and the Hyperdrive templates have Playwright specs and some have Workers tests, but their runtime needs are outside what `vitest-pool-workers` provides. The agent runs what the template's scripts run, and when a spec is skipped or fails for want of a backing service, the review says that rather than counting it as a finding against the pull request.

### Will it insist on the preview image fields?

Only when `cloudflare.publish` is `true`, which is what `lintPackageJson` checks. `CONTRIBUTING.md` says those URLs are supplied by the Cloudflare team during review, so for an unpublished template the review notes they are pending rather than blocking on them.
