Skip to content

Commit 94cab3a

Browse files
rmarinhoCopilot
andcommitted
docs: Add device list command spec with discovery approach analysis
Add 'maui device list' command specification to the CLI design doc, including: - Command syntax with --platform and --json options - Human-readable and JSON output schemas - Analysis of two discovery approaches (MSBuild vs native CLI) - Comparison table of pros/cons - Six real-world scenarios requiring project-free device enumeration - Recommended approach (direct native tool invocation) - Relationship to dotnet run --list-devices (complementary) - References to ComputeAvailableDevices targets in dotnet/android and dotnet/macios Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent fd9256a commit 94cab3a

File tree

1 file changed

+171
-1
lines changed

1 file changed

+171
-1
lines changed

docs/design/cli.md

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
description: "Design document for the dotnet-maui CLI tool for AI-assisted development"
33
date: 2026-01-07
4+
revised: 2026-02-27
45
---
56

67
# dotnet-maui CLI Design Document
@@ -163,6 +164,168 @@ Initial implementation targets Android and iOS/Mac Catalyst, with Windows and ma
163164
- **Windows** (planned): Uses Windows screen capture APIs to capture the active app window or full screen.
164165
- **macOS** (planned): Uses macOS screen capture APIs or command-line tooling to capture the active app window or full screen.
165166

167+
#### `device list`
168+
169+
Lists connected devices, running emulators, and available simulators
170+
across all platforms from a single command.
171+
172+
**Usage:**
173+
174+
```bash
175+
dotnet maui device list [options]
176+
```
177+
178+
**Options:**
179+
180+
- `--platform <PLATFORM>`: Filter by platform (`android`, `ios`,
181+
`maccatalyst`). If omitted, lists all platforms.
182+
- `--json`: Output as JSON for machine consumption.
183+
184+
**Human-readable output:**
185+
186+
```
187+
ID Description Type Platform Status
188+
emulator-5554 Pixel 7 - API 35 Emulator android Online
189+
0A041FDD400327 Pixel 7 Pro Device android Online
190+
94E71AE5-8040-4DB2-8A9C-6CD24EF4E7DE iPhone 16 - iOS 26.0 Simulator ios Shutdown
191+
FBF5DCE8-EE2B-4215-8118-3A2190DE1AD7 iPhone 14 - iOS 26.0 Simulator ios Booted
192+
AF40CC64-2CDB-5F16-9651-86BCDF380881 My iPhone 15 Device ios Paired
193+
```
194+
195+
**JSON output (`--json`):**
196+
197+
```json
198+
{
199+
"devices": [
200+
{
201+
"id": "emulator-5554",
202+
"description": "Pixel 7 - API 35",
203+
"type": "Emulator",
204+
"platform": "android",
205+
"status": "Online"
206+
},
207+
{
208+
"id": "FBF5DCE8-EE2B-4215-8118-3A2190DE1AD7",
209+
"description": "iPhone 14 - iOS 26.0",
210+
"type": "Simulator",
211+
"platform": "ios",
212+
"status": "Booted"
213+
}
214+
]
215+
}
216+
```
217+
218+
The `id` field is the same identifier accepted by `dotnet run --device
219+
<id>`, so output from `maui device list` can be piped directly into a
220+
run command.
221+
222+
### Device Discovery: Two Approaches
223+
224+
There are two ways to enumerate devices, each suited to different
225+
scenarios.
226+
227+
#### Approach A: Via `dotnet run --list-devices` (project-based)
228+
229+
The .NET SDK (≥ .NET 11) provides `dotnet run --list-devices`, which
230+
calls the `ComputeAvailableDevices` MSBuild target defined by each
231+
platform workload ([spec][dotnet-run-spec]):
232+
233+
- **Android** ([dotnet/android]): calls `adb devices`, returns
234+
serial, description, type (Device/Emulator), status, model
235+
- **Apple** ([dotnet/macios]): calls `simctl list` and `devicectl
236+
list`, returns UDID, description, type (Device/Simulator),
237+
OS version, RuntimeIdentifier
238+
239+
This approach **requires a project file** — MSBuild evaluates the
240+
`.csproj` to locate the correct workload targets. It also operates
241+
**per-framework**: you select a target framework first, then get
242+
devices for that platform only.
243+
244+
[dotnet/android]: https://github.com/dotnet/android
245+
[dotnet/macios]: https://github.com/dotnet/macios
246+
247+
#### Approach B: Direct native tool invocation (project-free)
248+
249+
The `maui` CLI can call the same native tools directly — `adb
250+
devices`, `xcrun simctl list devices`, `xcrun devicectl list devices`
251+
— without evaluating any MSBuild project. This returns a unified,
252+
cross-platform device list in a single call.
253+
254+
#### Comparison
255+
256+
| | Approach A (MSBuild) | Approach B (Native CLI) |
257+
|---|---|---|
258+
| **Project required** | Yes — needs `.csproj` | No |
259+
| **Cross-platform** | One platform per call (per TFM) | All platforms in one call |
260+
| **Metadata** | Rich (RuntimeIdentifier, workload-specific fields) | Standard (id, description, type, status) |
261+
| **Speed** | Slower (MSBuild evaluation + restore) | Fast (<2s, direct process calls) |
262+
| **ID compatibility** | Source of truth for `dotnet run --device` | Same native IDs — compatible |
263+
| **Requires workloads** | Yes (platform workload must be installed) | Only native tools (`adb`, `simctl`) |
264+
| **Extensible** | Workloads add new device types automatically | Must add support per platform |
265+
266+
#### Scenarios Without a Project
267+
268+
Several real workflows need device enumeration **before** a project
269+
exists or **outside** any project context:
270+
271+
1. **AI agent bootstrapping** — An agent starting a "vibe coding"
272+
session needs to discover available targets before scaffolding a
273+
project. It cannot call `dotnet run --list-devices` because there
274+
is no `.csproj` yet.
275+
276+
2. **IDE startup** — VS Code opens a workspace with no MAUI project
277+
loaded. The extension needs to populate its device picker to show
278+
the user what's available. A project-free query is the only option.
279+
280+
3. **Environment validation** — A developer runs `maui device list`
281+
to answer "can I see my phone?" without needing to be inside any
282+
project directory. This is a diagnostic step, not a build step.
283+
284+
4. **CI pipeline setup** — A CI script checks that the expected
285+
emulator or simulator is running before invoking `dotnet run`.
286+
The check should not depend on a specific project file.
287+
288+
5. **Multi-project solutions** — A solution contains both Android and
289+
iOS projects. The developer wants a single unified device list
290+
rather than running `--list-devices` per project.
291+
292+
6. **Cross-platform overview**`dotnet run --list-devices` shows
293+
devices for one TFM at a time. A developer switching between
294+
Android and iOS wants to see everything at once.
295+
296+
#### Recommended Approach
297+
298+
`maui device list` uses **Approach B** (direct native tool
299+
invocation) as its primary implementation:
300+
301+
- It works anywhere — no project, no workload targets, no MSBuild
302+
evaluation overhead.
303+
- Device identifiers are the same native IDs used by
304+
`ComputeAvailableDevices`, so they are fully compatible with
305+
`dotnet run --device`.
306+
- The `maui` CLI already wraps these native tools for other commands
307+
(screenshots, environment setup), so device listing is a natural
308+
extension.
309+
310+
When a project **is** available and the user wants framework-specific
311+
device filtering, `dotnet run --list-devices` remains the right tool
312+
— it provides richer metadata (RuntimeIdentifier) and benefits from
313+
workload-specific logic. The two approaches are complementary:
314+
315+
```
316+
maui device list → "What devices exist on this machine?"
317+
dotnet run --list-devices → "What devices can run this project?"
318+
```
319+
320+
**Platform Implementation:**
321+
322+
| Platform | Native tool | What is enumerated |
323+
|----------|------------|-------------------|
324+
| Android | `adb devices -l` | Physical devices and running emulators |
325+
| iOS (simulators) | `xcrun simctl list devices --json` | All simulators (booted + shutdown) |
326+
| iOS (physical) | `xcrun devicectl list devices` | Connected physical devices |
327+
| Mac Catalyst | (host machine) | The Mac itself |
328+
166329
### Future Commands
167330

