What the agent does
Your backend starts a session per customer repository, and the agent reads what the project declares before running anything. In a Next.js codebase like nextjs/saas-starter, package.json pins next to 15.6.0-canary.59, a canary build rather than a release, alongside react and react-dom 19.1.0, tailwindcss 4.1.7, drizzle-orm ^0.43.1, stripe ^18.1.0 and zod ^3.24.4, all under dependencies with no devDependencies at all. pnpm-lock.yaml is lockfileVersion: '9.0', so it installs with pnpm. It runs pnpm outdated and keeps the direct packages whose latest release is a major version or more ahead of the locked one; a canary pin is reported in its own entry, since "behind" means something different for a prerelease.
Next it looks for tests and finds none. The scripts are dev, build, start and five db: scripts for Drizzle and seeding, with no test or lint script and no test files. The prompt covers that case: when a project defines no tests, the agent reports pnpm build and pnpm exec tsc --noEmit as the checks it could run, and says plainly in the tests array that no test command exists. The build needs configuration. lib/db/drizzle.ts throws POSTGRES_URL environment variable is not set at import, and lib/payments/stripe.ts constructs a Stripe client from STRIPE_SECRET_KEY the same way, so the agent reads .env.example, sets placeholder values for POSTGRES_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, BASE_URL and AUTH_SECRET in the sandbox only, and records that it did.
For risky patterns it reads the code paths that matter in a SaaS app. It opens every route handler under app/api/ and checks whether each one checks the session: app/api/user/route.ts returns whatever getUser() gives, so the agent follows getUser into lib/db/queries.ts to see what an unauthenticated request receives. It reads app/(login)/actions.ts, where server actions are wrapped in validatedAction or validatedActionWithUser, and checks that each action changing team membership or the account uses the second. It reads lib/auth/session.ts, which builds the JWT key from process.env.AUTH_SECRET, and middleware.ts, which only protects paths starting with /dashboard. The Stripe webhook in app/api/stripe/webhook/route.ts calls stripe.webhooks.constructEvent, so it is verified and does not go on the list.
No file is changed. The agent works on its own clone, the placeholder environment exists only in its sandbox, and the turn ends with the JSON as the final answer.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Audit this Next.js repository without changing any file. Return only JSON with three arrays. outdated_dependencies: direct dependencies whose latest release is at least one major version ahead of the locked version, with name, locked and latest; report canary or prerelease pins with a note. tests: each test command in package.json and the CI workflows, with passed true or false and the last 20 lines of output when it failed; if there are none, say so and report pnpm build and tsc --noEmit as the checks instead, using placeholder values from .env.example in the sandbox. risky_patterns: up to ten issues such as API routes or server actions that do not check the session, secrets read without a check that they are set, unverified webhooks, or user input reaching SQL or HTML unescaped, each with file, line, pattern and a one-sentence reason.",
"resources": [
{
"url": "https://github.com/your-org/your-app"
}
]
}- 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.
- 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.
- 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
The session's result is the JSON, and the run.completed webhook includes it as data.result up to 16 KiB; for a larger audit the webhook leaves it out and your server reads data.session_url with the key. For a repository like this one the tests array is honest about what exists: an entry saying no test command is defined, then the build and type-check results with a note that placeholder environment values were used. A customer reading the audit learns both that the code compiles and that nothing tests it.
Your product validates the three arrays before saving them. Someone reviewing audits checks that each risky_patterns entry names a concrete path (this route, this action, this line) and a reason tied to it, and that a build failure is not just a placeholder value the code rejected. The transcript keeps the pnpm outdated output, the build log and every file the agent read, so each finding can be traced back.
Run it on every new customer onboarding
When a customer finishes onboarding in your product and picks a repository, start the audit from the same request handler. Send an Idempotency-Key derived from the customer and repository so a double-submitted form returns the run already started, and keep the execution_id from the 202 with the customer record.
The key's webhook receives run.completed with the execution_id when the audit ends. Verify the Standard Webhooks signature with the whsec_ secret, find the customer, store data.result, and show the audit on their first dashboard. If the event is run.failed, show that the audit could not finish and offer a retry with a new idempotency key.
The use case this job follows, with its automation and trigger: Run an agent per customer task.
Why run it on Rush?
Building a customer's Next.js app means running pnpm install on their dependency tree, including any install scripts, and executing their build. Doing that in your own backend puts every customer's code on the same machines as your product. A Rush session runs it in a sandbox of its own, and the clone and the placeholder environment stay there; what reaches your servers is the JSON.
The audit is evidence, not an opinion. The outdated list comes from the lockfile and the registry, the build result from a build that ran, and each risky pattern from a file the agent opened, all recorded in the session transcript. Many customers can be audited at the same time, one sandbox each, up to the key's max_concurrent limit.
Frequently asked questions
What does the audit do when a repository has no tests?
It says so. The tests array gets an entry stating that no test command is defined, followed by the results of pnpm build and tsc --noEmit, which are the checks a project with no tests still has. That gap is often the most useful line in the audit.
Does it need my customer's real environment variables?
No. The agent reads .env.example and sets placeholder values in the sandbox so the build can run, and the audit notes that it did. Real secrets are never needed for an audit, and you should not send them.
Does it work with npm or Yarn projects?
Yes. The agent picks the package manager from the lockfile in the repository (package-lock.json, yarn.lock or pnpm-lock.yaml) and the packageManager field when there is one, and uses that manager's own outdated command.
How many audits can run at once?
As many as the key's max_concurrent allows, 4 by default. Starting one more answers 429; queue the request on your side and start it when a webhook tells you another audit finished.