> ## Documentation Index
> Fetch the complete documentation index at: https://visorai.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Platforms and runtime

> See which platforms visor supports, how runtime resolution works, and which environment variables affect execution.

## Supported platforms

visor supports two mobile platforms:

| Platform | Driver stack               |
| -------- | -------------------------- |
| Android  | Appium with `UiAutomator2` |
| iOS      | Appium with `XCUITest`     |

visor is mobile-only today. Web support is not implemented.

## Runtime

visor connects to an Appium server and interacts with an actual simulator, emulator, or device.

Runtime execution requires:

* a running Visor daemon from `visor start`
* a booted iOS or Android target
* installed Node runtime dependencies, including Appium and WebdriverIO
* a valid app identifier or environment-based fallback

Platform note:

* Android `app-id` maps to `appPackage`
* iOS `app-id` maps to `bundleId` and must match an app already installed on the selected simulator or device
* the Android package name and iOS bundle identifier can differ for the same product

## Device selection

visor requires a running device target for runtime commands. Pass `--device` when you know the target identifier:

```bash theme={null}
visor run checkout-smoke.json --device emulator-5554 --app-id com.example.app
```

If you omit `--device`, visor detects running Android devices and booted iOS simulators:

* Android devices come from `adb devices` entries in the `device` state
* iOS simulators come from `xcrun simctl list devices booted`

When exactly one target is detected, visor uses it automatically. When multiple targets are detected in an interactive terminal, visor prompts you to choose one. In a non-interactive shell, visor returns a failure envelope and asks you to rerun with `--device`.

The runtime platform is inferred from the selected device. The CLI does not accept `--platform`.

## Default runtime values

When you do not set an explicit runtime value, visor resolves defaults for non-device settings.

| Setting                           | Default value           |
| --------------------------------- | ----------------------- |
| Appium server URL                 | `http://127.0.0.1:4723` |
| Android app id fallback           | `com.example.app`       |
| iOS bundle id fallback            | `com.example.app`       |
| Android default activity fallback | `.MainActivity`         |

## Environment variables

visor reads these runtime settings from environment variables when explicit runtime input is not provided.

| Environment variable                     | Purpose                                                   |
| ---------------------------------------- | --------------------------------------------------------- |
| `VISOR_ANDROID_APP_PACKAGE`              | Android app package name                                  |
| `VISOR_ANDROID_APP_ACTIVITY`             | Android launch activity                                   |
| `VISOR_IOS_BUNDLE_ID`                    | iOS bundle identifier                                     |
| `VISOR_ATTACH_TO_RUNNING`                | Reuse running app process (`true`/`1`/`yes`/`on`)         |
| `VISOR_APPIUM_CMD`                       | Command `visor start` uses when it needs to launch Appium |
| `VISOR_WEBDRIVER_CONNECTION_TIMEOUT_MS`  | WebDriverIO request timeout for Appium calls              |
| `VISOR_WEBDRIVER_CONNECTION_RETRY_COUNT` | WebDriverIO retry count for Appium calls                  |
| `VISOR_APP_MAP_DIR`                      | Host directory for persisted app maps                     |
| `VISOR_NO_MAP`                           | Disable app-map reads and writes (`true`/`1`/`yes`/`on`)  |
| `VISOR_DISABLE_MAP`                      | Alias for `VISOR_NO_MAP`                                  |

Legacy `PATF_*` fallbacks are only supported for the mobile runtime variables implemented in the adapter layer:

* `PATF_ANDROID_APP_PACKAGE`
* `PATF_ANDROID_APP_ACTIVITY`
* `PATF_IOS_BUNDLE_ID`
* `PATF_ATTACH_TO_RUNNING`

There is no `PATF_*` fallback for Appium command resolution.

## Runtime resolution order

For scenario runs and benchmarks, visor resolves runtime settings in this order:

1. explicit runtime input
2. detected running device target, when `--device` is omitted
3. scenario-level defaults where applicable
4. environment variables
5. built-in defaults

The main resolved values are:

* platform
* device
* timeout
* artifact output directory
* server URL
* app identifier

## App-map state

Mapped execution stores local host state under `.visor/maps` by default. The map identity is scoped by platform and app id, so observations from different flows in the same app accumulate into one shared map while Android and iOS maps remain separate.

The persistent map stores schema version, screen variants, source-derived labels, normalized fingerprints, navigation edges, destination contracts, confidence, and stale-path evidence. It does not embed screenshots.

Use `VISOR_APP_MAP_DIR` to move map state, or pass `--no-map` / set `VISOR_NO_MAP=true` to disable both reading and writing the map for a run.

## Attach mode

When you pass `--attach` (or set `VISOR_ATTACH_TO_RUNNING=true`), visor asks Appium to reuse the already running app process instead of launching from scratch.

* Android capabilities used: `noReset=true`, `fullReset=false`, `autoLaunch=false`, `dontStopAppOnReset=true`
* iOS capabilities used: `noReset=true`, `fullReset=false`, `autoLaunch=false`, `shouldTerminateApp=false`, `forceAppLaunch=false`

## Runtime lifecycle and connectivity preflight

For scenario execution and direct action commands, start the Visor daemon first:

```bash theme={null}
visor start
```

`visor start` ensures Appium is reachable and starts a local daemon that keeps WebDriver sessions warm for subsequent commands. Runtime commands fail early if the daemon is not running.

If another Appium process is already listening on the selected `server-url`, `visor start` fails instead of reusing it. Stop the existing Appium process or choose a different `--server-url` so Visor owns the Appium lifecycle.

Manage lifecycle with:

* `visor start`
* `visor status`
* `visor stop`

## Current limitations

The runtime layer currently has these important limits:

* no web runtime
* no desktop runtime
* no built-in device provisioning
* no multi-app orchestration within a single run
* no assertion engine beyond visibility checks
