All jobs

Turn Linear Issues into Pull Requests for a Next.js App

Label the issue and an agent reads it, implements it in your Next.js app's server actions and pages, checks the build and opens a pull request that links the issue.

Run this on RushIn a Project that has your repository.

What the agent does

The run starts with the issue and the code side by side. A resources entry of the form https://linear.app/<workspace>/issue/<ID> puts the issue into the prompt through your Linear connection, and the repository entry clones the app. For an issue like "let a team owner rename the team from the settings page" in an app shaped like nextjs/saas-starter, the agent reads package.json (Next.js 15 canary with next dev --turbopack, React 19.1, Drizzle ORM with drizzle-kit, postgres, jose, bcryptjs, zod, swr, Tailwind 4, and no test or lint script), next.config.ts (experimental.ppr and clientSegmentCache), middleware.ts (redirects /dashboard without a session cookie and re-signs the cookie on GET) and .env.example (POSTGRES_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, BASE_URL, AUTH_SECRET).

Then it finds where the feature belongs. lib/db/schema.ts already has teams.name as a non-null varchar(100), team_members.role, and an ActivityType enum used by logActivity. The settings area is app/(dashboard)/dashboard/: layout.tsx lists the Team, General, Activity and Security pages, page.tsx is a client component that reads /api/team and /api/user with SWR and drives removeTeamMember and inviteTeamMember through useActionState, and general/page.tsx shows the pattern for an editable form bound to updateAccount. The actions live in app/(login)/actions.ts, each a zod schema passed to validatedActionWithUser from lib/auth/middleware.ts, and the queries in lib/db/queries.ts (getUserWithTeam, getTeamForUser). Nothing has to be invented; the agent follows the shape that is there.

The change is small and in the project's idiom: a teamNameSchema (name from 1 to 100 characters, matching the column) and an updateTeamName action that loads the caller with getUserWithTeam, refuses when the membership role is not owner, updates teams.name and updatedAt, and logs a new ActivityType.UPDATE_TEAM entry; the enum gains the value and dashboard/activity/page.tsx gains an icon for it in iconMap. On the Team page a card with the current name, an Input and a Button from components/ui/ posts to the action with useActionState, shows the returned error or success, and calls SWR's mutate('/api/team') so the header updates. Members who are not owners see the name without the form.

The repository has no test runner, so the agent checks the change the way the project can be checked: it starts a Postgres in the sandbox, writes the five variables from .env.example into .env, runs pnpm db:migrate, then pnpm build and npx tsc --noEmit, and opens the page in its browser as a signed-up owner to rename the team and see the activity entry. If the issue asks for tests, it adds Vitest with one file for the new action and a test script rather than a whole harness. The pull request description links the issue, explains the role check and the enum change, and quotes the build output.

Start it with one API call

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

{
  "agent": "claude",
  "input": "Do the work the Linear issue given as a resource describes: let a team owner rename the team from the settings page. Read the issue and its comments first. Follow this app's patterns: a zod schema and a validatedActionWithUser server action in app/(login)/actions.ts, a Drizzle update in lib/db, an ActivityType entry logged through logActivity, and a card on the Team page with the existing Input and Button components and useActionState. Only members whose role is owner may rename. Run pnpm db:migrate against a local Postgres, then pnpm build and tsc --noEmit, and exercise the page in the browser. If the project has no test runner, add Vitest with one test for the new action rather than a full harness. Open a pull request whose description links the issue and quotes the build result. Do not merge.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    },
    {
      "url": "https://linear.app/your-org/issue/ENG-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 pull request on a new branch whose diff touches app/(login)/actions.ts (the schema and the action), lib/db/schema.ts (one enum value), app/(dashboard)/dashboard/page.tsx (the rename card), app/(dashboard)/dashboard/activity/page.tsx (the icon), and, when a test runner was added, package.json, vitest.config.ts and one test file. No migration is needed because teams.name already exists, and the description says so.

The description links the issue by its URL, summarises the role rule in one sentence, and quotes the pnpm build and tsc --noEmit results; the session's record holds the browser steps, so a reviewer can see the rename happen and the activity row appear without checking out the branch.

Before merging, a reviewer checks that the owner check reads the membership role from team_members rather than trusting the client, that the zod limit matches the varchar(100) column, that mutate('/api/team') is called so the header shows the new name, and that the activity enum change did not leave iconMap missing a key, which would fail type-checking.

Run it on every Linear issue labeled agent

Add an automation to the Project with this prompt and a linear trigger on linear.issue.labeled, with config.labels naming the label your team uses to hand work to an agent. Each labeled issue starts one run with the issue as its context, so a ticket with a clear acceptance line turns into a pull request without anyone copying it into a prompt. Changes made by an app integration never fire the trigger, so a bot that labels issues starts no runs.

Pair it with linear.issue.state_changed and config.states to make a two-step flow: a state mapped to plan starts a read-only run that comments its plan on the issue, and the next state mapped to exec starts the run that opens the pull request. Set max_runs_per_hour on the automation so a bulk relabel does not start a run per issue at once.

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

Why run it on Rush?

A Next.js app with server actions, Drizzle and a Postgres dependency is quick to change and slow to set up for one small ticket: a database, five environment variables, a migration, and a build before you can see the page. On Rush the agent does that in its own sandbox with a browser, and the pull request arrives with the build output and a record of the page working, so the ticket's cost is the review, not the setup.

Issues arrive in batches. Each labeled issue gets its own run and its own sandbox, so ten tickets on a Monday become ten pull requests to review rather than ten branches on one laptop, and the trail from issue to pull request to build result is kept for each.

Frequently asked questions

How does the agent see the Linear issue?

As a resources entry with the issue's URL, read through your Linear connection; the issue's title, description and comments are in the prompt before the first file is opened. A repository that no GitHub App installation covers, or an issue with no Linear connection, is refused when the run is created rather than failing later.

The app has no tests. What counts as proof?

The build (pnpm build), the type check (tsc --noEmit) and the browser session in the record where the rename is performed and the activity log shows it. If the issue asks for tests, the agent adds Vitest with one test for the action and a test script, and says so in the description.

Will it add a database migration?

Only when the schema changes. For a team rename the teams.name column already exists, so drizzle-kit generate has nothing to emit and the agent leaves lib/db/migrations/ alone. An issue that needs a new column gets a generated migration in the same pull request.

Does it need Stripe to work?

Not for this issue. STRIPE_SECRET_KEY is set to a placeholder so the module loads; the pricing page and checkout are not exercised. An issue that touches billing would need a Stripe test key stored as a Project secret.

Can it comment the pull request link on the issue?

Not yet from inside the run. A Linear sign-in connects, but a run cannot name it as a connection, so the agent links the issue from the pull request and your handler for run.completed can post the link back to Linear.