Remote runs on the cloud grid
kane-cli testrun run --remote dispatches a suite of _test.md files to TestMu AI HyperExecute instead of running it on your machine. The grid provisions the runtime, runs every member, and streams the job back to your terminal: one job, one exit code, one sealed evidence pack, and the same recordings and evidence you get from a run on your own machine.
Remote runs cover both kinds of test:
- Web suites run on Chrome on a HyperExecute macOS runner, with no Chrome on your machine or CI runner, headless by construction, 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 mobile runs on your own machine.
kane-cli plugin install remote-execution # once
kane-cli testrun run --tags smoke --remote --parallel 4 # a web suite on 4 grid runners
kane-cli testrun run tests/app/ --remote --device-name "Pixel 7" --os-version 14 # an Android suite
kane-cli testrun run tests/ios/ --remote --device-name "iPhone 15" --os-version 17.5
--remote is not the same as --ws-endpoint or --cdp-endpoint. Those attach 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 nothing but Node and the plugin is needed locally.
Prerequisites
| You need | Why | How to check |
|---|---|---|
| A TestMu AI plan that includes HyperExecute, with macOS runner concurrency (web and mobile members both run on macOS runners) | Every remote run is a HyperExecute job | Ask your account owner, or open the HyperExecute dashboard for your organisation |
The remote-execution plugin | It owns the HyperExecute binary kane-cli dispatches with | kane-cli plugin install remote-execution, then kane-cli plugin doctor remote-execution |
| A TestMu AI username and access key | HyperExecute authenticates with basic auth. An OAuth profile is exchanged for them automatically; otherwise pass --username and --access-key | kane-cli whoami |
| A project directory that contains the tests | The current directory is zipped and shipped as the job payload | Run from the repository root, or any parent of the tests |
| Recordings not gitignored | The payload respects .gitignore, and an ignored output-<stem>/ never reaches the grid. Builds are not payload, see The app under test on the grid | --dry-run reports gitignored_inputs; un-ignore with, for example, !output-*/ |
The project and folder the run uploads to are the ones configured on your profile (kane-cli config project and kane-cli config folder); they are passed to the grid's login.
How a remote run works
- Preflight, then remote preflight. The normal
testrunplan is built (one organisation, one project, see Preflight); then kane-cli checks the selection can be one grid job (What one job can hold) and, for mobile, resolves the device against the grid catalog. Anything wrong stops here, nothing is dispatched, exit2. - Payload. The current directory is zipped (respecting
.gitignore) and uploaded with a generated job definition. The dispatch leaves.hyperexecute/,hyperexecute-cli.logand.updatedhyperexecute.yamlin that directory: add them to.gitignore, they are not inputs. - On the grid (a macOS runner): a pre-step installs kane-cli and logs in with your credentials and project; for mobile it 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 authors on the grid. - Back to you. The job streams 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, the pack is published to Test Manager, and the suite summary and exit code are the same as a localtestrun.
Allow a few minutes on top of the tests' own time: in practice about 15 seconds of setup for a web job, and a minute or more for a mobile job (device boot, app install). A wall-clock timeout of 10 minutes is a safe starting point in CI.
Dispatching a run
--remote takes the normal testrun selection (paths, --match, --tags).
kane-cli testrun run --tags smoke --remote --dry-run # both preflights, nothing dispatched
kane-cli testrun run --tags smoke --remote --parallel 4
--dry-run runs both preflights and resolves any device without creating a job. Use it before every new selection; it costs nothing.
A real run prints the job id and dashboard link, then tracks the job until it completes:
job 24fc58b2-… dispatched → https://hyperexecute.lambdatest.com/hyperexecute/task?jobId=24fc58b2-…
| Flag | On the grid |
|---|---|
--parallel <n> | Becomes the job's concurrency: the members are auto-split across n grid runners, each running its share one member at a time. Device suites parallelize the same way, and every task has its own VM and device |
--headless | Not needed, every member runs headless on the grid |
--on-failure, --name, --bug-detection, --author, --no-adaptive-heal | Forwarded to the members on the grid |
--username, --access-key | Used for the grid login and the Test Manager upload |
Web suites on the grid
A web suite needs nothing beyond the prerequisites: the grid runner has Chrome, kane-cli finds it and runs each member headless. Use it when the runner cannot have Chrome, when you want the suite off your laptop, or when you want more parallelism than one machine gives you.
kane-cli plugin install remote-execution
kane-cli testrun run tests/web/ --remote --parallel 4 --on-failure fail-fast
What you see back is a normal testrun summary; the only extra lines are the dispatch and the job link. A member that authors on the grid comes back with 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.
A web selection cannot share a job with device members (mobile_remote_mixed). Run the two suites separately.
Choosing a grid device
Remote devices come from the grid catalog, not from the AVDs or simulators on your machine. List what the grid can provision:
kane-cli devices list --target emulator --remote # Android emulators
kane-cli devices list --target simulator --remote # iOS simulators
kane-cli devices list --target simulator --remote --os-version 17.5 # only that OS version
Each row is a device name plus the OS versions it ships with. Address one with both:
| Flag or key | Purpose |
|---|---|
--device-name "<name>" | The name exactly as the catalog prints it ("Pixel 7", "iPhone 15"). Validated before dispatch |
--os-version <v> | The OS version (14, 17.5). On its own, it means any catalog device running that version |
device_name: or os_version: in a _test.md | Per-test defaults, used when the flags are absent. See Mobile target |
If you pass neither, kane-cli picks a catalog default for the platform and prints it on the device line. Read it before relying on it.
The two platforms bind the device differently:
- Emulator: the job allocates one device for all its members, so they must agree on one Android version (
mobile_os_version_splitotherwise, or force one with--os-version). An AVD name from your own machine is ignored in a member (you get adevice_name_ignorednote), because a remote job's device is named by the catalog. - Simulator: each task boots a simulator inside its own VM, so each member binds its own
device_name:andos_version:(validated against the catalog).--device-nameand--os-version, when passed, apply to every member. Members may ask for different iOS versions as long as their iOS majors map to one HyperExecute pool, which the catalog decides (today 17 and 18 share one, 26 is another); otherwisemobile_pool_split.
The app under test on the grid
The grid machine has to obtain the app. A build never rides the payload, it reaches the grid by id:
app: in the test | What happens |
|---|---|
A local build, .apk for emulator or a .zip of the .app for simulator, anywhere on disk | Uploaded from your machine at preflight, once per distinct file (a per-machine cache skips a build your account already has), and handed to the grid as --app <id>. It may be gitignored or outside the project. --dry-run uploads nothing |
An uploaded APP… id | Used as is, and the grid downloads it |
Each member gets its own id, so a run may hold members that name different builds. A .ipa is refused up front: it is a device build, and the emulator and simulator upload does not take it. Every upload is reported (app: <file> → APP… (uploaded), or the remote_app event for agents).
kane-cli apps list --target emulator|simulator shows the uploaded builds your account can use, and the APP ID column is what app: takes. There is no upload subcommand: 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 the current profile is the authority on which ids a run can use.
What one job can hold
One remote run is one HyperExecute job, which allocates one kind of runtime. The remote preflight refuses a selection that needs more than one, and tells you how to split it (--match or --tags):
| Reason | Meaning | Fix |
|---|---|---|
mobile_remote_mixed | Web and device tests in one selection | Two runs: one for the device tests, one for the rest |
mobile_remote_mixed_platform | Emulator and simulator tests in one selection | Two runs, one per platform |
mobile_os_version_split | Emulator tests asking for different Android versions | One run per version, or --os-version to force one |
mobile_pool_split | Simulator tests whose iOS versions need different HyperExecute pools | One run per pool, or --os-version to force one |
mobile_remote_unsupported | A device target the grid cannot provide | Run it on your own machine, or deselect it |
mobile_app_missing | A device test names a local build that is not on this machine | Fix the path, or use an APP… id |
mobile_app_not_uploadable | The build is not one the cloud takes (a .ipa, or the wrong extension for the platform) | .apk for emulator, a .zip of the .app for simulator, or an APP… id |
mobile_app_upload_failed | Uploading the build from your machine failed | Fix the upload (network, auth), or use an APP… id |
member_outside_payload | A test lives outside the dispatched directory | Run from a directory that contains it |
gitignored_inputs | Required recordings are gitignored | Un-ignore them (for example !output-*/) or commit them |
on_grid | Already running on a HyperExecute grid | --remote cannot re-dispatch from inside a job |
Every reason arrives with the offending paths, both in the terminal and as a remote_error event for agents.
What comes back
- Recordings: authored members'
output-<stem>/directories 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 with a pack. - A member is
brokenwith no steps and nothing was published: the grid-side kane-cli refused before launching. 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, orkane-cli plugin doctor remote-executionshows what is missing (plugin, binary, login).
In CI
A remote run needs no Chrome, Xcode or Android Studio on the runner, only Node and the plugin:
npm install -g @testmuai/kane-cli
kane-cli plugin install remote-execution
# a web suite
kane-cli testrun run tests/web/ --remote --parallel 4 \
--username "$LT_USERNAME" --access-key "$LT_ACCESS_KEY" --on-failure fail-fast
# a mobile suite
kane-cli testrun run tests/app/ --remote \
--device-name "Pixel 7" --os-version 14 \
--username "$LT_USERNAME" --access-key "$LT_ACCESS_KEY" --on-failure fail-fast
Archive .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 adds typed events around the normal testrun_* stream (see For agents):
type | Payload | Notes |
|---|---|---|
remote_start | backend, env | Dispatch begins |
remote_device | platform, slug, name, os_version, avd_id?, pool? | The resolved grid device, mobile only. A web run has no device line |
remote_device_hint | reason, detail | device_name_ignored (emulator only, a local AVD name was dropped) or catalog_stale |
remote_app | path, app_id, source | One per distinct local build uploaded from your machine, mobile only. source is uploaded, cache (already uploaded by this machine) or dry-run (app_id empty, nothing sent) |
remote_dispatched | job_id, job_url | The HyperExecute job exists, and the link opens the dashboard |
remote_error | code, detail | Remote preflight refused the selection (codes above), followed by testrun_done and exit 2 |
remote_exec_sync, remote_coverage | status, reason, detail? | Informational: assurance graph sync and coverage, skipped when the project has no .context store |
remote_done | status, exit, job_id, sessions_path | Terminal for the remote wrapper, and follows testrun_done |
testrun_summary also carries a remote object (backend, jobId, jobUrl, sessionsPath).
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 - 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
