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:

name: Soot
on:
push:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
pull-requests: write
issues: write
jobs:
soot:
if: ${{ github.event.pull_request.draft != true }}
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- uses: sootbean/soot-preview-action@v1
with:
start: npm run dev # whatever boots your app dev server

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:

- uses: ./.github/actions/setup # your own composite
- uses: sootbean/soot-preview-action@v1
with:
package-manager: none
start: pnpm dev:all:lite

Inputs

inputdefaultdescription
startemptycommand that boots your dev server in the background
port8081dev server port (Metro/Expo default)
package-managerautoauto | npm | yarn | pnpm | bun | none
installemptyoverride the install command (monorepo filters, etc.)
node-version24Node version installed via actions/setup-node
modeautoauto | preview | build
maestroemptyMaestro flow paths to run against the preview bundle, or auto for every .maestro/*.yaml
runnerlocalwhere the recording executes: local (your CI runner) or hosted (a SootBean GPU recorder)
build-envemptynewline 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:

typeURLbehavior
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=ioslive 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:

  1. reads the PR diff;
  2. asks SootBean cloud whether the change has an app surface worth previewing (and whether the account is entitled);
  3. boots your app and opens it in headless SootSim;
  4. lets the agent drive the relevant surface and save a flow;
  5. replays the flow with recording enabled;
  6. uploads the bundle, events, storage, snapshots, network replay data, and video when present;
  7. 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-logs artifact on the Actions run to see the decision reason.
  • Boot never became ready: the action waits for port (default 8081). If your dev server binds a different port, set port:; if it needs env to boot, pass it via build-env.
  • Auth failed inside the build: the captured bundle needs a runtime key whose allowed origins include sootsim.com. Bake it in with build-env sourced from a repo secret.
  • Deeper diagnostics: every run uploads a soot-agent-logs artifact (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

gh run rerun <pull_request_run_id> -R owner/repo

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.

Ready to build?

Run your React Native app in the browser. No simulators, no native toolchain, no waiting.

curl -fsSL https://sootsim.com/install.sh | sh