What the agent does
In a NestJS project like lujakob/nestjs-realworld-example-app, TypeScript is pinned at ^3.8.3, and it sits in dependencies rather than devDependencies. tsconfig.json targets es6 with lib es2017, experimentalDecorators and emitDecoratorMetadata on, noImplicitAny off, no strict flag and no skipLibCheck. Before bumping anything the agent copies src/config.ts.example to src/config.ts in the sandbox, because tsc cannot resolve the SECRET import without it, and runs npx tsc --noEmit on the current version to record a baseline count.
Then it installs the latest TypeScript and runs tsc again. With no skipLibCheck, the first wave of errors usually comes from old type packages rather than the app: @types/node ^13.13.4 and @types/jest ^25.2.1 were written for a much older compiler. The agent bumps type packages to versions that match the runtime and test runner the project actually uses, and records how many errors that removed, before touching a line of src/.
What remains is the app's own code, and the agent fixes it with types, not escapes. The places it reads first are the ones already typed loosely: jwt.verify results stored as decoded: any in src/user/auth.middleware.ts, src/user/user.decorator.ts and src/shared/base.controller.ts, which become a small interface for the token payload with a type guard; articleData: any in ArticleService.update, which becomes the existing DTO type; and req.user = user.user in the auth middleware, which needs a declaration that adds user to Express's Request instead of a cast. Calls such as userRepository.findOne({email}) are checked against the TypeORM 0.2 types the project installs.
The prompt forbids any, casts through unknown and ts-ignore, so when a fix would need one, the agent stops and explains the type problem in the pull request instead. After tsc reports zero errors it runs npm test, whose only spec, src/tag/tag.controller.spec.ts, needs a MySQL database from ormconfig.json.example, and runs node dist/main.js after a build to see the app start.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Upgrade TypeScript to the latest version in this project and record the tsc --noEmit error count before and after. Copy src/config.ts.example to src/config.ts in the sandbox only. First update outdated @types packages and record how many errors that removes. Then fix every remaining error with real types: no any, no casts to unknown, no ts-ignore or ts-expect-error. Type jwt.verify payloads with an interface and a type guard, and extend Express's Request for req.user with a declaration. Start MySQL from ormconfig.json.example, run npm test, build and start the app. Open a pull request with the error counts at each step and a list of each fix grouped by cause.",
"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 pull request changes package.json and the lockfile for TypeScript and the type packages, adds a declaration file for the Request extension and an interface for the token payload, and edits the source files that had errors. The description has three numbers from tsc in the sandbox: the baseline on the old compiler, the count right after the bump, and the count after the type packages were updated, followed by the fixes grouped by cause, with the file and the error code for each.
A reviewer checks the diff for anything the prompt ruled out (no new any, no as unknown as, no ts-ignore) and reads the new types where a value used to be any, since those are where runtime behaviour could change if a guard rejects a value the old code accepted. If an error could not be fixed without an escape hatch, it appears in the description as an open item, not hidden in the diff.
Run it on every TypeScript release
When a new TypeScript version ships, send one POST /o/{org}/sessions per repository with the version in the prompt. Each run reports the before and after error counts, so even a run that cannot finish tells you how far each codebase is from the new compiler.
Dependabot or Renovate pull requests that bump typescript and fail CI are another trigger: a handler can start a run on that pull request's branch by putting https://github.com/your-org/your-app/pull/123 in resources, so the agent fixes the errors on the branch that introduced them.
The use case this job follows, with its automation and trigger: Fix a bug from an alert.
Why run it on Rush?
A compiler upgrade on an older NestJS codebase can surface errors across dozens of files, and fixing them properly means running tsc over and over while the code is half-changed. In a Rush sandbox the agent can do that on its own copy with a MySQL server for the tests, and every tsc run is kept with its output, so the counts in the pull request are the real ones.
If several services share the same old TypeScript, each gets its own run and its own pull request, started in parallel up to the key's concurrency limit. The fixes stay separate, so one service's harder errors never hold up another's merge.
Frequently asked questions
Will it just add any or ts-ignore to make the errors go away?
No. The prompt forbids any, casts through unknown, ts-ignore and ts-expect-error. If an error cannot be fixed with real types, the agent lists it as open in the pull request with an explanation, so you can decide.
Will it turn on strict mode?
Not as part of this job. Strict mode is a separate change with its own set of errors, and mixing it into a compiler upgrade makes both harder to review. You can ask for it in a follow-up message to the same session.
What about errors inside node_modules?
Those come from type packages that are too old for the new compiler. The agent updates the @types packages to versions that match your runtime first, rather than turning on skipLibCheck to hide them, and reports how many errors that step removed.
Does it upgrade NestJS too?
Only if a NestJS type definition cannot compile on the new TypeScript at all, and then the description says which error forced it. Otherwise the framework version stays as it is.