Supported platforms
Visor supports two mobile platforms:
Visor is mobile-only today. Web support is not implemented.
Requirements
- Node.js 20.19+, 22.12+, or 24+, and npm 10+
- a booted simulator, emulator, or connected device
- the target app installed on that device
- the current Appium 3 driver for your platform
uiautomator2 for Android or xcuitest for iOS:
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 3 and WebdriverIO
- a valid app identifier or environment-based fallback
- Android
app-idmaps toappPackage - iOS
app-idmaps tobundleIdand 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:
--device, Visor detects running Android devices and booted iOS simulators:
- Android devices come from
adb devicesentries in thedevicestate - iOS simulators come from
xcrun simctl list devices booted
--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.Environment variables
Visor reads these runtime settings from environment variables when explicit runtime input is not provided.Runtime resolution order
For scenario runs and benchmarks, Visor resolves runtime settings in this order:- explicit runtime input
- detected running device target, when
--deviceis omitted - scenario-level defaults where applicable
- environment variables
- built-in defaults
- 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.
Visor writes two storage layers:
- a private runtime index with screen variants, source-derived elements, fingerprints, navigation edges, destination contracts, confidence, and stale-path evidence;
- compact agent memory under
.visor/maps/agent/with semantic screens, meaningful safe actions, executable recognizers, routes, reliability, and unresolved gaps.
data.map.agent_path, not the runtime path returned as data.map.path. Neither layer embeds screenshots. Keep the entire .visor/ directory local and ignored.
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: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 startvisor statusvisor 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