By default every flow in an upload runs on one device, set by the --ios-device,
--ios-version, --android-device and --android-api-level flags on dcd cloud.
A device matrix runs your whole suite against several devices from a single dcd cloud
invocation. Every flow runs once per device, all under one upload with one console entry.
Pass --ios-device-matrix <device>:<version> (or --android-device-matrix <device>:<apiLevel>) once per device you want. Supported devices and operating systems are listed here.
dcd cloud --app-binary-id <id> ./flows \
--ios-device-matrix iphone-16-pro:18 \
--ios-device-matrix iphone-16-pro:26 \
--ios-device-matrix iphone-16-pro-max:26
# one upload, 3 devices x N flowsdcd cloud --app-binary-id <id> ./flows \
--android-device-matrix pixel-8:34 \
--android-device-matrix pixel-10:36Append :play to run a cell against a Google Play device. Google Play is available as pixel-8:34, pixel-10:36, pixel-10:37 and pixel-7:34 (see Google Play APIs):
dcd cloud --app-binary-id <id> ./flows \
--android-device-matrix pixel-8:34 \
--android-device-matrix pixel-8:34:playEvery --ios-device-matrix / --android-device-matrix names exactly one device. There is no
cross-product: the flags are not combined with each other, or with --ios-device / --ios-version.
# runs exactly these two, and nothing else
dcd cloud [...] --ios-device-matrix iphone-15:17 --ios-device-matrix iphone-16-plus:26This is deliberate as not every device supports every OS. Naming each device explicitly means you always get exactly what you asked for.
A matrix runs one test per (flow x device), so a 4-device matrix over 10 flows is 40 flows, not 10. Before submitting, the CLI prints the number of flows and what they will cost:
⏺ Device matrix
⎿ cells 4
est. cost $0.36
Pixel 8 · API 34 2 flows · $0.18
Pixel 10 · API 36 2 flows · $0.18
Rates are per device — iPad, Generic Tablet, Pixel 10 Pro Fold and Google Play flows are charged at the advanced rate, as per our pricing.
Each device gets its own result, grouped together in the console so you can compare a flow across devices at a glance.
Under --json, every entry in tests[] carries a device object, so the same flow run on two
devices is unambiguous:
{
"uploadId": "...",
"tests": [
{ "name": "login.yaml", "status": "PASSED", "device": { "name": "Pixel 8", "osVersion": "34", "googlePlay": false } },
{ "name": "login.yaml", "status": "FAILED", "device": { "name": "Pixel 10", "osVersion": "36", "googlePlay": false } }
]
}Without --async the run waits for every device and exits 0 only if all of them passed. Retrying a single failed result re-runs just that one flow on that one device and not the entire matrix.
-
Every device and OS must be a supported combination, including Google Play if applicable. An unsupported one is rejected before anything runs so you never get a partial submission. Some runner types support fewer devices, see Runner Type.
-
One platform per upload. An upload runs one app binary, so
--ios-device-matrixand--android-device-matrixcannot be combined in the same run. -
A flow that names its own device wins. If a flow targets a device in its YAML via per-flow devices, it runs once on that device and is excluded from the matrix. Ten flows across four devices with one targeted flow is 37 runs, not 40.