# Turn a Labeled GitHub Issue Into a Pull Request on a React Router App

Yes. Label a GitHub issue on a React Router 7 app and an agent reproduces it with a Playwright test, fixes it and opens a pull request that closes the issue.

[Run this on Rush](https://cloud.getrush.ai/run/github-issue-to-pr/react-router/), in a Project that has your repository.

## What the agent does

The agent clones the app into its own cloud sandbox with the labelled issue after its prompt and reads how the repository runs before it touches the bug. In a React Router 7 app like documenso/documenso, the web app lives in `apps/remix`, a name kept from before the move: its `package.json` depends on `react-router` 7 with `@react-router/node`, `@react-router/serve` and `@react-router/dev`, and its `build` runs `react-router typegen && tsc` before `react-router build` and a Rollup build of the Hono server. The root `package.json` requires Node 24 and npm 11 with `packageManager` set to `npm@11.19.1`, runs the workspaces through Turbo, lints with Biome 2.4.8 (`npm run lint` is `biome check .`), and holds the Prisma commands under `prisma:*`. The agent uses npm, not pnpm, because that is what the lockfile and `.github/actions/node-install` use.

Reproducing comes first, and the repository has the harness for it. `packages/app-tests/playwright.config.ts` runs `e2e/` with three projects, `api`, `license` and `ui`, on Desktop Chrome at 1920 by 1200, with `retries` 4 and `maxFailures` 1 in CI, traces and video on failure, and a `__disable_animations` cookie. `e2e/fixtures/authentication.ts` signs in through `/api/auth/email-password/authorize` with a CSRF token, and `@documenso/prisma/seed` exports `seedUser`, `seedBlankDocument`, `seedPendingDocument` and the rest that `e2e/document-flow/signers-step.spec.ts` uses to build a document before clicking through it. The agent reads the issue's steps against the route the behaviour lives in, such as `app/routes/_recipient+/sign.$token+` for a signing report, and writes one spec next to its neighbours that follows the steps with the seeds and fails on the current code.

To run it, the agent does what `.github/workflows/e2e-tests.yml` does: `cp .env.example .env`, `npm ci --no-audit` and `npm run prisma:generate`, `npm run dx:up` to start the `docker/development/compose.yml` services (Postgres 15 on port 54320, Inbucket for mail, Redis, Gotenberg), `prisma:migrate-dev`, `prisma:seed`, `npx playwright install --with-deps`, then `npm run ci` with `NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH` set to `apps/remix/example/cert.p12` and `DANGEROUS_BYPASS_RATE_LIMITS` on, narrowed with `E2E_TEST_PATH` to the new spec so a single failing test takes minutes rather than the whole suite. It confirms the failure, then fixes the cause with the smallest change in the route, the tRPC router under `packages/trpc` or the server-only code under `packages/lib/server-only`, and runs the spec again until it passes.

Before it pushes, it runs `npm run lint` for Biome and `npm run build` for the Remix workspace, and if the fix touched a string, `npm run translate:extract` so the Lingui catalogs stay in step. The branch follows `CONTRIBUTING.md`, with the issue number in its name, and the pull request title follows the Conventional Commits form that `semantic-pull-requests.yml` enforces, such as `fix: ...`. The description says `Closes #<issue>`, explains the cause in the file's own terms and quotes the test failing before and passing after. Changes under `packages/app-tests/e2e` get the repository's own e2e-changes label from `.github/labeler.yml`, so a reviewer sees at once that a test was added.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "Fix the GitHub issue that follows this prompt in this React Router 7 monorepo. The web app is apps/remix (React Router, not Next.js, despite the name); use npm 11 and Node 24 as package.json requires. Find the route under apps/remix/app/routes, the tRPC router under packages/trpc or the server-only module under packages/lib/server-only the behaviour lives in. Reproduce the issue first with one Playwright spec under packages/app-tests/e2e next to the closest existing spec, using the seed helpers from @documenso/prisma/seed and apiSignin from e2e/fixtures/authentication.ts, and confirm it fails. Set up as .github/workflows/e2e-tests.yml does: cp .env.example .env, npm ci --no-audit, npm run prisma:generate, npm run dx:up, npm run prisma:migrate-dev, npm run prisma:seed, npx playwright install --with-deps, then npm run ci with NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=./example/cert.p12 and DANGEROUS_BYPASS_RATE_LIMITS=true, narrowed to your spec with E2E_TEST_PATH. Fix the cause with the smallest change, run the spec again, then npm run lint and npm run build; run npm run translate:extract if you changed a user-facing string. Name the branch with the issue number as CONTRIBUTING.md asks, give the pull request a Conventional Commits title, and write Closes #<issue>, the cause, and the failing-then-passing test output in its description.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

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 pull request whose title passes the Conventional Commits check and whose body says `Closes #<issue>`. The diff holds one new spec under `packages/app-tests/e2e`, the change in the route, tRPC procedure or server-only module, and any regenerated Lingui catalog. The description names the cause in the file's own terms and quotes the Playwright output before and after the fix, with the `E2E_TEST_PATH` it ran.

The push runs the repository's own workflows on GitHub: `ci.yml` builds the app and the Docker image, `e2e-tests.yml` runs the whole Playwright suite against fresh services, and `pr-labeler.yml` adds the e2e-changes label. A reviewer reads the spec first and checks that it would fail on `main`, then that the fix stayed where the issue was rather than widening into a refactor, and that no string was changed without its catalog entry.

The session keeps the whole record: the services starting, the failing run, the edits, the passing run, Biome and the build. `GET /o/{org}/sessions/{id}` returns the pull request once the turn has finished, and a follow-up on the same session can add a case for a second recipient or an assistant role without redoing the setup.

## Run it on every GitHub issue labelled agent

In the console, add an automation to the Project with this prompt and a `github` trigger on `issues.labeled`, filtered to the `agent` label in `labels`. The trigger appends the issue after the prompt, so the automation's prompt holds no example issue. Only labels added by a repository owner, member or collaborator fire it, which fits a repository where `issue-opened.yml` first labels every new issue `status: triage` and a maintainer decides what to hand off. Each labelled issue gets its own sandbox, branch and pull request.

From your own triage tool, the same request goes to `POST /o/{org}/sessions` with the issue's text after the prompt and a `request_id` made from the issue id, so a redelivered event starts nothing new. A key's `webhook_url` reports when a run that key started finishes, with `data.session_url` that reads the pull request.

## Why run it on Rush?

Reproducing a bug in this app means Postgres, a mail catcher, Redis, a PDF converter, Prisma migrations and seeds, and a Playwright install, which is why bug reports wait. In its own sandbox the agent does that setup the way `e2e-tests.yml` does, runs one spec until it fails and then until it passes, and keeps every command and its output, so the pull request's claim about the cause rests on a test rather than a reading.

One sandbox per issue means a Monday's worth of triaged bugs can be worked in parallel without sharing a database, and each pull request arrives with the test that would have caught it. The reviewer gets a diff, a failing-then-passing run and a label on the e2e change, and nothing is pushed anywhere but the new branch.

## Frequently asked questions

### Why does the page say React Router when the app directory is called remix?

Because the app depends on `react-router` 7 and the `@react-router/*` packages, builds with `react-router build` and runs `react-router typegen`; `apps/remix` is a name kept from before the move. The only Next.js in the repository is the docs site under `apps/docs`. The prompt says so, so the agent does not reach for Next.js conventions.

### What if the issue cannot be reproduced?

The agent says what it tried: the spec it wrote, the seeds it used and the output it saw, and opens no pull request. It can leave that as the run's `result` for the maintainer to read, or, if the automation allows comments, as a comment on the issue asking for the missing step. It does not change code it could not show was wrong.

### Will it run the entire e2e suite?

Not in the sandbox. `E2E_TEST_PATH` narrows `npm run ci` to the new spec, which is what `packages/app-tests/package.json` provides it for. The full suite runs on GitHub through `e2e-tests.yml` when the pull request is pushed, with the `maxFailures` and retries that workflow sets.

### The repository says it no longer accepts external pull requests. Does this still apply?

The run opens the pull request on your own repository or fork, where you are the maintainer; it never opens one upstream. That repository's `CONTRIBUTING.md` also asks that every line of AI-assisted code be reviewed by the person submitting it, and the failing-then-passing test in the description is there to make that review short.
