Files
Hubert Gancarczyk e09e200eb5 feat(flows): let a flow run select a booted remote iOS simulator (#1060)
## What

A booted remote iOS simulator is now a device a flow run can be pointed
at - both by auto-detection and by `--platform ios-remote`.

## Why

It was invisible to flow device resolution. With a remote simulator
booted alongside local ones:

```
$ argent flow run checkout
7 booted devices matched - pass --device or --platform to disambiguate.
Available devices: 79EE0744 (ios, Booted), A1E0DF35 (ios, Booted), emulator-5554 (android, device), ...
```

Three local iPhones and four Android emulators, and the remote simulator
absent entirely. Narrowing to it did not work either - `--platform
ios-remote` was rejected by the parameter's enum. The only way onto a
remote simulator was typing the full `remote:<uuid>` id.

The cause is one type. `RawDevice.platform` was typed from the tuple of
platforms an author can *write* in a flow file, which has no
`ios-remote`, so nothing forced the case to be handled and two functions
quietly fell through:

- `isBooted` hit its `default: return false`, so a remote row never
counted as booted.
- `deviceEntryId` fell through to `serial`, a field a remote row does
not carry (it uses `udid`, prefixed `remote:`). Even once counted, it
had no id - and a resolution error printed it as `? (ios-remote,
Booted)`, hiding the very id the caller needed.

## How

The tuple served two different jobs at once - what an author may write,
and what a run may be pointed at - so it is now two:

- `LAUNCH_PLATFORMS` - launch-map keys and `when:` guards. Unchanged.
- `SELECTABLE_PLATFORMS` - device selection. Adds `ios-remote`.

`ios-remote` is selectable but deliberately not writable. A flow says
what it drives, not which machine hosts the simulator, so `when: {
platform: ios-remote }` stays a parse error.

For the same reason `ios` and `ios-remote` do not overlap: `ios` selects
local simulators only. The flow file is identical either way, so which
host runs it is an explicit choice rather than something that changes
with whatever happens to be booted.

## Scope

Selection only. A remote flow run is still coordinate-only - selector
steps, `await: { idle: true }` and `snapshot: { cropOn }` need a UI tree
source that `ios-remote` does not have yet, and `launch:` maps still
have no `ios-remote` key. Those are separate changes.

## Verification

End-to-end against a booted cloud simulator (`remote:73A22194-…`, iPhone
17 Pro / iOS 26.5) driven through the branch tool-server, with three
local simulators and four Android emulators also up:

| Run | Result |
| --- | --- |
| `platform: "ios-remote"` | resolves `remote:73A22194-…`, flow passes |
| no platform | 8 booted devices listed, including `remote:73A22194-…
(ios-remote, Booted)` - named by its id, not `?` |
| `platform: "ios"` | 3 local simulators only, the remote one absent |

`npm run build` and the tool-server suite pass.

## Docs

`flow-yaml.mdx` and the `argent flow run --help` text both list
`ios-remote` and note that `ios` never picks a remote simulator.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added support for selecting remote iOS simulators with `--platform
ios-remote`.
* Remote simulators are automatically detected when booted and
identified by their device ID.
  * Local `ios` selection continues to target only local simulators.

* **Documentation**
* Updated command-line help and flow documentation to describe remote
iOS simulator support and platform selection behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Hubert Gancarczyk <claude-hubert.gancarczyk@swmansion.com>
2026-09-10 14:31:02 +02:00
..
2026-06-01 23:22:10 +02:00