GitHub PR Previews
The SootBean GitHub App attaches a playable preview to each pull request and keeps live branch builds available for inspection. A PR-diff-driven agent boots your app in headless SootSim, drives the surface your change touched, and posts a single sticky comment with the recording.
Your repo does not need a provider API key or SOOTSIM_API_KEY. The workflow
authenticates with the GitHub installation token, and SootBean cloud owns the
agent, model proxy, upload, and PR comment.
PR previews and branch builds require the Carbon plan. The agent runs on SootBean’s cloud and model keys, so the automated preview/build flows are gated to Carbon. A pull request on a repo without an entitled account gets a sticky comment noting that previews require Carbon, and no preview is generated.
Set up a repo
Install the SootBean GitHub App on the
repo. On first install it opens a bootstrap PR that adds
.github/workflows/soot.yml tuned to your repo. Merge it and you are done.
To write the workflow by hand, add one job that checks out and calls
sootbean/soot-preview-action@v1:
The action installs your dependencies, boots the dev server in the background,
waits for it to be ready, drives the app, and reports back. On a
pull_request it runs the preview agent; on a push to a tracked branch it runs
the branch build.
Package manager
The action auto-detects your package manager from the lockfile or the
package.json packageManager field and installs with it (npm ci, yarn install --immutable/--frozen-lockfile, pnpm install --frozen-lockfile, or
bun install --frozen-lockfile). Override with package-manager: or a custom
install: command for a monorepo.
If your workflow already runs its own setup (checkout, Node, install, e.g. a
repo ./.github/actions/setup composite), run it before this action and pass
package-manager: none so the action skips straight to the preview:
Inputs
| input | default | description |
|---|---|---|
start | empty | command that boots your dev server in the background |
port | 8081 | dev server port (Metro/Expo default) |
package-manager | auto | auto | npm | yarn | pnpm | bun | none |
install | empty | override the install command (monorepo filters, etc.) |
node-version | 24 | Node version installed via actions/setup-node |
mode | auto | auto | preview | build |
maestro | empty | Maestro flow paths to run against the preview bundle, or auto for every .maestro/*.yaml |
runner | local | where the recording executes: local (your CI runner) or hosted (a SootBean GPU recorder) |
build-env | empty | newline KEY=VALUE pairs baked into the captured bundle (Clerk / API keys); source from ${{ secrets.* }} |
Full input list and behavior: the action’s README.
Where the recording runs
The runner input decides where SootSim and the recording execute. Your app’s
install and dev server always run on your own CI runner either way — the choice
is only about the machine that drives and records it.
runner: local runs everything on your workflow’s runner. Nothing leaves
your CI beyond the finished upload, and there is no extra plan requirement
beyond previews themselves. The trade-off is hardware: standard hosted CI
runners have two CPU cores and no GPU, so SootSim renders through software.
Short walkthroughs and quick flows are fine; longer recordings come out
choppy, and on complex apps the recording can slow the interaction itself.
runner: hosted keeps your CI runner serving the dev server and moves the
driving and recording to a SootBean GPU recorder. Your workflow opens a
one-off tunnel for the run, gated by a per-run token so only the assigned
recorder can reach your dev server, and tears it down as soon as the run
ends. The recorder renders with a real GPU, which is what makes the
walkthrough video watchably smooth, and heavier Maestro suites do not eat
your CI minutes. It requires the Carbon plan.
Rules of thumb: start with local; switch to hosted when the videos matter
(design review, sharing with non-engineers) or when your flows are long enough
that software rendering visibly degrades them. If your policy forbids exposing
a dev server through any tunnel, even token-gated and per-run, stay on
local — that constraint outranks video quality.
Preview vs build
SootSim publishes two share types from GitHub Actions:
| type | URL | behavior |
|---|---|---|
| PR preview | /preview/<id> | recorded replay of the changed surface, including bundle, events, storage, network replay data, snapshots, and video when recording succeeds |
| branch build | /build/<owner>/<repo>/<branch>?platform=ios | live configured app build that keeps talking to the endpoint your workflow configured |
Keep those modes separate. A recorded PR preview should replay what CI captured; it should not silently fall through to a live backend for missing requests. A branch build is the live inspection mode, so auth and API failures there usually mean the app’s build-time configuration needs work.
What the bot does
For each non-draft PR, the workflow:
- reads the PR diff;
- asks SootBean cloud whether the change has an app surface worth previewing (and whether the account is entitled);
- boots your app and opens it in headless SootSim;
- lets the agent drive the relevant surface and save a flow;
- replays the flow with recording enabled;
- uploads the bundle, events, storage, snapshots, network replay data, and video when present;
- updates one sticky PR comment with the preview result and branch build links.
For pushes to configured branches, the build lane uploads the live branch build without running the PR agent.
Verify a preview
A terminal preview or build failure must fail the GitHub workflow. Do not add
continue-on-error to the Soot action. A green check still is not visual proof:
it confirms the pipeline finished, but cannot confirm that the changed surface
rendered correctly.
Before treating a preview as ready:
- read the SootSim sticky comment and confirm it says ready, not failed or skipped;
- open the linked
/preview/<id>; - confirm the video loads when present;
- switch to Live and confirm the app catches up to the recorded point;
- scrub the timeline and confirm the live app follows without getting stuck;
- check that the frames show the changed surface, not just a login screen or the starting tab twice;
- open the branch build link separately when you need live staging data.
Skipped previews are valid for docs-only, CI-only, and backend-only changes. If the PR changed user-visible UI and the bot skipped it, adjust the app map or preview guidance instead of accepting the skip.
Troubleshooting
- “PR previews require a Carbon plan” in the sticky comment: the repo’s SootBean account is on Free. Subscribe to Carbon, then re-run the PR workflow.
- Preview skipped on a UI change: the relevance gate judged the diff had no
observable short-clip delta. Adjust your preview guidance, or open the
soot-agent-logsartifact on the Actions run to see the decision reason. - Boot never became ready: the action waits for
port(default8081). If your dev server binds a different port, setport:; if it needs env to boot, pass it viabuild-env. - Auth failed inside the build: the captured bundle needs a runtime key
whose allowed origins include
sootsim.com. Bake it in withbuild-envsourced from a repo secret. - Deeper diagnostics: every run uploads a
soot-agent-logsartifact (each probe’s stdout/stderr) to the Actions run page; download it for post-mortems.
Re-running previews
When you need to regenerate history, rerun the original pull request workflow run. That preserves the PR event shape the agent expects:
terminal
Do not use a push run when you need a PR preview; push runs only update branch
builds. Do not use workflow_dispatch unless your workflow was explicitly
written for it.