168331
To keep scope small for initial version, future commands are:
@@ -191,6 +354,9 @@ dotnet maui tree --format json
191354
### AI Agent Workflow
192355

193356
```bash
357+
# 0. Discover available devices (no project needed)
358+
dotnet maui device list --json
359+
194360
# 1. Make code changes
195361
# ... agent modifies MainPage.xaml ...
196362

@@ -285,10 +451,14 @@ future.
285451
- [vibe-wpf experiment][vibe-wpf]
286452
- [dotnet run for .NET MAUI specification][dotnet-run-spec]
287453
- [Workload manifest specification][workload-spec]
288-
- [AppleDev.Tools][appledev-tools] - Wraps simctl and xcdevice commands
454+
- [AppleDev.Tools][appledev-tools] - Wraps simctl and devicectl commands
455+
- [ComputeAvailableDevices (Android)][compute-android] - Android workload MSBuild target
456+
- [ComputeAvailableDevices (Apple)][compute-apple] - Apple workload MSBuild target
289457
- [System.CommandLine documentation](https://learn.microsoft.com/dotnet/standard/commandline/)
290458
- [Android Debug Bridge (ADB)](https://developer.android.com/studio/command-line/adb)
291459
- [simctl command-line tool](https://nshipster.com/simctl/)
292460

293461
[vibe-wpf]: https://github.com/jonathanpeppers/vibe-wpf
294462
[appledev-tools]: https://github.com/Redth/AppleDev.Tools
463+
[compute-android]: https://github.com/dotnet/android/blob/main/Documentation/docs-mobile/building-apps/build-targets.md#computeavailabledevices
464+
[compute-apple]: https://github.com/dotnet/macios/blob/main/docs/building-apps/build-targets.md#computeavailabledevices

0 commit comments

Comments
 (0)