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/)