|
1 | 1 | --- |
2 | 2 | description: "Design document for the dotnet-maui CLI tool for AI-assisted development" |
3 | 3 | date: 2026-01-07 |
| 4 | +revised: 2026-02-27 |
4 | 5 | --- |
5 | 6 |
|
6 | 7 | # dotnet-maui CLI Design Document |
@@ -163,6 +164,168 @@ Initial implementation targets Android and iOS/Mac Catalyst, with Windows and ma |
163 | 164 | - **Windows** (planned): Uses Windows screen capture APIs to capture the active app window or full screen. |
164 | 165 | - **macOS** (planned): Uses macOS screen capture APIs or command-line tooling to capture the active app window or full screen. |
165 | 166 |
|
| 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 | + |
166 | 329 | ### Future Commands |
167 | 330 |
|
168 | 331 | To keep scope small for initial version, future commands are: |
@@ -191,6 +354,9 @@ dotnet maui tree --format json |
191 | 354 | ### AI Agent Workflow |
192 | 355 |
|
193 | 356 | ```bash |
| 357 | +# 0. Discover available devices (no project needed) |
| 358 | +dotnet maui device list --json |
| 359 | + |
194 | 360 | # 1. Make code changes |
195 | 361 | # ... agent modifies MainPage.xaml ... |
196 | 362 |
|
@@ -285,10 +451,14 @@ future. |
285 | 451 | - [vibe-wpf experiment][vibe-wpf] |
286 | 452 | - [dotnet run for .NET MAUI specification][dotnet-run-spec] |
287 | 453 | - [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 |
289 | 457 | - [System.CommandLine documentation](https://learn.microsoft.com/dotnet/standard/commandline/) |
290 | 458 | - [Android Debug Bridge (ADB)](https://developer.android.com/studio/command-line/adb) |
291 | 459 | - [simctl command-line tool](https://nshipster.com/simctl/) |
292 | 460 |
|
293 | 461 | [vibe-wpf]: https://github.com/jonathanpeppers/vibe-wpf |
294 | 462 | [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