What the agent does
The agent reads the repository before it runs a schematic. In an app shaped like realworld-apps/angular-realworld-example-app, package.json pins every @angular/* package to 21.2.12 and @angular/cli to 21.2.10, the lockfile is bun.lock, and the scripts are bun run start, bun run build, bun run test on Vitest 4 through @analogjs/vite-plugin-angular, and bun run test:e2e on Playwright. CLAUDE.md says to run bun run setup first, because the theme stylesheet and the end-to-end specs live in the realworld git submodule, and to run bun run format before presenting code. angular.json has one project, angular-conduit, built with @angular/build:application into dist/angular-conduit, with an explicit assets list rather than a public folder, a production budget of 500 kB warning and 1 MB error on the initial bundle, and src/_redirects copied to the output root.
The bootstrap is standalone. src/main.ts calls bootstrapApplication(AppComponent, appConfig), and src/app/app.config.ts provides zoneless change detection, the router, an HttpClient with the api, token and error interceptors, and an app initializer that checks the stored JWT. src/index.html loads Ionicons and Google Fonts from external hosts. These are the places the PWA work touches: the service worker is registered as a provider in app.config.ts, and the manifest link and theme-color meta go into index.html.
The agent runs bunx ng add @angular/pwa@21 --skip-confirmation, pinning the schematic to the 21 line because @angular/pwa 21.2 asks for @angular/cli 21.2.10 or newer and the latest 22 line asks for CLI 22. The schematic adds @angular/service-worker at 21.2.12, which must match @angular/core exactly, writes ngsw-config.json and manifest.webmanifest with an icon set, adds provideServiceWorker('ngsw-worker.js', { enabled: !isDevMode(), registrationStrategy: 'registerWhenStable:30000' }) to the providers, and sets serviceWorker in the build options. Because this project lists assets explicitly, the agent checks the entries the schematic wrote against the existing assets array and the _redirects entry rather than assuming a public directory. It then adds the Google Fonts and Ionicons origins to an assetGroups entry in ngsw-config.json so the app shell renders offline with its real typefaces.
Updates are handled, not just installed. A small src/app/core/pwa/update.service.ts subscribes to SwUpdate.versionUpdates, and on VERSION_READY prompts for a reload; its spec under src/**/*.spec.ts, which vitest.config.ts includes, mocks SwUpdate with an observable and asserts the prompt fires once. The agent runs bun run build with the production configuration and confirms dist/angular-conduit/browser/ngsw.json and the manifest are in the output, serves that directory and loads it in the sandbox browser to confirm the worker registers, then runs bun run test, bun run test:e2e and bun run format:check.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Make this Angular app installable as a PWA. Read package.json, bun.lock, CLAUDE.md, angular.json, src/index.html, src/main.ts and src/app/app.config.ts first, and run bun run setup so the realworld submodule is present. Add @angular/pwa with the schematic pinned to the same major as @angular/cli, check what it wrote into angular.json against the explicit assets list, cache the external font and icon stylesheets in ngsw-config.json, add an update service that prompts to reload on VERSION_READY with a Vitest spec, build for production and confirm ngsw.json is in dist/angular-conduit/browser, serve the build and confirm the service worker registers, run bun run test, bun run test:e2e and bun run format:check, and open a pull request.",
"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
What comes back is a pull request on its own branch. The diff adds ngsw-config.json, the manifest and its icons, and src/app/core/pwa/update.service.ts with its spec; it changes package.json and bun.lock for @angular/service-worker, angular.json for the serviceWorker option and any asset entries, src/index.html for the manifest link and theme-color, and src/app/app.config.ts for the provider. The description lists the cached origins, states the registration strategy, and names the production bundle size the build printed against the 500 kB budget.
The checks are the proof. The Format Check workflow runs bun run format:check, the Playwright Tests workflow runs the RealWorld end-to-end suite against the dev server, and the Build and Release workflow on main zips dist/angular-conduit/browser, so ngsw.json ships in the same artifact. The session's trajectory at GET /o/{org}/sessions/{id}/messages keeps the ng add output, the production build and every test run.
Before merging, a reviewer checks that @angular/service-worker matches @angular/core at 21.2.12, that the worker is disabled in development so bun run start is unaffected, and that the API host is not in an asset group, since cached API responses would serve stale articles. Nothing reaches main until the pull request merges, and the worker only takes effect on the deployed build.
Run it on every new Angular repository
Start one run per frontend repository that has no service worker from your own server: POST /o/{org}/sessions with this prompt and that repository in resources, one call each. GET /o/{org}/github lists every repository the Rush GitHub App installation can reach, so a script can find the ones with an angular.json and no ngsw-config.json and start a run for each. Each run has its own sandbox and its own branch, and a request_id per repository makes a retried call return the run it already started.
Give the key a webhook_url and each run POSTs run.completed with its session_url when the turn finishes, so the pull request links collect on your side without polling. A key has at most max_concurrent runs in progress at once, 4 by default, and a further start is 429, so a batch over many repositories should feed them in as earlier ones finish.
The use case this job follows, with its automation and trigger: Hand off from your terminal.
Why run it on Rush?
A PWA is only done when the production build registers a worker and the app shell loads with the network off, and that check is awkward on a laptop: the worker is disabled in development, so you build, serve the output on another port, open devtools, toggle offline and reload, then do it again after every change. On Rush the agent does that loop in its own sandbox with its own browser, and each build and each page load is in the transcript.
The hand-off is also the proof. The pull request carries the config, the provider, the update service and its spec; the repository's Playwright and format workflows run on it; and the trajectory shows the production build's bundle sizes and the worker registering. Several repositories mean several sandboxes at once, each with its own pull request, rather than a sequence of afternoons.
Frequently asked questions
Why pin the schematic to version 21?
Because @angular/pwa on the 22 line declares a peer dependency on @angular/cli 22, and this repository is on CLI 21.2.10 with every framework package at 21.2.12. The 21.2 line of the schematic asks for CLI 21.2.10 or newer and adds @angular/service-worker at the version that matches @angular/core exactly, which the service worker package requires.
Will the service worker run during bun run start?
No. The provider is registered with enabled: !isDevMode(), so the worker is active only in production builds. The Playwright suite runs against the dev server, as playwright.config.ts starts the dev server on port 4200, so it keeps testing the app without a worker in the way.
What gets cached offline?
The app shell the schematic lists in ngsw-config.json: index.html, the built scripts and styles, the manifest and the assets, plus the Google Fonts and Ionicons stylesheets from src/index.html, which the agent adds as external URLs in an asset group. API responses are not cached, so article lists and the signed-in user always come from the network.
What about the explicit assets list in angular.json?
This project has no public directory; angular.json lists src/favicon.ico, the SVGs from the realworld submodule and src/_redirects one by one. The agent reads what the schematic wrote for the manifest and icons and reconciles it with that list before building, and the pull request shows the final assets array so a reviewer can see nothing was dropped.
How do users get a new version?
The worker fetches ngsw.json on navigation and downloads a changed build in the background. The added update.service.ts listens on SwUpdate.versionUpdates and, on VERSION_READY, asks the user to reload; its spec mocks SwUpdate and asserts the prompt. With registerWhenStable:30000 the worker registers once the app is stable or after 30 seconds, whichever comes first.