From 00577ade73418ab6fc4c55869167be2f7aad8e96 Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Wed, 25 Feb 2026 20:27:14 +0000 Subject: [PATCH] Add maui CLI design document with environment setup commands Extends docs/design/cli.md with environment setup commands for Android (SDK/JDK/emulator) and Apple (Xcode/simulator/runtime), global options (--json, --interactive, --dry-run), platform filter values, and implementation references to dotnet/android-tools. Full specification: PR #33865 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/design/cli.md | 294 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 231 insertions(+), 63 deletions(-) diff --git a/docs/design/cli.md b/docs/design/cli.md index d2477d8a6370..c61fbb07a61f 100644 --- a/docs/design/cli.md +++ b/docs/design/cli.md @@ -1,18 +1,21 @@ --- -description: "Design document for the dotnet-maui CLI tool for AI-assisted development" +description: "Design document for the maui CLI tool" date: 2026-01-07 +updated: 2026-02-26 --- -# dotnet-maui CLI Design Document +# `maui` CLI Design Document ## Overview -The `dotnet-maui` CLI is a command-line tool that provides simple -commands for capturing screenshots, viewing logs, and inspecting the -visual tree of running .NET MAUI applications. While designed to -enable AI agents to iteratively develop and validate applications, -these commands are equally useful for developers who want quick access -to debugging and inspection capabilities from the terminal. +The `maui` CLI is a command-line tool for .NET MAUI development that provides two main capabilities: + +1. **Environment setup** — manages Android SDK/JDK, Xcode runtimes, simulators, and emulators +2. **App inspection** — captures screenshots, streams logs, and inspects the visual tree of running apps + +It is designed for three consumers: **AI agents**, **CI/CD pipelines**, and **humans**. + +**Full specification**: [PR #33865](https://github.com/dotnet/maui/pull/33865) — covers architecture, error contracts, IDE integration, JSON schemas, and vNext roadmap. ## Motivation @@ -24,47 +27,49 @@ simctl io booted screenshot`, while Android uses `adb exec-out screencap`. Similarly, log access, visual tree inspection, and device management all have platform-specific implementations. -The `dotnet-maui` CLI provides a unified interface across Android, +The `maui` CLI provides a unified interface across Android, iOS, macOS, Windows, and Mac Catalyst, making these operations simple and consistent for both developers and AI agents. +### Design Principles + +1. **Delegate to native toolchains** — wraps `sdkmanager`, `adb`, `xcrun simctl`, etc. +2. **Reuse shared libraries** — leverages [`dotnet/android-tools`](https://github.com/dotnet/android-tools) (`Xamarin.Android.Tools.AndroidSdk`) for SDK/JDK discovery, and contributes new capabilities (JDK installation, SDK bootstrap, license acceptance) back to it. +3. **Machine-first output** — every command supports `--json` +4. **Stateless** — each command reads state, acts, and exits +5. **Complement `dotnet run`** — uses the same device identifiers and framework options as [`dotnet run` for .NET MAUI][dotnet-run-spec] + ## Goals -1. **Screenshot capture**: Enable AI agents to capture screenshots of +1. **Environment setup**: Manage Android SDK/JDK, Xcode runtimes, + simulators, and emulators from a single tool + +2. **Screenshot capture**: Enable AI agents to capture screenshots of running .NET MAUI applications to validate visual changes -2. **Log access**: Provide unified access to platform-specific device +3. **Log access**: Provide unified access to platform-specific device logs (logcat, Console, etc.) -3. **Visual tree inspection**: Allow agents to inspect the runtime +4. **Visual tree inspection**: Allow agents to inspect the runtime visual tree structure and properties (.NET MAUI visual tree) -4. **Developer experience**: Integrate seamlessly with existing +5. **Developer experience**: Integrate seamlessly with existing `dotnet` CLI workflows, this should fit in with `dotnet run`, `dotnet watch`, etc. ## Installation and Invocation -The CLI will be available through multiple invocation methods to -support different workflows: - -### Method 1: Direct Tool Invocation +The CLI is available through multiple invocation methods: ```bash -dotnet-maui screenshot -o screenshot.png -``` +# Direct tool invocation (after install) +maui screenshot -o screenshot.png -### Method 2: .NET CLI - -```bash +# Via the .NET CLI dotnet maui screenshot -o screenshot.png -``` - -### Method 3: `dotnet tool exec` or `dnx` -```bash +# Inline install and invocation (no prior install needed) dotnet tool exec -y Microsoft.Maui.Cli screenshot -o screenshot.png -dnx -y Microsoft.Maui.Cli screenshot -o screenshot.png ``` ### Installation @@ -78,12 +83,10 @@ dotnet tool install Microsoft.Maui.Cli # Restore local tools dotnet tool restore - -# Inline install and invocation -dotnet tool exec -y Microsoft.Maui.Cli screenshot -o screenshot.png -dnx -y Microsoft.Maui.Cli screenshot -o screenshot.png ``` +The tool installs as `maui` on PATH. All commands in this document use the `maui` form. + The .NET workload specification includes support for automatically installing tools from workloads via the `tools-packs` feature (see [workload manifest specification][workload-spec]). However, this @@ -92,15 +95,115 @@ could be automatically installed when the `maui` workload is installed, eliminating the need for manual tool installation. Until then, manual installation via `dotnet tool install` will be how -we prove out the `dotnet-maui` CLI. +we prove out the `maui` CLI. [workload-spec]: https://github.com/dotnet/designs/blob/566ad4cafcc578d6389c215c61924ee9e07dcb29/accepted/2020/workloads/workload-manifest.md#tools-packs -## Command Structure +## Global Options + +All commands support: + +| Flag | Description | +|------|-------------| +| `--json` | Structured JSON output | +| `--verbose` | Detailed logging | +| `--interactive` | Control interactive prompts (default: `true` for terminals, `false` in CI or when output is redirected) | +| `--dry-run` | Preview actions without executing | +| `--platform

