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 sessionThe 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 warnKeep 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?
| Command | Supported behavior |
|---|---|
| Create and quit the Appium session | Attach and detach only; never allocate or stop a Revyl device. |
| Find elements by accessibility ID | Exact Android content-desc or iOS AXUniqueId. |
| Find elements by native ID or class | Exact full Android resource-id; native Android class or raw iOS type such as TextField. |
| Find within an element | Search descendants only, excluding the parent itself. |
| Read text, enabled state, or rectangle | Read from the current native hierarchy. |
| Read native attributes | Raw allowlisted platform attributes as strings, or null when an allowed attribute is absent. |
| Click | Tap the center after rechecking the hierarchy. |
| Send text | Tap a recognized native editable field and type without clearing; no special keys or clear command. |
| Screenshot | Return a PNG through WebDriver. |
| Activate an installed app | Native Appium activate-app endpoint with bundle/package ID, without launch options. |
| Read or select context | NATIVE_APP only; selecting it does not change the device. |
| Native gestures | Explicit 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.