Revyl Documentation

Runtime / Mobile / Device infrastructure

Appium

The Revyl driver connects a supported native Appium subset to existing device sessions.

The Revyl Appium driver is a thin extension loaded by your own Appium server. It maps a limited set of native WebDriver commands to Revyl's existing device APIs. Your test keeps using an Appium client; it does not need to become a Revyl test or call an AI agent.

This is a source-installed driver, not a hosted Appium service. It supports the native commands listed below and is not a drop-in replacement for UiAutomator2 or XCUITest.

For the supported device lifecycle, use the device quickstart. A viewer URL is still a live stream, not a WebDriver endpoint.

How it connects

Your Appium test client
          |
Local Appium server + Revyl driver
          |
Authenticated Revyl device API
          |
Existing Android emulator / iOS simulator session

The driver uses the backend's session lookup and authenticated device proxy. It does not expose worker addresses or require ADB, WebDriverAgent, or local Xcode. Access is checked by the backend for the session and each proxied operation. Only one controller should operate a session at a time.

Install and connect

Get the standalone Appium driver and follow its README for setup and a runnable Python sample. Use Node 24+ and npm 10 or newer; install before loading runtime credentials:

git clone https://github.com/RevylAI/appium-revyl-driver.git
cd appium-revyl-driver
npm ci --ignore-scripts
npx --no-install appium driver install --source=local "$PWD"

There is no published revyl Appium driver on npm yet; use the source install above rather than appium driver install revyl.

Start or select a running Revyl session with your app already installed and launched. Creating a session uses your organization's cloud resources. Keep the session ID returned by the quickstart.

Provide REVYL_API_KEY to the Appium server through your secret manager or CI environment, then run:

npx --no-install appium --address 127.0.0.1 --port 4723 --log-level warn

Keep the server on loopback: exposing it would grant callers access through your server credential. Do not put API keys in capabilities or enable debug logging around sensitive test inputs.

Point your existing Appium client at http://127.0.0.1:4723 and use these capabilities instead of its standard native-driver capabilities:

{
  "platformName": "Android",
  "appium:automationName": "Revyl",
  "appium:revylSessionId": "YOUR_RUNNING_REVYL_SESSION_UUID",
  "appium:noReset": true
}

Use "iOS" for an iOS session. A session ID is not an ADB serial or simulator UDID. Capabilities that request installation, reset, browser automation, or another driver's behavior are rejected.

Which existing test commands work?

CommandSupported behavior
Create and quit the Appium sessionAttach and detach only; never allocate or stop a Revyl device.
Find elements by accessibility IDExact Android content-desc or iOS AXUniqueId.
Find elements by native ID or classExact full Android resource-id; native Android class or raw iOS type such as TextField.
Find within an elementSearch descendants only, excluding the parent itself.
Read text, enabled state, or rectangleRead from the current native hierarchy.
Read native attributesRaw allowlisted platform attributes as strings, or null when an allowed attribute is absent.
ClickTap the center after rechecking the hierarchy.
Send textTap a recognized native editable field and type without clearing; no special keys or clear command.
ScreenshotReturn a PNG through WebDriver.
Activate an installed appNative Appium activate-app endpoint with bundle/package ID, without launch options.
Read or select contextNATIVE_APP only; selecting it does not change the device.
Native gesturesExplicit revyl:tap, revyl:doubleTap, revyl:longPress, and directional revyl:swipe commands.

Screenshots must be non-interlaced PNGs of at most 16 megapixels. Backend responses are bounded to 16 MiB.

XPath, iOS predicates/class chains, visibility assertions, page source, browser/WebView contexts, W3C actions, mobile: scripts, and arbitrary execute scripts are not supported. A suite using these needs adaptation or its existing execution environment.

Find an element again after every tap, text input, app launch, or hierarchy change. The native API does not expose stable element handles, so the driver deliberately raises stale-element errors instead of reusing old coordinates. Dynamic screens may need test changes. The hierarchy check and coordinate action are not atomic; avoid destructive flows and concurrent controllers. Handles are never re-resolved by selector. Identical-looking replacement nodes or changes that occur and revert between observations cannot be detected.

The Python smoke example uses accessibility-ID lookups, text input, a tap, an exact text assertion, and a private screenshot. Adapt its fixture-app locators to your app. In WebdriverIO, use addValue to avoid the unsupported clear command that setValue may invoke first. Native input taps the field before typing without clearing it, which can move the caret or change the selection. Appending at the end is not guaranteed; use an initially empty field for the smoke example.

Clear, install, and reset remain unsupported. A coordinate-based clear cannot verify that the same editable target became empty, and restarting an app is not a data reset. The driver rejects these operations rather than approximating them. The current text-input path may include typed text in action reports; use non-sensitive test data, not credentials.

Native gestures

Each execute command takes exactly one options object. These are Revyl contracts, not UiAutomator2 or XCUITest mobile: commands:

driver.execute_script("revyl:tap", {"x": 100, "y": 200})
driver.execute_script("revyl:doubleTap", {"x": 100, "y": 200})
driver.execute_script("revyl:longPress", {"x": 100, "y": 200, "durationMs": 1500})
driver.execute_script("revyl:swipe", {"x": 100, "y": 200, "direction": "up", "durationMs": 500})

Coordinates must be integers inside the current native screen: Android pixels and iOS points, not iOS screenshot pixels. Long press accepts 1–10000 ms and defaults to 1500 ms. Swipe accepts the same duration range, defaults to 500 ms, and moves one quarter of the screen dimension in the requested direction, clamped at the edge. Explicit endpoints, custom distances, pinch, and drag are unsupported. Double-tap uses the worker's native two-tap gesture without a configurable interval. Unknown options are rejected.

Evidence and cleanup

Inspect the test's actual assertions and screenshots before claiming a pass. Native actions use the existing Revyl action-report path with Appium agent attribution. A screenshot or a successful HTTP request alone does not prove your test passed. A timed-out action may already have executed; the driver does not retry it. Worker/device providers can still retry internally, so this is not an end-to-end at-most-once guarantee.

Always quit the Appium session in your test's cleanup. Then the job that owns the cloud allocation must separately release it:

revyl device stop --session-id "$REVYL_SESSION_ID"

Stop only the session your job owns. Quitting the driver intentionally leaves an externally owned Revyl session running.

Standard drivers and broader compatibility

This subset does not provide standard UiAutomator2 connectivity over ADB or XCUITest's WebDriverAgent and host-side operations. Those remain separate integration requirements for broader compatibility. It also does not enable Maestro.

On this page