What the agent does
This SvelteKit app already put its colours in variables, and they only describe a light page. package.json names the app realworld.svelte.dev, with @sveltejs/kit ^2.52.2, svelte ^5.55.7 and vite ^7.3.2. Scripts are dev, build, preview, lint (prettier --check) and format. There is no test script, and the tree has no test or spec files. The lockfile is pnpm-lock.yaml. src/app.html links /conduit-theme.css, which is static/conduit-theme.css, and the comment at the top calls it Conduit Minimal CSS v4. :root sets --brand to #33aa44, --text to #373a3c, --text-muted to #999, --border to #eee and --bg-light to #f3f3f3. body then sets color to var(--text) but sets background-color to #fff, a literal, so a dark --text on an unchanged body still sits on white.
The agent adds a dark set of the same variables and points the hard-coded backgrounds at them, instead of copying the thousand-line sheet. The header comment in conduit-theme.css lists the classes the templates use: container, navbar, btn-primary, form-control, article-preview, tag-pill, banner, and the page hooks home-page, auth-page, settings-page, editor-page, profile-page and article-page. Those hooks are the contract. New selectors that the Svelte files do not use are wasted. The toggle is a control in src/routes/Nav.svelte, which already switches Home, New Post, Settings and the profile link on page.data.user. The preference has to be known on the server render, or the light background flashes. In SvelteKit that is a cookie read from src/routes/+layout.svelte (or a small hook) and written onto the html element in app.html, with prefers-color-scheme as the value when the cookie is absent.
The routes to photograph are the ones on disk: / (src/routes/+page.svelte), /login, /register, /settings, /editor, /editor/[slug], /article/[slug], /profile and /profile/@[user] plus the favorites child. The dev server is vite dev. The sandbox browser opens each route twice, light and dark, at the width the theme's --content-breakpoint of 1080px implies for a desktop capture, and once narrower so the navbar does not hide the toggle. Contrast is checked for --text on the page background, --text-muted (today #999, which is the likely failure on a dark page) and --brand #33aa44 on both a light and a dark button. There is no test command to hide behind, so the screenshots and prettier --check are the checks the pull request can show.
A teammate watching the stream can say the muted grey failed, or that the toggle should live on the settings page as well as the navbar. The follow-up names the variable. The agent changes --text-muted in the dark set, recaptures article and settings, and only then opens the pull request. The pull request lists every literal background it moved onto a variable, so a reviewer can see that body is no longer #fff.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "codex",
"input": "Add dark mode that follows prefers-color-scheme and a toggle that remembers the choice. The theme is static/conduit-theme.css, linked from src/app.html. It already has light variables on :root, and body sets background-color to #fff. Add a dark set of the same variables, move hard-coded backgrounds onto them, and do not duplicate the class rules. Remember the choice in a cookie so the server render matches, via src/routes/+layout.svelte and the html element in app.html. Put the toggle in src/routes/Nav.svelte. Screenshot /, /login, /register, /settings, /editor, /article and /profile in both themes, check contrast for --text, --text-muted and --brand, and post the screenshots. Apply follow-ups, then open a pull request. Run prettier --check. There is no test script; do not invent one.",
"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 that edits static/conduit-theme.css, src/app.html, src/routes/+layout.svelte and src/routes/Nav.svelte. The description shows the dark values next to the light ones, calls out body moving off the literal #fff, and includes both themes of the home feed, the auth pages, settings, the editor, an article and a profile. Session artifacts hold the image files, each with a URL that works for an hour without the API key. Reading the session again issues a fresh URL.
The reviewer checks three things the screenshots make obvious: muted metadata still readable, the green brand still distinct from the dark page, and no flash of the white background on a reload with the cookie set. They also read the variable diff rather than a rewritten stylesheet. prettier --check is the lint this repository has, and its output is in the transcript.
Steering happens before that pull request exists. GET the event stream to watch the browser steps. POST a follow-up to /o/{org}/sessions/{id}/messages after the turn leaves running. A POST during the turn is 409 TURN_ACTIVE, and the console keeps a follow-up sent then until the turn ends and the parked sandbox wakes. Parked sandboxes stay for 7 idle days.
Run it on every theme request
Send this request when someone asks for a theme change on the SvelteKit app. One sandbox holds the branch, the dev server and the browser, and the org can read the run. The starter, or an org admin, sends the correction. Taking the browser directly is a five-minute lease held by one person.
When the turn finishes, the key's webhook receives run.completed or run.failed with session_url and events_url. result on that payload is the final answer, up to 16 KiB; the session read returns the rest. Several apps can be themed at once until the key hits max_concurrent, which defaults to 4 and then answers 429.
The use case this job follows, with its automation and trigger: Steer a run as a team.
Why run it on Rush?
The bug in a dark theme is a literal colour the variable pass missed, and you only see it on a rendered article. Doing that on a laptop means a long-lived dev server and a screen share for every correction. Here the agent runs vite dev in the sandbox, captures the routes, and stays parked between comments so a designer can answer hours later without a new branch.
The merge is still a person's. The pull request shows the variable table and the pictures. The transcript shows the prettier run and each follow-up that changed --text-muted or the cookie. No other run shares that checkout.
Frequently asked questions
Why a cookie instead of localStorage?
src/app.html is rendered on the server, and the theme sheet paints body immediately. A value that exists only in localStorage is applied after hydration, which flashes the light background. A cookie is available while +layout.svelte renders, so the html element has the theme on the first response. The toggle writes the same cookie.
There are no tests. What does the agent run?
prettier --check, which is the lint script, and the browser captures. The prompt tells it not to add a test runner. If you want a Playwright script later, say so in a follow-up. Until then the screenshots of both themes are the evidence in the pull request.
Will it rewrite the whole theme file?
It should not. The light variables stay, a dark set is added, and literals such as the body background move onto variables. The class names in the file's header comment are the ones the routes use. A pull request that reformats the entire sheet is something you send back.
Who can tell it to change a colour mid-run?
The person who started the run, or an org admin. Other org members can read the transcript and the screenshots. A follow-up waits until the current turn has finished. The sandbox still has the edited CSS when it wakes.