CLI & MCP Server

Give your agent a real iOS simulator.

grantiva builds your app, boots a device, taps, types, swipes, screenshots, reads the accessibility tree, and diffs the result against an approved baseline. Every one of those is also an MCP tool, so an AI agent can do it too.

No Appium server. No Maestro install. No Accessibility permission to grant. Headless on CI.

Terminal
$ brew install grantiva/tap/grantiva
$ grantiva doctor
$ grantiva init

macOS 15+, Xcode 16+. MIT licensed. No Grantiva account required for local use.

One binary

The dependency list is empty.

Most iOS UI automation asks you to install a server, grant a permission, and hope CI agrees. This one is a Homebrew formula and an Xcode you already have.

No Appium server, no Maestro install

UI automation runs through GrantivaAgent — a WebDriverAgent shipped inside the CLI binary and extracted by grantiva runner install. Nothing separate to install, version, or keep alive. Your existing Maestro flow files still run; the tool that ran them does not.

No Accessibility permission

Nothing to approve in System Settings, nothing to re-approve after an OS update, and nothing that silently breaks a CI runner. It works the same on your Mac and on a fresh macOS-15 GitHub runner.

Free, and it works offline

Capture, compare, and approve baselines locally in .grantiva/baselines/ with no account at all. Sign in only for grantiva ci run — shared baselines across machines and results posted to your PRs.

Commands

Everything supports --json.

Which is the whole point. A command that only prints for humans is a command an agent has to guess at.

Build and run

grantiva build

Build the app for a simulator using xcodebuild.

grantiva build install

Build and install the app on a simulator, then optionally launch it. Use --no-launch to seed the data container first.

grantiva run

Run Maestro-compatible flows against a simulator. Reports step pass/fail and screenshots the failure.

grantiva ci run

The full pipeline: capture screenshots, compare against baselines, upload results.

Visual regression

grantiva diff capture

Navigate to every configured screen and capture screenshots.

grantiva diff compare

Diff current captures against baselines — pixel plus CIE76 perceptual color distance.

grantiva diff approve

Promote the current captures to baselines.

Agent-native

grantiva mcp

Start the MCP server for AI agent integration. Speaks MCP over stdio.

grantiva hierarchy

Dump the UI hierarchy of a booted simulator without relaunching the app. XML or JSON.

grantiva runner start

Start GrantivaAgent and keep it alive for interactive use.

grantiva record

Record a simulator and extract PNG frames at exact requested timestamps.

Simulators and setup

grantiva simulator ensure

Create or idempotently reuse an exact named simulator.

grantiva simulator teardown

Shut down every simulator owned by a ticket or session.

grantiva doctor

Check environment and dependencies.

grantiva init

Generate grantiva.yml in the current directory.

Model Context Protocol

18 tools. One grantiva mcp.

grantiva_a11y_tree and grantiva_a11y_check are the two that change what an agent can do. Every other UI tool is a way to act; these are the way to see. The tree is the same hierarchy VoiceOver walks — so an agent that lands on an unexpected screen can read what is actually in front of it and pick a different element, instead of retrying a label that was never there.

UI automation

Every UI-mutating tool returns the updated accessibility tree in its response — so the agent sees what changed after each tap without having to ask again.

grantiva_screenshot

Take a screenshot of the iOS simulator. Returns a base64-encoded PNG image.

grantiva_tap

Tap a UI element by accessibility label or by coordinates.

grantiva_swipe

Swipe on the simulator screen.

grantiva_type

Type text into the currently focused field.

grantiva_a11y_tree

Get the current accessibility tree — every element with its label, type, frame, and state, as JSON.

grantiva_a11y_check

Audit the current screen for missing labels on interactive elements and tap targets smaller than 44pt.

Build and test

grantiva_build

Build via xcodebuild. Returns success status, duration, warnings, and errors.

grantiva_run

Build, install, and launch the app on the simulator.

grantiva_test

Run the test suite via xcodebuild test. Returns pass/fail counts and output.

Simulators

grantiva_sim_list

List available simulators with name, UDID, state, runtime, and availability.

grantiva_sim_boot

Boot a simulator by name or UDID.

grantiva_sim_ensure

Create or idempotently reuse an exact named simulator, optionally booting it to readiness.

grantiva_sim_delete

Delete one simulator by its exact name or UDID.

Context and scripting

grantiva_context

Report the loaded grantiva.yml, the booted simulator, the Xcode version, and the runner session status. Call this first.

grantiva_script

Run a batch of UI actions in sequence — tap, tap_xy, swipe, type, wait — and return the final accessibility tree.

Visual regression

grantiva_vrt_capture

Capture screenshots for every configured screen.

grantiva_vrt_compare

Diff current captures against baselines. Returns pixel and perceptual metrics per screen.

grantiva_vrt_approve

Promote captures to baselines.

Two resources, with subscriptions

The server also publishes grantiva://hierarchy (the view hierarchy as JSON) and grantiva://screenshot (the current screen as a PNG). After a tap, swipe, type, or script call, the server emits a resource-updated notification for the hierarchy — a subscribed client refreshes its picture of the screen on its own.

Setup

Two minutes to a wired-up agent.

The server speaks MCP over stdio, so you normally never run it by hand — your MCP client launches it for you. It reads grantiva.yml from the working directory, which is how the build and VRT tools learn your scheme, simulator, and bundle ID.

Commit it for the whole team

A project-scoped .mcp.json at your repo root gives everyone the same tools.

UI tools need a live session

Run grantiva runner start --detach before the agent starts tapping. If no session is alive, the UI tools fail gracefully rather than taking the server down — the build, simulator, and context tools keep working.

Claude Desktop needs an absolute path

It does not inherit your shell PATH. which grantiva will tell you where Homebrew put the binary.

Claude Code
$ claude mcp add grantiva -- grantiva mcp
.mcp.json
{
  "mcpServers": {
    "grantiva": {
      "command": "grantiva",
      "args": ["mcp"]
    }
  }
}
claude_desktop_config.json
{
  "mcpServers": {
    "grantiva": {
      "command": "/usr/local/bin/grantiva",
      "args": ["mcp"],
      "cwd": "/Users/you/Developer/MyApp"
    }
  }
}
Visual Regression

Screenshot every screen. Diff it. Block the PR.

Describe your screens in grantiva.yml, and the CLI boots the simulator, builds, installs, navigates to each one, captures it, and compares against the approved baseline — pixel difference plus CIE76 perceptual color distance, so an anti-aliasing shift does not read as a regression.

Maestro flows work as-is

Existing .maestro flows are auto-detected and parsed — tapOn, inputText, assertVisible, swipe, runFlow, takeScreenshot. No rewrite.

GitHub Check Runs

grantiva ci run posts before/after diffs to the pull request as a Check Run.

Split build and test

--app-file consumes a pre-built .app or .ipa from a CI artifact, so the build job and the visual job can be separate.

Local baselines, no account

diff capture, diff compare, diff approve all work against .grantiva/baselines/ on your machine.

grantiva.yml
scheme: MyApp
simulator: iPhone 16
bundle_id: com.example.myapp

screens:
  - name: Home
    path: launch
  - name: Settings
    path:
      - tap: "Profile"
      - tap: "Settings"

diff:
  threshold: 0.02
  perceptual_threshold: 5.0

Install it now. Decide about the rest later.

The CLI is free and needs no account. When you want shared baselines, PR checks, attestation, or feature flags, the rest of the platform is already wired to the same project.

macOS 15+, Xcode 16+. Source on GitHub.