What is VRT?
Grantiva VRT (Visual Regression Testing) catches unintended UI changes before they ship. You define the screens you care about in a YAML config file, and the CLI-driven capture engine screenshots each one on every pull request. If anything changes, the diff shows up in the dashboard and as a GitHub Check Run on the PR. VRT is not Xcode UI testing. You do not writeXCTestCase classes or use Xcode Instruments. The CLI drives your app with its own runner, grantiva-runner, embedded in the binary. Your existing Xcode UI tests are unaffected.
The baseline/capture/compare lifecycle
Every VRT workflow follows three phases:1. Capture
The CLI builds your app, boots a simulator, and navigates through each screen defined ingrantiva.yml. Screenshots are written to .grantiva/captures/.
grantiva diff capture is entirely local and needs no account. grantiva ci run is the command that captures, compares, and uploads in one pass.
2. Compare
Each new screenshot is diffed against the stored baseline using two metrics:
A screen fails if either threshold is exceeded.
3. Approve or reject
Approve expected changes to update the baseline. Reject unexpected ones to block the PR.How the CLI driver works
Grantiva ships a pre-built runner binary (grantiva-runner) inside the CLI, extracted on first use or by grantiva runner install. The runner drives the app through GrantivaAgent, a WebDriverAgent embedded alongside it, over local HTTP. There is no Appium server to run, no Maestro install, and no Accessibility permission to grant.
For each screen, the CLI:
- Boots the simulator and installs your app
- Starts a GrantivaAgent session
- Executes the taps, swipes, waits, and assertions in the screen’s
path - Captures the screenshot at the end of the path
launchApp, rather than the CLI pre-launching it — a CLI-side launch would create a process the agent cannot control, breaking stopApp and the other lifecycle steps.
This is why a physical device is not required for VRT — everything runs inside the iOS simulator. You do not need App Attest or any SDK integration for VRT to work.
Local vs CI usage
Local development:grantiva diff approve promotes the current captures to baselines; pass screen names to approve selectively.
CI (GitHub Actions, and any other macOS runner):
grantiva ci run runs build, capture, compare, and upload in sequence, and posts a GitHub Check Run on the pull request when the GitHub App is configured. It exits 0 when every screen passes and 1 when any fails — the results are uploaded either way.
Authentication:
- Local:
grantiva auth loginopens your browser. Credentials are saved to~/.grantiva/auth.jsonwith mode0600. - CI: set
GRANTIVA_API_KEYfrom your CI secrets. The environment variable takes precedence over the saved file, so nothing needs writing to disk on a runner.
grantiva diff capture and grantiva diff compare against local baselines need no account at all. Authentication buys you cloud baselines, uploaded runs, and the review loop.
How results appear in the dashboard
Eachgrantiva ci run creates a VRT Run in your dashboard with:
- Total / Passed / Failed / New screen counts (clickable to filter the screenshot grid)
- Per-screen status:
passed,failed,new_screen, orpending - Side-by-side baseline vs current diff view for failed screens
- Approve/reject controls
Reviewing a run
Every review action in the dashboard has a CLI equivalent, so a pipeline can close the loop it opened:--accept-all. grantiva console vrt reject closes the run without touching any baseline.
See VRT review for the full command set.
Configuration reference
grantiva.yml controls everything:
Next steps
- VRT quick start — get running in under 10 minutes
- Commands — the full reference, including
grantiva diff,grantiva ci run, andgrantiva doctor - CI integration — GitHub Actions, pre-built binaries, and parallel runs
- VRT review — accept, flag, and approve runs from the terminal