All jobs

Turn GitHub Issues into Pull Requests for a React Project

Yes. Label a GitHub issue on a React project and an agent reads it, adds a Vitest test, runs the suite, and opens a pull request that links the issue.

Run this on RushIn a Project that has your repository.

What the agent does

The agent identifies the package manager and the test runner from the repository before it edits a component. In a library shaped like pmndrs/zustand, package.json is version 5.0.15, packageManager is pnpm@11.3.0, and engines.node is >=12.20.0. Both pnpm-lock.yaml and package-lock.json are present, so the agent installs with pnpm because the packageManager field says so, and it does not delete the other lockfile. devDependencies pin vitest ^4.1.10, typescript ^6.0.3 and react ^19.2.8. The test script runs every test:* script: test:format is prettier --list-different, test:types is tsc --noEmit, test:lint is eslint, and test:spec is vitest run.

The code the issue usually names is small and split on purpose. src/index.ts only re-exports ./vanilla.ts and ./react.ts. createStore is in vanilla.ts and returns an api with setState, getState, getInitialState and subscribe. create is in react.ts and binds that api to a hook. useStore reads the slice through React.useSyncExternalStore, with getState for the client snapshot and getInitialState for the server snapshot. Middleware lives in its own files: persist.ts, immer.ts, devtools.ts, redux.ts, subscribeWithSelector.ts, ssrSafe.ts and combine.ts. An issue about selectors is not a change to persist, and the agent says which file it opened.

Tests already mirror that split. vitest.config.mts aliases zustand to src/index.ts and zustand/* to src/*.ts, sets environment jsdom, dir tests, globals true and setupFiles tests/setup.ts. tests/basic.test.tsx imports create from zustand and createWithEqualityFn from zustand/traditional, and renders with @testing-library/react. Other files cover vanilla stores, persist, devtools, immer, shallow and SSR. The agent adds the new test in the file that already covers that middleware, or in basic.test.tsx when the issue is about create itself. It runs pnpm test:spec first, which is vitest run, then pnpm test:types when the change touches a type in vanilla.ts.

It does not rebuild the published dist as part of fixing an issue. The build script chains rollup for base, vanilla, react, middleware, immer, shallow and the traditional entry, then rewrites .d.ts paths. That pipeline is what publish uses. A bug fix belongs in src/ and tests/, and the pull request says the dist rewrite was left for the release script. examples/ is left untouched unless the issue points at an example. If vitest fails because jsdom and useSyncExternalStore disagree, the agent reads the failure and fixes the test or the subscription, and it does not set globals or the environment to something the config does not already use.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Resolve GitHub issue #ISSUE in this repository. Read the issue and its comments. In a library laid out like pmndrs/zustand, install with pnpm because package.json's packageManager field says pnpm@11.3.0, even though package-lock.json is also present. Read src/vanilla.ts (createStore) and src/react.ts (create, useStore via useSyncExternalStore) before editing. Add a Vitest test under tests/ next to the existing file for that behaviour, using the jsdom config in vitest.config.mts. Run pnpm test:spec and, if you changed types, pnpm test:types. Do not rebuild dist, do not edit both lockfiles, and do not change examples unless the issue says to. Open a pull request whose body says Fixes and the issue number and quotes the Vitest summary.",
  "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 on its own branch. In a Zustand-shaped repository the diff is a file under src/ or src/middleware/ and a test under tests/, for example a new case in tests/basic.test.tsx or tests/persistSync.test.tsx. dist/ is absent from the diff. The body contains Fixes and the issue number, the pnpm test:spec summary, and a note when tsc --noEmit was also run. package.json's packageManager field is unchanged.

The session's repository and pull request fields are how you open the review. The transcript lists the pnpm commands and the Vitest reporter output, including a failed run the agent then fixed. Nothing is merged by the run. The branch sits until someone approves it.

A reviewer checks that the test renders through the same @testing-library/react helpers the neighbouring tests use, that a selector bug was fixed in useStore rather than by wrapping the hook, and that a vanilla bug was fixed in createStore so React and non-React callers both see it. The Fixes line is what attaches the pull request to the issue.

Run it on every labelled GitHub issue

On your server, handle the GitHub issues webhook. For issues.labeled with the label you chose, send POST https://api.prix.dev/o/{org}/sessions with this body, the repository URL in resources, and the issue number substituted into input. An Idempotency-Key set to the delivery id makes a retry return the same session. The App must be installed on the repository or the call is 422 RESOURCE_NOT_ACCESSIBLE.

The key's webhook_url receives run.completed, run.failed or run.cancelled when the turn finishes, and session_url is where you read the pull request. Check webhook-signature against the raw body with the whsec_ secret. A key's max_concurrent, 4 unless you set another number, is the most sessions in progress. Further creates return 429, which is the signal to queue labels rather than drop them.

The use case this job follows, with its automation and trigger: Turn a Linear label into a PR.

Why run it on Rush?

A Zustand issue is easy to fix in the wrong layer: the hook in react.ts, the store in vanilla.ts, or a middleware that wraps setState. On a laptop that usually means pnpm install, a jsdom Vitest run, and a tsc --noEmit that the test script hides inside pnpm test. The agent runs those in a sandbox with its own clone, and the working tree on your machine stays where you left it.

The pull request is the review surface, and the transcript is the evidence of what pnpm test:spec printed. You can see that dist was not rebuilt and that the extra lockfile was not rewritten. Other labelled issues run beside this one, each with its own sandbox, up to max_concurrent.

Frequently asked questions

pnpm and npm lockfiles are both in the tree. Which does it use?

pnpm, because package.json's packageManager field is pnpm@11.3.0. The agent does not delete package-lock.json and does not run npm install, which would refresh the wrong lockfile. If your repository has only package-lock.json, the prompt should say npm ci instead.

Does it run format and lint, or only Vitest?

The request runs pnpm test:spec, and pnpm test:types when types change. test:format and test:lint are part of pnpm test but are not required for a behaviour fix. Add them to the prompt when you want prettier and eslint on the same run. A format failure in a file the issue did not touch is reported, not rewritten across the repository.

Will it commit the rollup dist output?

No. The build script's postbuild step rewrites declaration files and copies package.json into dist. That is release machinery. The pull request contains src and tests. Shipping dist is a separate release, and the agent says it left that alone.

The bug shows up in React 19 and in a vanilla store. Where is the fix?

useStore in src/react.ts is a subscriber over the vanilla api. If getState is wrong for every caller, the fix is createStore in vanilla.ts and the test imports the vanilla entry. If only the hook's snapshot is wrong, the fix is the useSyncExternalStore selectors in react.ts, with a render test in tests/basic.test.tsx.

Can it fix an issue in the examples directory?

Only when the issue says the example is the bug. examples/ is not part of the Vitest dir, which is tests/. A library fix is covered under tests/ so it stays true for every caller, and the example is updated in a follow-up when you ask for that.