kane-cli testrun run --remote sends a suite of _test.md files to HyperExecute instead of running it on your machine. The grid sets up the runtime, runs every test in the suite (each one is a member), and streams the job back to your terminal. You get one job, one exit code, one sealed evidence pack, and the same recordings and evidence as a run on your own machine.
Remote runs cover every kind of test:
- Web suites run in Chrome on a HyperExecute macOS runner. Your machine or CI runner needs no Chrome, the run is always headless, and
--parallel Nspreads the members across N grid runners. - Mobile suites (
target: emulatorortarget: simulator) run on a virtual Android emulator or iOS simulator on a HyperExecute macOS host, so you can author and run mobile tests from any machine: Linux, Windows, Intel Macs, or a Mac without Xcode or Android Studio. The macOS Apple Silicon requirement applies only to emulator and simulator runs on your own machine. - Real-device suites (
target: androidortarget: ios) run on real devices in the cloud, driven from a HyperExecute Linux runner. See Real-Device Suites on the Grid.
--remote is different from --ws-endpoint and --cdp-endpoint. Those flags connect a remote browser to a run that still executes on your machine (kane-cli run, kane-cli testmd run). --remote moves the whole suite to the grid. Kane CLI itself runs there, and your machine needs only Node and the plugin.Prerequisites
The run uploads to the project and folder configured on your profile (
kane-cli config project and kane-cli config folder). Kane CLI passes them to the login on the grid.
How a remote run works
- Preflight, then remote preflight. Kane CLI builds the normal
testrunplan (one organisation, one project, see Preflight). It then checks that the selection fits in one grid job (see What one job can hold) and, for mobile, looks up the device in the grid catalog. If anything is wrong, the run stops here with exit2and nothing is dispatched. - Payload. Kane CLI zips the current directory, respecting
.gitignore, and uploads it with a generated job definition. Dispatching leaves.hyperexecute/,hyperexecute-cli.log, and.updatedhyperexecute.yamlin that directory. They are not inputs, so add them to.gitignore. - On the grid (a macOS runner, or a Linux runner for real-device suites), a setup step installs Kane CLI and logs in with your credentials and project. For mobile, it also installs the device tooling and boots the device. Then each member runs as its own
kane-cli testmd run, headless, exactly as it would on your machine. A member with recordings replays them. A member without recordings is authored on the grid. - Back to you. The job streams its progress and the dashboard link to your terminal. When it ends, the members’
output-<stem>/recordings and the sealed evidence pack are downloaded into your project, and the pack is published to Test Manager. The suite summary and exit code match a localtestrun.
Dispatching a run
--remote takes the normal testrun selection (paths, --match, --tags).
--dry-run runs both preflights and resolves any device without creating a job. It costs nothing, so use it before every new selection.
A real run prints the job id and dashboard link, then follows the job until it completes:
Web suites on the grid
A web suite needs nothing beyond the prerequisites. The grid runner has Chrome, and Kane CLI finds it and runs each member headless. Use the grid when your runner cannot have Chrome, when you want the suite off your laptop, or when you need more parallel capacity than one machine offers.testrun summary, plus two extra lines for the dispatch and the job link. A member that is authored on the grid returns its output-<stem>/ recordings, so the next run, on the grid or on your machine, replays them. Commit those recordings as you would after a local run.
Web tests and device tests cannot share a job (mobile_remote_mixed). Run them as two separate suites.
Choosing a grid device (emulator and simulator)
Remote devices come from the grid catalog, not from the AVDs or simulators on your machine. To see what the grid can provide:
Kane CLI resolves each test’s device on your machine. It picks the device name and the OS version separately, each in this order:
--device-name/--os-version- The test file’s
device_name:/os_version: - Your saved device (
kane-cli config set-device-name/set-os-version), when it is the same kind (emulator or simulator) and the grid has it. A saved device the grid does not have is skipped with asaved_device_unavailablenote. - The default: Pixel 8 Pro · Android 15 for emulators, iPhone 17 Pro Max · iOS 26.0 for simulators.
- Emulator: the job uses one device for all its members, so they must all ask for the same Android version. If they differ, the preflight refuses with
mobile_os_version_split. To force one version, pass--os-version. If a member names an AVD from your own machine, Kane CLI ignores it and shows adevice_name_ignorednote, because a remote job’s device name comes from the catalog. - Simulator: each task boots a simulator inside its own VM, so each member uses its own
device_name:andos_version:, checked against the catalog. If you pass--device-nameand--os-version, they apply to every member. Members can ask for different iOS versions as long as their major versions belong to the same HyperExecute pool. The catalog decides the pools: iOS 17 and 18 share one, and iOS 26 is in another. If members need different pools, the preflight refuses withmobile_pool_split.
Real-device suites on the grid
target: android and target: ios tests run on real devices in the cloud. The job runs on a HyperExecute Linux runner, and each member opens its own device session, so:
--parallel Nruns N members at once, up to the real devices your plan allows. A session beyond that queues for up to 15 minutes (see Plan Requirements).- Android and iOS real-device members can share one job.
- A job cannot mix real-device members with web, emulator, or simulator members (
mobile_remote_mixed).
--device-name/--os-version- The test file’s
device_name:/os_version: - The hub picks any free device. The hub is the service that assigns real devices to sessions.
Devices: block:
real_device_list_unavailable note, and the hub decides which device each member gets.
Before you dispatch a real-device suite, check these rules:
- Every member needs an
app:in its file:.apkor.aabfor Android,.ipafor iOS, or anAPP…id. Without one, the run stops withmobile_app_required.testrunhas no--appflag. --device-slugis refused for real devices.- Adaptive heal is off on real devices, so a failed replay step fails the test.
The app under test on the grid
The grid machine has to get the app from somewhere. A build is never part of the payload. It reaches the grid by id:
Each member gets its own id, so members in one run can use different builds. An
.ipa is refused for emulator and simulator tests, because it is a device build. Use it with target: ios. Every upload is reported, as app: <file> → APP… (uploaded) in the terminal or as the remote_app event for agents.
kane-cli apps list --target emulator|simulator|android|ios shows the uploaded builds your account can use. Put a value from the APP ID column in app:. There is no separate upload command: any run with a local build, on the grid or on your machine, uploads it and prints the APP… id. Uploads belong to an organisation, so apps list for your current profile is the definitive list of ids a run can use.
What one job can hold
Each remote run is one HyperExecute job, and a job provides one kind of runtime. The remote preflight refuses a selection that needs more than one, and tells you how to split it with--match or --tags:
Each reason comes with the paths that caused it, both in the terminal and in a
remote_error event for agents.
What comes back
- Recordings: the
output-<stem>/directories of authored members land in your project exactly as a run on your machine would leave them, so the next run replays from cache. - Evidence: one sealed pack for the suite in
.testmuai/evidence/, published to your project’s execution history in Test Manager. - Job logs: the per-member session logs under
~/.testmuai/kaneai/sessions/remote/<job-id>/, and the full stage logs on the HyperExecute dashboard at the printed job link. - Exit code: the same as a local
testrun.0all passed,1a member failed or broke,2preflight, auth or usage (nothing dispatched),3cancelled.
When a remote run fails
- A member failed or broke (exit
1): read it like any other failure.output-<stem>/Result.mdnames the failing step and reason, and the evidence pack has the screenshots and logs. See Debugging from a Pack. - A member is
brokenwith no steps and nothing was published: Kane CLI on the grid refused to start. Open the job link and read the scenario stage log. For mobile, the usual cause is anAPP…id that belongs to a different organisation than the account running the job. - Nothing was dispatched (exit
2): the printed reason is one of the preflight codes above. Runkane-cli plugin doctor remote-executionto see whether the plugin, binary, or login is missing.
In CI
A remote run needs no Chrome, Xcode, or Android Studio on the CI runner, only Node and the plugin:.testmuai/evidence/*.evidence as the build artifact. More pipeline shapes are in CI/CD.
For agents: NDJSON events
In agent or non-TTY mode, a remote run wraps the normaltestrun_* stream in additional typed events (see For agents):
testrun_summary also carries a remote object (backend, jobId, jobUrl, sessionsPath).
When you parse the stream of a dispatched run, keep reading after testrun_done until remote_done and the process exit, and keep the remote status and the session-log path. A preflight refusal or a dry run can end without remote_done.
Known limitations
--bug-detectionis not forwarded. Remote dispatch does not pass--bug-detectionto the member commands, so do not rely on it for bug detection in a remote run.--on-failureis not applied. Remote dispatch does not map--on-failureinto the job template, so do not rely on it for fail-fast behavior in a remote run.--namenames the suite only. It is suite metadata and is not passed to member commands.
Next Steps
- Batch Runs (testrun) for selection, preflight, flags and exit codes
- Mobile Testing for setup on your own machine, or skip it with
--remote - Real Devices for real Android and iOS devices, plans, live view and limits
- Writing test.md files for
target:,app:,device_name:andos_version: - Evidence Packs for what comes back and how to view it
- CI/CD for pipeline patterns, including runners with no Chrome