` | Filter by platform: `android`, `ios`, `maccatalyst`, `windows` | -### Global Options +**Interactivity detection** follows the same pattern as `dotnet` CLI — auto-detects CI environments (`TF_BUILD`, `GITHUB_ACTIONS`, `CI`, etc.) and checks `Console.IsOutputRedirected`. -The `dotnet-maui` CLI follows the conventions established by [`dotnet +## Environment Setup Commands + +### Android + +| Command | Description | +|---------|-------------| +| `maui android install` | Install JDK + SDK + recommended packages | +| `maui android install --accept-licenses` | Non-interactive install | +| `maui android install --packages ` | Install specific packages | +| `maui android jdk check` | Check JDK status | +| `maui android jdk install` | Install OpenJDK 21 | +| `maui android jdk list` | List installed JDKs | +| `maui android sdk list` | List installed packages | +| `maui android sdk list --available` | Show available packages | +| `maui android sdk install ` | Install package(s) | +| `maui android sdk accept-licenses` | Accept all licenses | +| `maui android sdk uninstall ` | Uninstall a package | +| `maui android emulator list` | List emulators | +| `maui android emulator create ` | Create emulator (auto-detects system image) | +| `maui android emulator start ` | Start emulator | +| `maui android emulator stop ` | Stop emulator | +| `maui android emulator delete ` | Delete emulator | + +Install paths and defaults are handled by [`dotnet/android-tools`](https://github.com/dotnet/android-tools). + +### Apple (macOS only) + +| Command | Description | +|---------|-------------| +| `maui apple install [--accept-license] [--runtime ]` | Optionally accepts Xcode license and installs simulator runtimes. Could prompt user to install Xcode in the future | +| `maui apple check` | Check Xcode, runtimes, and environment status | +| `maui apple xcode check` | Check Xcode installation and license | +| `maui apple xcode list` | List Xcode installations | +| `maui apple xcode select ` | Switch active Xcode | +| `maui apple xcode accept-license` | Accept Xcode license | +| `maui apple simulator list` | List simulators | +| `maui apple simulator create ` | Create simulator | +| `maui apple simulator start ` | Start simulator | +| `maui apple simulator stop ` | Stop simulator | +| `maui apple simulator delete ` | Delete simulator | +| `maui apple runtime check` | Check runtime status | +| `maui apple runtime list` | List installed runtimes | +| `maui apple runtime list --all` | List all runtimes (installed and downloadable) | +| `maui apple runtime install ` | Install an iOS runtime | + +> **License flag naming**: Android uses `accept-licenses` (plural) because `sdkmanager` requires accepting multiple SDK component licenses. Apple uses `accept-license` (singular) because `xcodebuild -license accept` accepts one unified Xcode license agreement. + +### Implementation References + +The `maui` CLI delegates to shared libraries for platform operations: + +**Android** — [`dotnet/android-tools`](https://github.com/dotnet/android-tools) (`Xamarin.Android.Tools.AndroidSdk`): + +| Feature | Implementation | +|---------|---------------| +| SDK discovery, bootstrap & license acceptance | [`SdkManager`](https://github.com/dotnet/android-tools/pull/275) | +| JDK discovery & installation | [`JdkInstaller`](https://github.com/dotnet/android-tools/pull/274) | +| ADB device management | [`AdbRunner`](https://github.com/dotnet/android-tools/pull/282) | +| AVD / Emulator management | [`AvdManagerRunner`](https://github.com/dotnet/android-tools/pull/283), [`EmulatorRunner`](https://github.com/dotnet/android-tools/pull/284) | + +**Apple** — wraps native toolchains directly: + +| Feature | Native tool | +|---------|------------| +| Simulator management | `xcrun simctl` (list, create, boot, shutdown, delete) | +| Runtime management | `xcrun simctl runtime` (list, add) | +| Xcode management | `xcode-select`, `xcodebuild -license` | +| Device detection | `xcrun devicectl list devices` (physical), `xcrun simctl list` (simulators) | + +Apple operations use [AppleDev.Tools][appledev-tools] for `simctl` and `devicectl` wrappers. + +### Exit Codes + +All commands use consistent exit codes: + +| Code | Meaning | +|------|---------| +| 0 | Success | +| 1 | General error | +| 2 | Environment/configuration error | +| 3 | Permission denied (elevation required) | +| 4 | Network error (download failed) | +| 5 | Resource not found | + +## App Inspection Commands (Future) + +> **Note**: App inspection commands are planned for a future release. The initial release focuses on environment setup and device management. + +### Device Selection Options + +App inspection commands will follow the conventions established by [`dotnet run` for .NET MAUI][dotnet-run-spec], using the same device selection and framework options: @@ -146,7 +249,7 @@ Captures a screenshot of the currently running .NET MAUI application. **Usage:** ```bash -dotnet maui screenshot [options] +maui screenshot [options] ``` **Options:** @@ -158,17 +261,17 @@ dotnet maui screenshot [options] Initial implementation targets Android and iOS/Mac Catalyst, with Windows and macOS support planned as described below. -- **Android**: Uses `adb screencap` -- **iOS/Mac Catalyst**: Uses `simctl io screenshot` for simulator, and device capture via Xcode tooling (future implementation) +- **Android**: Uses `adb exec-out screencap -p` +- **iOS/Mac Catalyst**: Uses `xcrun simctl io booted screenshot ` for simulator; physical device capture via Xcode tooling (future) - **Windows** (planned): Uses Windows screen capture APIs to capture the active app window or full screen. - **macOS** (planned): Uses macOS screen capture APIs or command-line tooling to capture the active app window or full screen. ### Future Commands -To keep scope small for initial version, future commands are: - -- `dotnet maui log` or `logs` -- `dotnet maui tree` for displaying the visual tree +- `maui device list` for unified device/emulator/simulator listing across platforms +- `maui screenshot` for capturing screenshots of running apps +- `maui logs` for streaming device logs +- `maui tree` for inspecting the visual tree ## Integration with `dotnet run` and `dotnet watch` @@ -180,12 +283,10 @@ The CLI is designed to work seamlessly with existing .NET workflows: # Terminal 1: Run application with hot reload dotnet watch run -# Terminal 2: Monitor logs -dotnet maui logs --follow --filter "MyApp" - -# Terminal 3: Inspect application -dotnet maui screenshot --output iteration1.png -dotnet maui tree --format json +# Terminal 2: Inspect application +maui screenshot --output iteration1.png +maui logs --follow --filter "MyApp" # future +maui tree --json # future ``` ### AI Agent Workflow @@ -198,13 +299,13 @@ dotnet maui tree --format json sleep 2 # 3. Capture screenshot -dotnet maui screenshot -o current.png +maui screenshot -o current.png -# 4. Analyze visual tree -dotnet maui tree --format json +# 4. Analyze visual tree (future) +maui tree --json -# 5. Check logs for errors -dotnet maui logs --level error +# 5. Check logs for errors (future) +maui logs --level error # 6. Agent analyzes outputs and decides next steps ``` @@ -220,10 +321,10 @@ dotnet maui logs --level error ### iOS / Mac Catalyst - **Device Detection**: `xcrun simctl list devices` (simulators), - `xcrun devicectl list devices` (physical devices) + `xcrun devicectl list devices` (physical devices) — via [AppleDev.Tools][appledev-tools] - **Screenshots**: `xcrun simctl io booted screenshot ` - (simulators), iOS devices (future implementation) + (simulators), iOS physical devices (future) - **Logs**: `xcrun simctl spawn booted log stream` or Console.app (simulators), `mlaunch --logdev` (physical devices) @@ -243,6 +344,72 @@ The CLI is designed for development and debugging scenarios only: (like screenshots and logs), the CLI should not be usable against production applications +## IDE Integration + +The `maui` CLI and its underlying libraries are designed to be the shared backend for IDE extensions, eliminating duplicate environment detection and setup logic across tools. + +### Architecture + +``` +┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ +│ VS Code ext │ │ Visual Studio │ │ AI Agent │ +│ (vscode-maui) │ │ extension │ │ (Copilot, etc.) │ +└────────┬─────────┘ └────────┬──────────┘ └────────┬─────────┘ + │ │ │ + spawns CLI references NuGet spawns CLI + │ library directly │ + │ │ │ + ▼ ▼ ▼ + ┌──────────────┐ ┌────────────────────┐ ┌──────────────┐ + │ maui CLI │ │ android-tools │ │ maui CLI │ + │ (process) │ │ (in-process) │ │ (--json) │ + └──────┬───────┘ └────────┬───────────┘ └──────┬───────┘ + │ │ │ + └─────────┬───────────┴───────────────────────┘ + │ spawns native tools + ┌───────────┼───────────┐ + ▼ ▼ ▼ + ┌───────────┐ ┌──────────┐ ┌──────────┐ + │ adb │ │ xcrun │ │ Windows │ + │ sdkmanager│ │ simctl │ │ SDK │ + └───────────┘ └──────────┘ └──────────┘ +``` + +### Integration Modes + +| Consumer | Integration | Rationale | +|----------|------------|-----------| +| **Visual Studio** extension | References `android-tools` NuGet package directly (in-process) | .NET extension — no serialization overhead, direct API access | +| **VS Code** (`vscode-maui`) | Spawns `maui` CLI process, parses `--json` stdout | TypeScript extension — CLI is the natural process boundary | +| **AI agents / CI** | Invokes `maui` CLI with `--json` | Process-based, language-agnostic | +| **Terminal** (human) | Invokes `maui` CLI directly | Human-readable output by default, `--json` when needed | + +Visual Studio consumes the `Xamarin.Android.Tools.AndroidSdk` NuGet package from [`dotnet/android-tools`](https://github.com/dotnet/android-tools) directly — the same library the CLI uses internally. This avoids process overhead and gives the VS extension full API access. Non-.NET consumers (VS Code, AI agents, CI) use the CLI as the canonical interface. + +### How IDEs Use It + +| Workflow | CLI command | IDE behavior | +|----------|------------|--------------| +| Workspace open | `maui apple check --json`, `maui android jdk check --json` | Show environment status in status bar / problems panel | +| Environment fix | `maui android install --json` | Display progress bar, stream `type: "progress"` messages | +| Device picker | `maui device list --json` (future) | Populate device dropdown / selection UI | +| Emulator launch | `maui android emulator start --json` | Show notification, update device list on completion | + +### Benefits + +- **Consistent behavior** — VS, VS Code, and CLI all use the same detection and setup logic (via shared libraries) +- **Single maintenance point** — bug fixes in `android-tools` propagate to all consumers +- **AI-ready** — agents use the same `--json` output that VS Code consumes +- **Flexible integration** — .NET consumers go in-process, others use the CLI + +### Current Status + +| Integration | Status | +|-------------|--------| +| VS Code extension (`vscode-maui`) | ✅ In progress | +| Visual Studio extension | Planned (vNext) | +| GitHub Copilot / AI agents | ✅ Supported via `--json` output | + ## Future Goals ### MCP Server @@ -262,7 +429,8 @@ if there's demonstrated need. ### More Subcommands -There are other .NET MAUI CLI tools such as: +Environment setup commands (Android SDK/JDK, Xcode, emulators, +simulators) are now included above. These were inspired by: - .NET MAUI "Check" / "Doctor" - https://github.com/Redth/dotnet-maui-check @@ -270,22 +438,22 @@ There are other .NET MAUI CLI tools such as: - Android SDK Management - https://github.com/Redth/AndroidSdk.Tools -These could easily be added down the road. - Future commands: -- `dotnet maui log` or `logs` for viewing console output -- `dotnet maui tree` for displaying the visual tree +- `maui device list` for unified device listing +- `maui logs` for viewing console output +- `maui tree` for displaying the visual tree +- `maui screenshot` for capturing screenshots -**Decision**: Start with just a few subcommands and expand in the -future. +**Decision**: Environment setup ships first. Device listing and app inspection commands +follow in a future release. ## References - [vibe-wpf experiment][vibe-wpf] - [dotnet run for .NET MAUI specification][dotnet-run-spec] - [Workload manifest specification][workload-spec] -- [AppleDev.Tools][appledev-tools] - Wraps simctl and xcdevice commands +- [AppleDev.Tools][appledev-tools] - Wraps simctl and devicectl commands - [System.CommandLine documentation](https://learn.microsoft.com/dotnet/standard/commandline/) - [Android Debug Bridge (ADB)](https://developer.android.com/studio/command-line/adb) - [simctl command-line tool](https://nshipster.com/simctl/)