From ec5cd4db9780895bdba69780124caba457fc65ff Mon Sep 17 00:00:00 2001 From: Redth Date: Mon, 4 May 2026 14:17:41 -0400 Subject: [PATCH] Update MAUI DevFlow tooling Switch repo development tooling, docs, and debug package references from the legacy Redth MauiDevFlow flow to the unified Microsoft MAUI DevFlow CLI and packages. Refresh the checked-in DevFlow agent skills with the output from maui devflow init. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/maui-ai-debugging/.skill-version | 5 - .claude/skills/maui-ai-debugging/SKILL.md | 428 ----------- .../maui-ai-debugging/references/linux.md | 124 --- .claude/skills/maui-devflow-debug/SKILL.md | 96 +++ .../references/android.md | 426 +++++------ .../references/batch.md | 100 +-- .../references/connectivity.md | 114 +++ .../references/ios-and-mac.md | 616 +++++++-------- .../maui-devflow-debug/references/linux.md | 172 +++++ .../references/macos.md | 410 +++++----- .../references/setup.md | 703 +++++++++--------- .../references/troubleshooting.md | 186 ++--- .claude/skills/maui-devflow-onboard/SKILL.md | 140 ++++ .../references/mauiprogram-registration.md | 34 + .../references/package-selection.md | 23 + AGENTS.md | 12 +- Directory.Build.props | 2 +- README.md | 2 +- docs/SCREENSHOTS.md | 22 +- dotnet-tools.json | 6 +- src/MauiSherpa.Core/Interfaces.cs | 2 +- .../Models/DevFlow/DevFlowModels.cs | 2 +- .../Services/CopilotToolsService.cs | 6 +- .../Services/DevFlowAgentClient.cs | 2 +- .../Services/ProfilingContextService.cs | 6 +- .../Skills/maui-profiling/SKILL.md | 4 +- .../MauiSherpa.LinuxGtk.csproj | 14 +- src/MauiSherpa.MacOS/MacOSMauiProgram.cs | 4 +- src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj | 4 +- .../Components/MainLayout.razor | 2 +- src/MauiSherpa.ProfilingSample/MauiProgram.cs | 4 +- .../MauiSherpa.ProfilingSample.csproj | 4 +- .../Pages/Home.razor | 2 +- src/MauiSherpa/MauiProgram.cs | 4 +- src/MauiSherpa/MauiSherpa.csproj | 4 +- src/MauiSherpa/Pages/DevFlow.razor | 4 +- .../Pages/Inspector/DevFlowPlatformTab.razor | 2 +- .../Pages/Inspector/DevFlowProfilingTab.razor | 4 +- .../Pages/Inspector/DevFlowTreeTab.razor | 2 +- .../Raw/Skills/maui-profiling/SKILL.md | 4 +- website/devflow.html | 30 +- website/getting-started.html | 2 +- 42 files changed, 1891 insertions(+), 1842 deletions(-) delete mode 100644 .claude/skills/maui-ai-debugging/.skill-version delete mode 100644 .claude/skills/maui-ai-debugging/SKILL.md delete mode 100644 .claude/skills/maui-ai-debugging/references/linux.md create mode 100644 .claude/skills/maui-devflow-debug/SKILL.md rename .claude/skills/{maui-ai-debugging => maui-devflow-debug}/references/android.md (92%) rename .claude/skills/{maui-ai-debugging => maui-devflow-debug}/references/batch.md (87%) create mode 100644 .claude/skills/maui-devflow-debug/references/connectivity.md rename .claude/skills/{maui-ai-debugging => maui-devflow-debug}/references/ios-and-mac.md (77%) create mode 100644 .claude/skills/maui-devflow-debug/references/linux.md rename .claude/skills/{maui-ai-debugging => maui-devflow-debug}/references/macos.md (88%) rename .claude/skills/{maui-ai-debugging => maui-devflow-debug}/references/setup.md (73%) rename .claude/skills/{maui-ai-debugging => maui-devflow-debug}/references/troubleshooting.md (89%) create mode 100644 .claude/skills/maui-devflow-onboard/SKILL.md create mode 100644 .claude/skills/maui-devflow-onboard/references/mauiprogram-registration.md create mode 100644 .claude/skills/maui-devflow-onboard/references/package-selection.md diff --git a/.claude/skills/maui-ai-debugging/.skill-version b/.claude/skills/maui-ai-debugging/.skill-version deleted file mode 100644 index d14b9d56..00000000 --- a/.claude/skills/maui-ai-debugging/.skill-version +++ /dev/null @@ -1,5 +0,0 @@ -{ - "commit": "feb9b85394a5ededb350466304a429cb36034567", - "updatedAt": "2026-03-04T01:51:49.8258590Z", - "branch": "main" -} \ No newline at end of file diff --git a/.claude/skills/maui-ai-debugging/SKILL.md b/.claude/skills/maui-ai-debugging/SKILL.md deleted file mode 100644 index 6f179956..00000000 --- a/.claude/skills/maui-ai-debugging/SKILL.md +++ /dev/null @@ -1,428 +0,0 @@ ---- -name: maui-ai-debugging -description: > - End-to-end workflow for building, deploying, inspecting, and debugging .NET MAUI and MAUI Blazor Hybrid apps - as an AI agent. Use when: (1) Building or running a MAUI app on iOS simulator, Android emulator, Mac Catalyst, - macOS (AppKit), or Linux/GTK, (2) Inspecting or interacting with a running app's UI (visual tree, tapping, - filling text, screenshots, property queries), (3) Debugging Blazor WebView content via CDP, (4) Managing - simulators or emulators, (5) Setting up MauiDevFlow in a MAUI project, (6) Completing a build-deploy-inspect-fix - feedback loop, (7) Handling permission dialogs and system alerts, (8) Managing multiple simultaneous apps via - the broker daemon. Covers: maui-devflow CLI, androidsdk.tool, appledev.tools, adb, xcrun simctl, xdotool, - and dotnet build/run for all MAUI target platforms including macOS (AppKit) and Linux/GTK. ---- - -# MAUI AI Debugging - -Build, deploy, inspect, and debug .NET MAUI apps from the terminal. This skill enables a complete -feedback loop: **build → deploy → inspect → fix → rebuild**. - -## Prerequisites - -```bash -dotnet tool install --global Redth.MauiDevFlow.CLI || dotnet tool update --global Redth.MauiDevFlow.CLI -dotnet tool install --global androidsdk.tool # Android only -dotnet tool install --global appledev.tools # iOS/Mac only -``` - -Keep the skill up to date: `maui-devflow update-skill`. Check installed version vs remote -with `maui-devflow skill-version`. For full update procedures, see -[references/setup.md](references/setup.md#checking-for-updates). - -## Integrating MauiDevFlow into a MAUI App - -For complete setup instructions, see [references/setup.md](references/setup.md). - -**Quick summary:** -1. Add NuGet packages (`Redth.MauiDevFlow.Agent`, and `Redth.MauiDevFlow.Blazor` for Blazor Hybrid) - - For **Linux/GTK apps** (detected via `grep -i 'GirCore\|Maui\.Gtk' *.csproj`), use `Agent.Gtk` and `Blazor.Gtk` instead - - For **macOS (AppKit) apps** (detected via `grep -i 'Platform\.Maui\.MacOS' *.csproj`), the standard `Agent` and `Blazor` packages include macOS support -2. Register in `MauiProgram.cs` inside `#if DEBUG` -3. For Blazor Hybrid: chobitsu.js is auto-injected (no manual script tag needed) -4. For Mac Catalyst: ensure `network.server` entitlement -5. For Android: run `adb reverse` for broker + agent ports -6. For Linux: no special network setup needed (direct localhost) -7. For macOS (AppKit): separate app head project, uses `open App.app` to launch. See [references/macos.md](references/macos.md) - -## Core Workflow - -### 1. Ensure a Device/Simulator/Emulator is Running - -**⚠️ Multi-project conflict avoidance:** When multiple projects may run simultaneously -(common with AI agents), each project should use its own dedicated simulator/emulator to -prevent apps from replacing each other. Check what's already in use first: - -```bash -maui-devflow list # see all registered agents -``` - -If another iOS or Android agent is already registered, **create a new simulator/emulator** -for your project instead of reusing the one that's already booted. - -**iOS Simulator:** -```bash -xcrun simctl list devices booted # check booted sims - -# Create a project-dedicated simulator to avoid conflicts -xcrun simctl create "MyApp-iPhone17Pro" "iPhone 17 Pro" "iOS 26.2" -xcrun simctl boot # boot the new sim -``` - -**Android Emulator:** -```bash -android avd list # list AVDs - -# Create a project-dedicated emulator to avoid conflicts -android avd create --name "MyApp-Pixel8" \ - --sdk "system-images;android-35;google_apis;arm64-v8a" --device pixel_8 -android avd start --name "MyApp-Pixel8" -``` - -**Mac Catalyst / macOS (AppKit) / Linux/GTK:** No device setup needed — runs as desktop app. -Multiple desktop apps can run simultaneously without conflicts. - -### 2. Detect the TFM - -**IMPORTANT:** Before building, detect the correct Target Framework Moniker from the project. -Do NOT assume `net10.0` — many projects use `net9.0`, `net8.0`, etc. - -```bash -grep -i 'TargetFrameworks' *.csproj Directory.Build.props 2>/dev/null -``` - -Use the detected version (e.g. `net9.0`) in all build commands. The examples use `$TFM`. - -### 3. Build, Deploy, and Connect - -Follow these steps for every launch and rebuild. - -**Step 1: Kill any previous instance** (skip on first launch). -A stale app's agent stays registered with the broker, causing `maui-devflow wait` to return -the old port instantly instead of waiting for the new build. - -```bash -# Stop the async shell from the previous launch, then confirm: -maui-devflow list # should show no agents (or only unrelated ones) -``` - -**Step 2: Launch in an async shell.** - -```bash -# iOS Simulator -dotnet build -f $TFM-ios -t:Run -p:_DeviceName=:v2:udid= - -# Android Emulator -dotnet build -f $TFM-android -t:Run - -# Mac Catalyst -dotnet build -f $TFM-maccatalyst -t:Run - -# macOS AppKit — build exits after compiling; launch separately -dotnet build -f $TFM-macos -open path/to/bin/Debug/$TFM-macos/osx-arm64/AppName.app - -# Linux/GTK -dotnet run --project -``` - -**⚠️ Process lifecycle rules:** -- `dotnet build -t:Run` (iOS, Android, Mac Catalyst) and `dotnet run` (Linux/GTK) **block - for the lifetime of the app**. Killing or stopping the shell **kills the app**. Use - `mode: "async"` with `initial_wait: 120` and do NOT stop the shell until you are done. -- **macOS (AppKit)** is the exception: `dotnet build` exits after compiling, and `open` - launches the app independently — the app survives shell termination. - -**Step 3: Wait for the agent** — never use `sleep`. - -```bash -maui-devflow wait # blocks until agent registers (default 120s) -maui-devflow wait --project path/to/App.csproj # filter to specific project -``` - -`maui-devflow wait` prints the assigned port as soon as the agent connects. Exit code 1 -means timeout — check async shell output for build errors. - -**Android only** — set up port forwarding after the agent connects: -```bash -adb reverse tcp:19223 tcp:19223 # Broker (lets agent in emulator reach host broker) -adb forward tcp: tcp: # Agent (lets CLI reach agent in emulator) -``` - -**To rebuild:** repeat from Step 1. See [references/troubleshooting.md](references/troubleshooting.md) -if the build fails. - -### 4. Inspect and Interact - -**Typical inspection flow:** -1. `maui-devflow MAUI tree` — see the full visual tree with element IDs, types, text, bounds -2. `maui-devflow MAUI tree --window 1` — filter to a specific window (0-based index) -3. `maui-devflow MAUI query --automationId "MyButton"` — find specific elements -4. `maui-devflow MAUI element ` — get full details (type, bounds, visibility, children) -5. `maui-devflow MAUI property Text` — read any property by name -6. `maui-devflow MAUI screenshot --output screen.png` — visual verification -7. `maui-devflow MAUI screenshot --id --output el.png` — element-only screenshot -8. `maui-devflow MAUI screenshot --selector "Button" --output btn.png` — screenshot by CSS selector - -**Property inspection** is more reliable than screenshots for verifying exact runtime values: -```bash -maui-devflow MAUI property BackgroundColor # verify dark mode colors -maui-devflow MAUI property IsVisible # check element visibility -``` - -**Live editing (no rebuild needed):** -```bash -maui-devflow MAUI set-property TextColor "Tomato" -maui-devflow MAUI set-property FontSize "24" -``` -Supports: string, bool, int, double, Color (named/hex), Thickness, enums. Changes persist -until the app restarts — safe for experimentation. - -**Typical interaction flow:** -1. `maui-devflow MAUI fill "text"` — type into Entry/Editor fields -2. `maui-devflow MAUI tap ` — tap buttons, checkboxes, list items -3. `maui-devflow MAUI clear ` — clear text fields -4. Take screenshot to verify result - -**Blazor WebView (if applicable):** -1. `maui-devflow cdp snapshot` — DOM tree as accessible text (best for AI) -2. `maui-devflow cdp Input fill "css-selector" "text"` — fill inputs -3. `maui-devflow cdp Input dispatchClickEvent "css-selector"` — click elements -4. `maui-devflow cdp Runtime evaluate "js-expression"` — run JS - -**Multiple BlazorWebViews:** If the app has more than one `BlazorWebView`, each is -registered independently with its `AutomationId`. Use `cdp webviews` to list them, -then target a specific one with `--webview` (or `-w`): - -```bash -maui-devflow cdp webviews # list all WebViews -maui-devflow cdp -w BlazorLeft snapshot # snapshot of a specific WebView -maui-devflow cdp -w 1 Runtime evaluate "document.title" # target by index -``` - -Without `--webview`, commands target the first (index 0) WebView. - -**Live CSS/DOM editing in Blazor (no rebuild needed):** -```bash -maui-devflow cdp Runtime evaluate "document.querySelector('h1').style.color = 'tomato'" -maui-devflow cdp Runtime evaluate "document.documentElement.style.setProperty('--bg-color', '#1a1a2e')" -``` - -### 5. Reading Application Logs - -MauiDevFlow automatically captures all `ILogger` output and WebView `console.*` calls -to rotating log files, retrievable remotely: - -```bash -maui-devflow MAUI logs # fetch 100 most recent log entries -maui-devflow MAUI logs --limit 50 # fetch 50 entries -maui-devflow MAUI logs --source webview # only WebView/Blazor console logs -maui-devflow MAUI logs --source native # only native ILogger logs -maui-devflow MAUI logs --follow # stream logs in real-time (Ctrl+C to stop) -maui-devflow MAUI logs -f --source native # stream only native logs -maui-devflow MAUI logs -f --json # stream as JSONL (machine-readable) -``` - -**Debugging workflow:** Reproduce the issue → `maui-devflow MAUI logs --limit 20` → check for -errors. Add temporary `ILogger` calls for more detail, rebuild, reproduce, and fetch logs again. - -### 6. Screen Recording - -Capture video of the app while performing interactions. Recording is host-side (not in-app) -using platform-native tools. - -```bash -# Start recording (default 30s timeout) -maui-devflow MAUI recording start --output demo.mp4 - -# Interact with the app -maui-devflow MAUI tap -maui-devflow MAUI navigate "//blazor" -maui-devflow MAUI fill "Hello World" - -# Stop and save -maui-devflow MAUI recording stop -``` - -**Platform tools used automatically:** -- **Android:** `adb screenrecord` (max 180s, capped with warning) -- **iOS Simulator:** `xcrun simctl io recordVideo` -- **Mac Catalyst / macOS (AppKit):** `screencapture -v` (targets app window when possible) -- **Windows/Linux:** `ffmpeg` (must be on PATH) - -**Options:** `--timeout ` (default 30), `--output ` (default `recording_.mp4`). -Only one recording at a time — stop before starting a new one. - -### 7. Network Request Monitoring - -Monitor HTTP requests made by the app in real-time. MauiDevFlow automatically intercepts -all `IHttpClientFactory`-based HTTP traffic via a `DelegatingHandler` — no app code changes -needed beyond the standard `AddMauiDevFlowAgent()` setup. - -```bash -# Live monitor — streams requests as they happen (Ctrl+C to stop) -maui-devflow MAUI network - -# JSONL streaming — machine-readable, one JSON object per line -maui-devflow MAUI network --json - -# One-shot: list recent captured requests -maui-devflow MAUI network list - -# Filter by method or host -maui-devflow MAUI network list --method POST -maui-devflow MAUI network list --host api.example.com - -# Full request/response details (headers + body) -maui-devflow MAUI network detail - -# Clear captured requests -maui-devflow MAUI network clear -``` - -**How it works:** -- A `DelegatingHandler` wraps the platform's HTTP handler (AndroidMessageHandler, - NSUrlSessionHandler, etc.), capturing request/response metadata, headers, and bodies -- Auto-injected via `ConfigureHttpClientDefaults` — works for all `IHttpClientFactory` clients -- For `new HttpClient()` outside DI, use `DevFlowHttp.CreateClient()` helper -- Bodies up to 256KB are captured (configurable via `AgentOptions.MaxNetworkBodySize`) -- A ring buffer (default 500 entries) stores recent requests in-memory - -**JSONL output** is ideal for AI parsing — pipe to `jq` or process programmatically: -```bash -maui-devflow MAUI network --json | jq 'select(.statusCode >= 400)' -``` - -**WebSocket streaming:** The live monitor uses WebSocket (`/ws/network`) for real-time push. -Connecting clients receive a replay of buffered history, then live entries as they arrive. - -## Command Reference - -### maui-devflow MAUI (Native Agent) - -Global options: `--agent-host` (default localhost), `--agent-port` (auto-discovered via broker), `--platform`. - -These options work on any subcommand position: `maui-devflow MAUI status --agent-port 10224` -or `maui-devflow --agent-port 10224 MAUI status` — both are valid. - -| Command | Description | -|---------|-------------| -| `MAUI status [--window W]` | Agent connection status, platform, app name, window count | -| `MAUI tree [--depth N] [--window W]` | Visual tree (IDs, types, text, bounds). Depth 0=unlimited. Window is 0-based index; omit for all windows | -| `MAUI query --type T --automationId A --text T` | Find elements (any/all filters) | -| `MAUI hittest [--window W]` | Find elements at a point (deepest first). Returns IDs, types, bounds | -| `MAUI tap ` | Tap an element | -| `MAUI fill ` | Fill text into Entry/Editor | -| `MAUI clear ` | Clear text from element | -| `MAUI screenshot [--output path.png] [--window W] [--id ID] [--selector SEL]` | PNG screenshot. Capture full window or a specific element by ID/selector. Window is 0-based index; default first window | -| `MAUI property ` | Read property (Text, IsVisible, FontSize, etc.) | -| `MAUI set-property ` | Set property (live editing — colors, text, sizes, etc.) | -| `MAUI element ` | Full element JSON (type, bounds, children, etc.) | -| `MAUI navigate ` | Shell navigation (e.g. `//native`, `//blazor`) | -| `MAUI scroll [--element id] [--dx N] [--dy N] [--window W]` | Scroll by delta or scroll element into view | -| `MAUI focus ` | Set focus to element | -| `MAUI resize [--window W]` | Resize app window. Window is 0-based index; default first window | -| `MAUI logs [--limit N] [--skip N] [--source S] [--follow] [--json]` | Fetch or stream application logs. `--follow` / `-f` streams in real-time via WebSocket (Ctrl+C to stop). `--json` outputs JSONL. Source: native, webview, or omit for all | -| `MAUI recording start [--output path] [--timeout 30]` | Start screen recording. Default timeout 30s. Uses platform-native tools (adb screenrecord, xcrun simctl, screencapture, ffmpeg) | -| `MAUI recording stop` | Stop active recording and save the video file | -| `MAUI recording status` | Check if a recording is currently in progress | -| `MAUI network` | Live network monitor — streams HTTP requests in real-time (Ctrl+C to stop). Use `--json` for JSONL output | -| `MAUI network list [--host H] [--method M] [--json]` | One-shot: dump recent captured HTTP requests as table or JSONL | -| `MAUI network detail ` | Full request/response details: headers, body, timing | -| `MAUI network clear` | Clear the captured request buffer | - -Element IDs come from `MAUI tree` or `MAUI query`. AutomationId-based elements use their -AutomationId directly. Others use generated hex IDs. When multiple elements share the same -AutomationId, suffixes are appended: `TodoCheckBox`, `TodoCheckBox_1`, `TodoCheckBox_2`, etc. - -### maui-devflow cdp (Blazor WebView CDP) - -Global options: `--agent-host` (default localhost), `--agent-port` (auto-discovered via broker). -CDP commands use the same agent port — all communication goes through a single port. -Use `--webview ` (or `-w `) on any CDP command to target a specific WebView -by index, AutomationId, or element ID. Default: first WebView. - -| Command | Description | -|---------|-------------| -| `cdp status` | CDP connection status and WebView count | -| `cdp webviews [--json]` | List available CDP WebViews (index, AutomationId, ready status) | -| `cdp snapshot` | Accessible DOM text (best for AI agents) | -| `cdp source` | Get full page HTML source | -| `cdp Browser getVersion` | Browser/WebView version info | -| `cdp Runtime evaluate ` | Evaluate JavaScript | -| `cdp DOM getDocument` | Full DOM document | -| `cdp DOM querySelector ` | Find first matching element | -| `cdp DOM querySelectorAll ` | Find all matching elements | -| `cdp DOM getOuterHTML ` | Get outer HTML of element | -| `cdp Page navigate ` | Navigate to URL | -| `cdp Page reload` | Reload page | -| `cdp Page captureScreenshot` | Screenshot as base64 | -| `cdp Input dispatchClickEvent ` | Click element by CSS selector | -| `cdp Input insertText ` | Insert text at focused element | -| `cdp Input fill ` | Focus + fill text into element | - -**Multi-WebView targeting:** If the app has multiple BlazorWebViews, use `cdp webviews` -to list them, then `--webview ` on any command to target a specific one. -Example: `maui-devflow cdp --webview 1 snapshot` or `maui-devflow cdp -w MyWebView Runtime evaluate "1+1"`. - -### maui-devflow Broker & Discovery - -The broker is a background daemon that manages port assignments for all running agents. -The CLI auto-starts the broker on first use — no manual setup needed. - -| Command | Description | -|---------|-------------| -| `list` | Show all registered agents (ID, app, platform, TFM, port, uptime) | -| `wait [--timeout 120] [--project path] [--wait-platform P] [--json]` | Wait for an agent to connect. Outputs the port (or JSON with `--json`). Useful after `dotnet build -t:Run` to block until the app is ready | -| `broker status` | Broker daemon status and connected agent count | -| `broker start` | Start broker daemon (auto-started by CLI — rarely needed manually) | -| `broker stop` | Stop broker daemon | -| `broker log` | Show broker log file | - -### maui-devflow batch (Multi-Command Execution) - -Execute multiple commands in one invocation via stdin. Returns JSONL responses. Use for -multi-step interactions to avoid repeated port resolution. - -```bash -echo "MAUI fill textUsername user; MAUI fill textPassword pwd123; MAUI tap buttonLogin" | maui-devflow batch -``` - -For full options, JSONL format, and streaming details, see [references/batch.md](references/batch.md). - -## Platform Details - -For detailed platform-specific setup, simulator/emulator management, and troubleshooting: - -- **Setup & Installation**: See [references/setup.md](references/setup.md) -- **iOS / Mac Catalyst**: See [references/ios-and-mac.md](references/ios-and-mac.md) -- **macOS (AppKit)**: See [references/macos.md](references/macos.md) -- **Android**: See [references/android.md](references/android.md) -- **Linux / GTK**: See [references/linux.md](references/linux.md) -- **Troubleshooting**: See [references/troubleshooting.md](references/troubleshooting.md) - -## ⚠️ Non-Disruptive Operation - -**CRITICAL:** Never run commands that steal focus, move windows, simulate mouse/keyboard input, -or otherwise disrupt the user's desktop. The user is likely working on the same computer. - -**Never use:** -- `osascript` to focus/activate windows, click UI elements, or send keystrokes -- `screencapture` interactively (the MauiDevFlow screenshot command captures in-process instead) -- `xdotool` focus/activate/key commands that affect the active window -- Any command that moves the mouse cursor or simulates input at the OS level -- `open -a` to bring apps to the foreground (use `open` only to launch, not to focus) - -**Instead:** All inspection and interaction goes through `maui-devflow` CLI commands, which -communicate with the in-app agent over HTTP — no foreground focus required. If you need -something that would require OS-level control (e.g., dismissing a system dialog outside the -app), **ask the user** to do it manually rather than attempting automation that would hijack -their input. - -## Tips - -- **Use `maui-devflow batch`** for multi-step interactions — resolves port once, adds delays, - returns structured JSONL. See [references/batch.md](references/batch.md). -- **Always use `maui-devflow MAUI screenshot`** — captures in-process, app does NOT need - foreground focus. -- Use `AutomationId` on important MAUI controls for stable element references. -- For Blazor Hybrid, `cdp snapshot` is the most AI-friendly way to read page state. -- Port discovery, multi-project setup, and custom ports: see [references/setup.md](references/setup.md#3b-port-configuration). diff --git a/.claude/skills/maui-ai-debugging/references/linux.md b/.claude/skills/maui-ai-debugging/references/linux.md deleted file mode 100644 index f2787750..00000000 --- a/.claude/skills/maui-ai-debugging/references/linux.md +++ /dev/null @@ -1,124 +0,0 @@ -# Linux / GTK Platform Guide - -Platform-specific setup and usage for .NET MAUI apps running on Linux via Maui.Gtk (GTK4). - -## Overview - -Maui.Gtk apps target `net10.0` (not a platform-specific TFM like `net10.0-ios`) and use -GTK4 via GirCore bindings. MauiDevFlow provides dedicated Linux packages that work with -this architecture. - -## NuGet Packages - -| Package | Purpose | -|---------|---------| -| `Redth.MauiDevFlow.Agent.Gtk` | In-app agent (visual tree, screenshots, tapping, logging) | -| `Redth.MauiDevFlow.Blazor.Gtk` | CDP bridge for WebKitGTK BlazorWebView | - -These replace `Redth.MauiDevFlow.Agent` and `Redth.MauiDevFlow.Blazor` which target -standard MAUI platforms (iOS, Android, macCatalyst, Windows). - -```xml - - - - - -``` - -## Registration - -### MauiProgram.cs - -```csharp -using MauiDevFlow.Agent.Gtk; -using MauiDevFlow.Blazor.Gtk; // Blazor Hybrid only - -var builder = MauiApp.CreateBuilder(); -// ... your existing setup ... - -#if DEBUG -builder.AddMauiDevFlowAgent(); -builder.AddMauiBlazorDevFlowTools(); // Blazor Hybrid only -#endif -``` - -### Application Startup - -The agent must be started after the MAUI Application is available. In your GTK app -startup (e.g., `GtkMauiApplication.OnActivate` or equivalent): - -```csharp -#if DEBUG -app.StartDevFlowAgent(); - -// For Blazor Hybrid, wire CDP to the agent: -var blazorService = app.Handler?.MauiContext?.Services - .GetService(); -blazorService?.WireBlazorCdpToAgent(); -#endif -``` - -## Building and Running - -Linux/GTK apps use `dotnet run` (not `dotnet build -t:Run` which is MAUI-specific): - -```bash -# Build and run (in background/async shell) -dotnet run --project - -# Build only -dotnet build -``` - -Build times are typically fast (~5-10s) since there's no device deployment step. - -## Network Setup - -**No special setup needed.** Linux apps run directly on localhost — the CLI connects -directly to `http://localhost:`. No port forwarding (unlike Android) or entitlements -(unlike Mac Catalyst) required. - -## Key Simulation - -The `LinuxAppDriver` uses `xdotool` for key simulation. Install it if needed: - -```bash -sudo apt install xdotool -``` - -For Wayland-only environments, `ydotool` may be needed instead. Key simulation is used -by the CLI for alert dismissal and keyboard input. - -## Platform Differences - -| Feature | Standard MAUI | Linux/GTK | -|---------|--------------|-----------| -| NuGet packages | `Agent`, `Blazor` | `Agent.Gtk`, `Blazor.Gtk` | -| TFM | `net10.0-` | `net10.0` | -| Build command | `dotnet build -f $TFM -t:Run` | `dotnet run --project ` | -| Agent startup | Automatic (lifecycle hook) | Manual (`app.StartDevFlowAgent()`) | -| Network | Varies by platform | Direct localhost | -| Screenshots | `VisualDiagnostics` | GTK `WidgetPaintable` → `Texture.SaveToPng()` | -| Native tap | Platform gesture system | `Gtk.Widget.Activate()` | -| Key simulation | Platform-specific | `xdotool` | -| Blazor WebView | WKWebView / WebView2 / Chrome | WebKitGTK 6.0 | - -## Troubleshooting - -### Agent Not Starting - -1. Ensure `app.StartDevFlowAgent()` is called after the app is activated -2. Check that `Application.Current` is available when `StartDevFlowAgent()` runs -3. Verify the port isn't in use: `lsof -i :` or `ss -tlnp | grep ` - -### xdotool Not Working - -- On Wayland, `xdotool` may not work. Try `ydotool` instead -- Ensure the app window has focus for key events - -### WebKitGTK CDP Issues - -- WebKitGTK uses `EvaluateJavascriptAsync` for JS evaluation -- The same two-eval CDP pattern (send + poll) applies as other platforms -- Check that `chobitsu.js` is properly loaded in the WebView diff --git a/.claude/skills/maui-devflow-debug/SKILL.md b/.claude/skills/maui-devflow-debug/SKILL.md new file mode 100644 index 00000000..11048acd --- /dev/null +++ b/.claude/skills/maui-devflow-debug/SKILL.md @@ -0,0 +1,96 @@ +--- +name: maui-devflow-debug +description: >- + Run build, deploy, inspect, and fix loops for .NET MAUI apps that already have + MAUI DevFlow integrated. USE FOR: launching MAUI apps, selecting devices or + emulators, waiting for or recovering agent connections, broker/port/adb + connectivity issues, visual tree inspection, screenshots, UI interaction, + Blazor WebView CDP debugging, reading DevFlow logs, and iterative app + debugging. DO NOT USE FOR: first-time DevFlow package setup (use + maui-devflow-onboard), or generic desktop automation unrelated to MAUI. INVOKES: + maui devflow CLI, dotnet CLI, Android adb/android tools, and Apple simctl + tools. +--- + +# DevFlow Debug + +Use this skill for the active debugging loop after a MAUI app has DevFlow +packages and `builder.AddMauiDevFlowAgent()` registered. + +## When to Use + +- Build and run a MAUI app on Android, iOS, Mac Catalyst, macOS, Windows, or GTK. +- Choose or create a simulator/emulator for a project. +- Wait for a DevFlow agent, inspect the visual tree, tap/fill UI, or capture screenshots. +- Recover from DevFlow connection failures after the app is integrated, including broker, port, and Android adb forwarding issues. +- Debug Blazor Hybrid content through DevFlow WebView/CDP commands. +- Read app logs, network captures, preferences, device info, or recordings through DevFlow. +- Iterate on an app bug with a build -> deploy -> inspect -> fix loop. + +## Route Elsewhere + +- If DevFlow packages or `MauiProgram.cs` registration are missing, use `maui-devflow-onboard`. +- If the failure is a generic build or SDK issue with no DevFlow angle, use normal .NET/MAUI diagnostics. + +## Core Loop + +1. Confirm the app is already integrated: + + ```bash + grep -rl "Microsoft.Maui.DevFlow" --include="*.csproj" . + ``` + + If no project has DevFlow package references, stop and switch to `maui-devflow-onboard`. + +2. Pick the target framework and launch target. Do not assume `net10.0`; inspect the project first. + + ```bash + grep -i "TargetFramework" *.csproj Directory.Build.props 2>/dev/null + ``` + +3. Start or select the device/emulator. For Android and iOS, avoid reusing a simulator/emulator that is already running another app under investigation. + +4. Launch the app and keep the launch process alive when required. + + - iOS, Android, and Mac Catalyst `dotnet build -t:Run` usually block for the app lifetime. + - GTK `dotnet run` blocks for the app lifetime. + - macOS AppKit builds can exit after compiling; launch the `.app` separately. + +5. Wait for the DevFlow agent before inspecting UI: + + ```bash + maui devflow wait + maui devflow ui tree --depth 3 --fields "id,type,text,automationId" + ``` + + If `wait`, `list`, or `ui tree` cannot connect after the app is running, load `references/connectivity.md` and recover the broker/agent connection before continuing. + +6. Inspect, interact, capture evidence, then edit the app and repeat from launch. + +## Critical Anti-patterns + +- Do not treat an empty `maui devflow list` as proof the project is not integrated. `list` is runtime state; project files are source of truth. +- Do not use arbitrary sleeps after launch. Use `maui devflow wait` to gate on the actual agent connection. +- Do not kill an async `dotnet build -t:Run` or `dotnet run` shell while you still need the app; that often kills the app. +- Do not reuse a busy simulator/emulator when multiple MAUI apps or agents may be running. +- Do not debug Blazor WebView DOM issues through the native visual tree alone; use the WebView/CDP commands. + +## Stop Signals + +- Stop and switch to `maui-devflow-onboard` when package references or `AddMauiDevFlowAgent()` are absent. +- Stop and ask which project, device, or agent to target when multiple candidates match. +- Stop rebuilding after two identical failures until you inspect the first meaningful build/runtime error. +- Stop using screenshots for exact property values; query the visual tree or properties instead. + +## Reference Map + +Load these only when needed: + +- `references/setup.md` - detailed integration, package, entitlement, and update notes. +- `references/connectivity.md` - broker, agent, port, Android forwarding, and "no agents connected" recovery. +- `references/android.md` - Android SDK, emulator, adb, build, deploy, and port forwarding details. +- `references/ios-and-mac.md` - iOS simulator, Mac Catalyst, permissions, entitlements, and Apple tooling. +- `references/macos.md` - macOS AppKit project shape, launch model, and troubleshooting. +- `references/linux.md` - GTK/Linux launch, packages, and WebKitGTK notes. +- `references/batch.md` - batching multiple DevFlow UI/WebView operations. +- `references/troubleshooting.md` - build, connection, CDP, and platform-specific failure recovery. diff --git a/.claude/skills/maui-ai-debugging/references/android.md b/.claude/skills/maui-devflow-debug/references/android.md similarity index 92% rename from .claude/skills/maui-ai-debugging/references/android.md rename to .claude/skills/maui-devflow-debug/references/android.md index f0f0d751..917506b8 100644 --- a/.claude/skills/maui-ai-debugging/references/android.md +++ b/.claude/skills/maui-devflow-debug/references/android.md @@ -1,213 +1,213 @@ -# Android Reference - -## Table of Contents -- [Emulator Management](#emulator-management) -- [Building and Deploying](#building-and-deploying) -- [Android CLI Tool](#android-cli-tool) -- [ADB Reference](#adb-reference) -- [SDK Management](#sdk-management) -- [Troubleshooting](#troubleshooting) - -## Emulator Management - -### Avoiding multi-project conflicts - -When multiple projects (or AI agents) may deploy to Android emulators simultaneously, -each project should use its own dedicated AVD. Two apps deployed to the same emulator -will coexist (unlike iOS), but `adb reverse`/`adb forward` port forwarding is per-device -and can cause confusion when multiple emulators are running. - -**Before creating or starting an emulator, check what's already in use:** -```bash -maui-devflow list # shows agents with platform + port -adb devices # shows connected emulators -``` - -If an emulator is already running another project's agent, create a new AVD: -```bash -android avd create --name "ProjectName-Pixel8" \ - --sdk "system-images;android-35;google_apis;arm64-v8a" --device pixel_8 -android avd start --name "ProjectName-Pixel8" -``` - -**When multiple emulators are running**, use `-s ` to target a specific one: -```bash -adb -s emulator-5554 reverse tcp:19223 tcp:19223 # first emulator -adb -s emulator-5556 reverse tcp:19223 tcp:19223 # second emulator -``` - -**Naming convention:** Use `-` (e.g. `TodoApp-Pixel8`) so it's -clear which AVD belongs to which project. - -### List and start AVDs -```bash -android avd list # list available AVDs -android avd start --name # start emulator -``` - -### Create AVD -```bash -# List available targets and device profiles -android avd targets # system images -android avd devices # device profiles (pixel, etc.) - -android avd create --name "Pixel8API35" \ - --sdk "system-images;android-35;google_apis;arm64-v8a" \ - --device pixel_8 -``` - -### Delete AVD -```bash -android avd delete --name -``` - -### Verify emulator is running -```bash -adb devices # should show "emulator-5554 device" -android device list # formatted list -``` - -## Building and Deploying - -```bash -# Build and deploy to running emulator -dotnet build -f net10.0-android -t:Run - -# Build only (no deploy) -dotnet build -f net10.0-android -``` - -**Critical: Port forwarding after deploy** — the Android emulator runs in its own network. -Forward the broker port and the agent port: -```bash -adb reverse tcp:19223 tcp:19223 # Broker (lets agent register) -adb forward tcp: tcp: # Agent (lets CLI reach agent) -``` - -The broker reverse is needed so the agent inside the emulator can connect to the host's -broker daemon. The agent forward uses the port shown in `maui-devflow list` after the agent -registers (range 10223–10899). - -If the broker isn't available (fallback mode), forward the port from `.mauidevflow` instead: -```bash -adb reverse tcp:9223 tcp:9223 # Fallback: direct agent port -``` - -Then verify: `maui-devflow MAUI status` and `maui-devflow cdp status`. - -### Install APK manually -```bash -adb install -r path/to/app.apk # install/reinstall -android device install --package path/to/app.apk -``` - -## Android CLI Tool - -The `android` command (from `androidsdk.tool` NuGet) wraps SDK tools. - -### SDK management -``` -android sdk list # all packages -android sdk list --installed # installed only -android sdk list --available # available for install -android sdk install --package "platforms;android-35" -android sdk install --package "system-images;android-35;google_apis;arm64-v8a" -android sdk install --package "emulator" -android sdk uninstall --package -android sdk info # SDK location, tools versions -android sdk accept-licenses # accept all SDK licenses -android sdk download # download cmdline-tools -``` - -### AVD management -``` -android avd list # available AVDs -android avd targets # available system images -android avd devices # available device profiles -android avd create --name --sdk --device -android avd delete --name -android avd start --name -``` - -### Device/emulator operations -``` -android device list # connected devices/emulators -android device info [--device ] # device properties -android device install --package # install APK -android device uninstall --package # uninstall by package name -``` - -### JDK management -``` -android jdk list # available JDKs -android jdk info # current JDK info -``` - -## ADB Reference - -### Device/emulator basics -```bash -adb devices # list connected devices -adb -s shell # shell into specific device -adb shell pm list packages | grep # find installed packages -adb shell am start -n / # launch activity -adb shell am force-stop # kill app -``` - -### Port forwarding (critical for MauiDevFlow) -```bash -adb reverse tcp:19223 tcp:19223 # Broker (agent → host) -adb forward tcp: tcp: # Agent (CLI → emulator, get port from `maui-devflow list`) -adb reverse --list # verify forwarding -adb forward --list # verify forwarding -adb reverse --remove-all # clean up reverse -adb forward --remove-all # clean up forward -``` - -### File operations -```bash -adb push local/file /sdcard/path # push file to device -adb pull /sdcard/path local/file # pull file from device -``` - -### Logs -```bash -adb logcat -s "DOTNET" --format brief # .NET runtime logs -adb logcat -s "MauiDevFlow" # agent logs -adb logcat --pid=$(adb shell pidof ) # app-specific logs -adb logcat -c # clear log buffer -``` - -### Screenshots and screen recording -```bash -adb shell screencap /sdcard/screen.png && adb pull /sdcard/screen.png -adb shell screenrecord /sdcard/video.mp4 # Ctrl+C to stop -``` - -## SDK Management - -### Typical setup for MAUI Android development -```bash -android sdk accept-licenses -android sdk install --package "platforms;android-35" -android sdk install --package "build-tools;35.0.0" -android sdk install --package "system-images;android-35;google_apis;arm64-v8a" -android sdk install --package "emulator" -android sdk install --package "platform-tools" -``` - -### Environment variables -```bash -export ANDROID_HOME=$HOME/Library/Android/sdk -export ANDROID_SDK_ROOT=$ANDROID_HOME -export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator -``` - -## Troubleshooting - -- **`adb devices` shows "unauthorized"**: Accept the USB debugging prompt on the device/emulator. -- **Agent not connecting on emulator**: Forgot `adb reverse tcp:19223 tcp:19223` for the broker. Run port forwarding, then check `maui-devflow list`. -- **Emulator won't start**: Check available system images with `android avd targets`. May need - to install with `android sdk install --package "system-images;..."`. -- **Build error "No Android devices found"**: Ensure emulator is booted (`adb devices`). -- **Slow emulator**: Use hardware acceleration. Prefer `arm64-v8a` images on Apple Silicon Macs. +# Android Reference + +## Table of Contents +- [Emulator Management](#emulator-management) +- [Building and Deploying](#building-and-deploying) +- [Android CLI Tool](#android-cli-tool) +- [ADB Reference](#adb-reference) +- [SDK Management](#sdk-management) +- [Troubleshooting](#troubleshooting) + +## Emulator Management + +### Avoiding multi-project conflicts + +When multiple projects (or AI agents) may deploy to Android emulators simultaneously, +each project should use its own dedicated AVD. Two apps deployed to the same emulator +will coexist (unlike iOS), but `adb reverse`/`adb forward` port forwarding is per-device +and can cause confusion when multiple emulators are running. + +**Before creating or starting an emulator, check what's already in use:** +```bash +maui devflow list # shows agents with platform + port +adb devices # shows connected emulators +``` + +If an emulator is already running another project's agent, create a new AVD: +```bash +android avd create --name "ProjectName-Pixel8" \ + --sdk "system-images;android-35;google_apis;arm64-v8a" --device pixel_8 +android avd start --name "ProjectName-Pixel8" +``` + +**When multiple emulators are running**, use `-s ` to target a specific one: +```bash +adb -s emulator-5554 reverse tcp:19223 tcp:19223 # first emulator +adb -s emulator-5556 reverse tcp:19223 tcp:19223 # second emulator +``` + +**Naming convention:** Use `-` (e.g. `TodoApp-Pixel8`) so it's +clear which AVD belongs to which project. + +### List and start AVDs +```bash +android avd list # list available AVDs +android avd start --name # start emulator +``` + +### Create AVD +```bash +# List available targets and device profiles +android avd targets # system images +android avd devices # device profiles (pixel, etc.) + +android avd create --name "Pixel8API35" \ + --sdk "system-images;android-35;google_apis;arm64-v8a" \ + --device pixel_8 +``` + +### Delete AVD +```bash +android avd delete --name +``` + +### Verify emulator is running +```bash +adb devices # should show "emulator-5554 device" +android device list # formatted list +``` + +## Building and Deploying + +```bash +# Build and deploy to running emulator +dotnet build -f net10.0-android -t:Run + +# Build only (no deploy) +dotnet build -f net10.0-android +``` + +**Critical: Port forwarding after deploy** — the Android emulator runs in its own network. +Forward the broker port and the agent port: +```bash +adb reverse tcp:19223 tcp:19223 # Broker (lets agent register) +adb forward tcp: tcp: # Agent (lets CLI reach agent) +``` + +The broker reverse is needed so the agent inside the emulator can connect to the host's +broker daemon. The agent forward uses the port shown in `maui devflow list` after the agent +registers (range 10223–10899). + +If the broker isn't available (fallback mode), forward the port from `.mauidevflow` instead: +```bash +adb forward tcp:9223 tcp:9223 # Fallback: direct agent port +``` + +Then verify: `maui devflow ui status` and `maui devflow webview status`. + +### Install APK manually +```bash +adb install -r path/to/app.apk # install/reinstall +android device install --package path/to/app.apk +``` + +## Android CLI Tool + +The `android` command (from `androidsdk.tool` NuGet) wraps SDK tools. + +### SDK management +``` +android sdk list # all packages +android sdk list --installed # installed only +android sdk list --available # available for install +android sdk install --package "platforms;android-35" +android sdk install --package "system-images;android-35;google_apis;arm64-v8a" +android sdk install --package "emulator" +android sdk uninstall --package +android sdk info # SDK location, tools versions +android sdk accept-licenses # accept all SDK licenses +android sdk download # download cmdline-tools +``` + +### AVD management +``` +android avd list # available AVDs +android avd targets # available system images +android avd devices # available device profiles +android avd create --name --sdk --device +android avd delete --name +android avd start --name +``` + +### Device/emulator operations +``` +android device list # connected devices/emulators +android device info [--device ] # device properties +android device install --package # install APK +android device uninstall --package # uninstall by package name +``` + +### JDK management +``` +android jdk list # available JDKs +android jdk info # current JDK info +``` + +## ADB Reference + +### Device/emulator basics +```bash +adb devices # list connected devices +adb -s shell # shell into specific device +adb shell pm list packages | grep # find installed packages +adb shell am start -n / # launch activity +adb shell am force-stop # kill app +``` + +### Port forwarding (critical for MAUI DevFlow) +```bash +adb reverse tcp:19223 tcp:19223 # Broker (agent → host) +adb forward tcp: tcp: # Agent (CLI → emulator, get port from `maui devflow list`) +adb reverse --list # verify forwarding +adb forward --list # verify forwarding +adb reverse --remove-all # clean up reverse +adb forward --remove-all # clean up forward +``` + +### File operations +```bash +adb push local/file /sdcard/path # push file to device +adb pull /sdcard/path local/file # pull file from device +``` + +### Logs +```bash +adb logcat -s "DOTNET" --format brief # .NET runtime logs +adb logcat -s "MauiDevFlow" # agent logs +adb logcat --pid=$(adb shell pidof ) # app-specific logs +adb logcat -c # clear log buffer +``` + +### Screenshots and screen recording +```bash +adb shell screencap /sdcard/screen.png && adb pull /sdcard/screen.png +adb shell screenrecord /sdcard/video.mp4 # Ctrl+C to stop +``` + +## SDK Management + +### Typical setup for MAUI Android development +```bash +android sdk accept-licenses +android sdk install --package "platforms;android-35" +android sdk install --package "build-tools;35.0.0" +android sdk install --package "system-images;android-35;google_apis;arm64-v8a" +android sdk install --package "emulator" +android sdk install --package "platform-tools" +``` + +### Environment variables +```bash +export ANDROID_HOME=$HOME/Library/Android/sdk +export ANDROID_SDK_ROOT=$ANDROID_HOME +export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator +``` + +## Troubleshooting + +- **`adb devices` shows "unauthorized"**: Accept the USB debugging prompt on the device/emulator. +- **Agent not connecting on emulator**: Forgot `adb reverse tcp:19223 tcp:19223` for the broker. Run port forwarding, then check `maui devflow list`. +- **Emulator won't start**: Check available system images with `android avd targets`. May need + to install with `android sdk install --package "system-images;..."`. +- **Build error "No Android devices found"**: Ensure emulator is booted (`adb devices`). +- **Slow emulator**: Use hardware acceleration. Prefer `arm64-v8a` images on Apple Silicon Macs. diff --git a/.claude/skills/maui-ai-debugging/references/batch.md b/.claude/skills/maui-devflow-debug/references/batch.md similarity index 87% rename from .claude/skills/maui-ai-debugging/references/batch.md rename to .claude/skills/maui-devflow-debug/references/batch.md index 80e95665..22974560 100644 --- a/.claude/skills/maui-ai-debugging/references/batch.md +++ b/.claude/skills/maui-devflow-debug/references/batch.md @@ -1,50 +1,50 @@ -# Batch Command Reference - -Execute multiple MAUI/cdp commands in a single CLI invocation via stdin. Outputs JSONL -responses (one JSON object per line) to stdout — ideal for AI agents and scripting. - -## Usage - -```bash -# Pipe multiple commands (semicolons or newlines as separators) -echo "MAUI fill textUsername user; MAUI fill textPassword pwd123; MAUI tap buttonLogin" | maui-devflow batch - -# Multi-line input -printf "MAUI status\nMAUI tree\nMAUI screenshot --output screen.png" | maui-devflow batch - -# With options -echo "MAUI status; MAUI tree" | maui-devflow batch --delay 500 --continue-on-error --agent-port 10224 - -# Human-readable output instead of JSONL -echo "MAUI status; MAUI tree" | maui-devflow batch --human -``` - -## Options - -| Option | Default | Description | -|--------|---------|-------------| -| `--delay ` | 250 | Delay between commands (lets UI settle) | -| `--continue-on-error` | false | Continue after a command fails (default: stop) | -| `--human` | false | Human-readable output instead of JSONL | - -## JSONL Response Format - -One JSON object per command, streamed as each completes: -```json -{"command":"MAUI fill textUsername user","exit_code":0,"output":"Filled: textUsername"} -{"command":"MAUI tap buttonLogin","exit_code":1,"output":"Error: Element not found: buttonLogin"} -``` - -## Interactive Streaming - -The batch command processes stdin line-by-line, so a caller can read each JSONL response -before sending the next command. This enables reactive workflows where the AI agent inspects -results and decides the next action. - -## Input Rules - -- Lines starting with `#` are comments (skipped) -- Empty lines are skipped -- Semicolons separate multiple commands on one line -- Quoted strings are preserved: `MAUI fill myEntry "hello world"` -- Only `MAUI` and `cdp` commands are allowed (broker/list/etc. are rejected) +# Batch Command Reference + +Execute multiple MAUI/cdp commands in a single CLI invocation via stdin. Outputs JSONL +responses (one JSON object per line) to stdout — ideal for AI agents and scripting. + +## Usage + +```bash +# Pipe multiple commands (semicolons or newlines as separators) +echo "MAUI fill textUsername user; MAUI fill textPassword pwd123; MAUI tap buttonLogin" | maui devflow batch + +# Multi-line input +printf "MAUI status\nMAUI tree\nMAUI screenshot --output screen.png" | maui devflow batch + +# With options +echo "MAUI status; MAUI tree" | maui devflow batch --delay 500 --continue-on-error --agent-port 10224 + +# Human-readable output instead of JSONL +echo "MAUI status; MAUI tree" | maui devflow batch --human +``` + +## Options + +| Option | Default | Description | +|--------|---------|-------------| +| `--delay ` | 250 | Delay between commands (lets UI settle) | +| `--continue-on-error` | false | Continue after a command fails (default: stop) | +| `--human` | false | Human-readable output instead of JSONL | + +## JSONL Response Format + +One JSON object per command, streamed as each completes: +```json +{"command":"MAUI fill textUsername user","exit_code":0,"output":"Filled: textUsername"} +{"command":"MAUI tap buttonLogin","exit_code":1,"output":"Error: Element not found: buttonLogin"} +``` + +## Interactive Streaming + +The batch command processes stdin line-by-line, so a caller can read each JSONL response +before sending the next command. This enables reactive workflows where the AI agent inspects +results and decides the next action. + +## Input Rules + +- Lines starting with `#` are comments (skipped) +- Empty lines are skipped +- Semicolons separate multiple commands on one line +- Quoted strings are preserved: `MAUI fill myEntry "hello world"` +- Only `MAUI` and `cdp` commands are allowed (broker/list/etc. are rejected) diff --git a/.claude/skills/maui-devflow-debug/references/connectivity.md b/.claude/skills/maui-devflow-debug/references/connectivity.md new file mode 100644 index 00000000..65a38ccd --- /dev/null +++ b/.claude/skills/maui-devflow-debug/references/connectivity.md @@ -0,0 +1,114 @@ +# Connectivity Recovery + +Use this when a project already has DevFlow package references and `builder.AddMauiDevFlowAgent()` registered, but the `maui` CLI cannot reach a running app. + +## Quick workflow + +1. Run the built-in diagnostic: + + ```bash + maui devflow diagnose + ``` + + Use the result to separate broker startup, missing project integration, no running app, and target-device networking issues. + +2. Verify integration before chasing ports: + + ```bash + grep -R --include="*.csproj" "Microsoft.Maui.DevFlow.Agent" . + grep -R "AddMauiDevFlowAgent" . + ``` + + If package references or `AddMauiDevFlowAgent()` are missing, stop and switch to `maui-devflow-onboard`. + +3. Check broker health: + + ```bash + maui devflow broker status + maui devflow broker start + ``` + +4. List and wait for agents: + + ```bash + maui devflow list + maui devflow wait + maui devflow ui tree --depth 1 + ``` + + A successful `ui tree` means connectivity is fixed; continue the main debug loop. + +## Platform notes + +### Android emulator + +Android emulators run in a separate network namespace. Broker registration and CLI-to-agent traffic need opposite forwarding directions: + +```bash +maui devflow list # note the assigned agent port +adb reverse tcp:19223 tcp:19223 # app in emulator -> host broker +adb forward tcp: tcp: # host CLI -> app agent +adb reverse --list +adb forward --list +``` + +If no broker is available and the app uses a direct `.mauidevflow` port, forward that port instead: + +```bash +adb forward tcp:9223 tcp:9223 +``` + +### iOS simulator + +No forwarding is normally needed because simulators share host networking: + +```bash +xcrun simctl list devices booted +``` + +### Mac Catalyst and macOS + +Mac Catalyst needs Debug entitlements that allow the agent and CDP servers to bind ports: + +```xml +com.apple.security.network.server + +``` + +macOS AppKit and Mac Catalyst otherwise use direct localhost access. Check for explicit port conflicts only after confirming broker discovery: + +```bash +lsof -i :9223 +``` + +### Windows and Linux/GTK + +These use direct localhost access. On Linux, verify the app process started: + +```bash +pgrep -f "YourApp" +``` + +## Common symptoms + +| Symptom | Fix | +|---------|-----| +| `maui devflow list` shows no agents | Verify app is running in Debug, package references exist, and `AddMauiDevFlowAgent()` executes | +| Android agent never registers | Run `adb reverse tcp:19223 tcp:19223` for broker registration | +| Android connection refused after registration | Run `adb forward tcp: tcp:` using the port from `maui devflow list` | +| Broker unavailable | `maui devflow broker start`; retry the command | +| Port already in use | Identify the owner with `lsof -i :` before killing a PID | +| Multiple agents connected | Ask which app/device/agent port to target; use `--agent-port` | + +## Stop signals + +- Stop and switch to `maui-devflow-onboard` if package references or `AddMauiDevFlowAgent()` are missing. +- Stop connectivity recovery once `maui devflow wait` succeeds and `maui devflow ui tree --depth 1` returns a tree. +- Stop and ask which target to use if multiple connected agents or devices match the app. +- Stop after confirming a generic build/deploy failure; the app must launch before broker connectivity can work. + +## Anti-patterns + +- Do not treat an empty `maui devflow list` as proof the project is not integrated. It only means no runtime agent is connected. +- Do not use `adb reverse` for the agent HTTP port when the host CLI must connect into the emulator. Use `adb forward tcp: tcp:` for that direction. +- Do not kill random processes by name. Identify the owning PID first. diff --git a/.claude/skills/maui-ai-debugging/references/ios-and-mac.md b/.claude/skills/maui-devflow-debug/references/ios-and-mac.md similarity index 77% rename from .claude/skills/maui-ai-debugging/references/ios-and-mac.md rename to .claude/skills/maui-devflow-debug/references/ios-and-mac.md index fd96e658..c6acd5db 100644 --- a/.claude/skills/maui-ai-debugging/references/ios-and-mac.md +++ b/.claude/skills/maui-devflow-debug/references/ios-and-mac.md @@ -1,292 +1,324 @@ -# iOS & Mac Catalyst Reference - -## Table of Contents -- [Simulator Management](#simulator-management) -- [Building and Deploying](#building-and-deploying) -- [Apple CLI Tool](#apple-cli-tool) -- [xcrun simctl Reference](#xcrun-simctl-reference) -- [Troubleshooting](#troubleshooting) - -## Simulator Management - -### Avoiding multi-project conflicts - -When multiple projects (or AI agents) may deploy to iOS simulators simultaneously, each -project should use its own dedicated simulator. Two apps deployed to the same simulator -will replace each other — only the last-deployed app survives. - -**Before creating or booting a simulator, check what's already in use:** -```bash -maui-devflow list # shows agents with platform + port -xcrun simctl list devices booted # shows all booted simulators -``` - -If a booted simulator is already running another project's agent, create a new one: -```bash -xcrun simctl create "ProjectName-iPhone17Pro" "iPhone 17 Pro" "iOS 26.2" -# Use the returned UDID in your build command -``` - -**Naming convention:** Use `-` (e.g. `TodoApp-iPhone17Pro`) so -it's clear which simulator belongs to which project. - -### List simulators -```bash -xcrun simctl list devices # all devices by runtime -xcrun simctl list devices booted # only booted -xcrun simctl list devices available # only available -apple simulator list # formatted table -apple simulator list --booted # booted only -``` - -### Create simulator -```bash -# List available device types and runtimes first -xcrun simctl list devicetypes # e.g. "iPhone 16 Pro" -xcrun simctl list runtimes # e.g. "iOS 18.2" - -xcrun simctl create "My iPhone" "iPhone 16 Pro" "iOS 18.2" -apple simulator create "My iPhone" --device-type "iPhone 16 Pro" --runtime "iOS 18.2" -``` - -### Boot / shutdown -```bash -xcrun simctl boot -xcrun simctl shutdown -apple simulator boot -apple simulator shutdown -``` - -### Install and launch app -```bash -xcrun simctl install booted /path/to/App.app -xcrun simctl launch booted com.company.appid -``` - -### Screenshots (iOS Simulator) -```bash -xcrun simctl io booted screenshot output.png -apple simulator screenshot --output output.png -``` - -### Screenshots (Mac Catalyst) - -**Use `maui-devflow MAUI screenshot`** for Mac Catalyst apps — it captures the UI in-process -and does NOT require the app to be in the foreground. Never use `osascript` to bring the window -to the front or `screencapture` for Mac Catalyst screenshots; they are unnecessary and unreliable. - -```bash -maui-devflow MAUI screenshot --output screen.png -``` - -### Delete / erase -```bash -xcrun simctl erase # factory reset -xcrun simctl delete # permanently remove -xcrun simctl delete unavailable # clean up old sims -``` - -## Building and Deploying - -### Mac Catalyst -```bash -dotnet build -f net10.0-maccatalyst # build only -dotnet build -f net10.0-maccatalyst -t:Run # build + run -open path/to/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/AppName.app # run existing -``` - -### iOS Simulator -```bash -# Find UDID of booted simulator -UDID=$(xcrun simctl list devices booted -j | python3 -c " -import json,sys -d=json.load(sys.stdin) -for r in d['devices'].values(): - for dev in r: - if dev['state']=='Booted': print(dev['udid']); break -" 2>/dev/null | head -1) - -# Build and deploy -dotnet build -f net10.0-ios -t:Run -p:_DeviceName=:v2:udid=$UDID -``` - -The `-t:Run` target keeps the process alive while the app runs — it **blocks until the app exits**. -Always run in an async/background shell, then poll `maui-devflow MAUI status` to detect when the -app is ready. Do NOT wait for the process to finish. - -### Determining the correct TFM -Check the project file for ``: -```bash -grep -i TargetFramework *.csproj -``` -Common values: `net9.0-ios`, `net9.0-maccatalyst`, `net10.0-ios`, `net10.0-maccatalyst`. - -## Apple CLI Tool - -The `apple` command (from `appledev.tools` NuGet) provides higher-level wrappers. - -### Simulator commands -``` -apple simulator list [--booted|--available|--unavailable|--name "..."] -apple simulator create --device-type "..." [--runtime "..."] -apple simulator boot -apple simulator shutdown -apple simulator erase -apple simulator delete -apple simulator screenshot [--output path.png] -apple simulator app install -apple simulator app launch -apple simulator app uninstall -apple simulator open [] -apple simulator open-url -apple simulator logs [--filter "..."] -apple simulator push [--payload "..."] -apple simulator location set --lat --lon -apple simulator privacy grant -``` - -### Device commands -``` -apple device list -apple xcode list # installed Xcode versions -``` - -## xcrun simctl Reference - -Key subcommands beyond the basics: - -| Command | Use | -|---------|-----| -| `simctl addmedia file.jpg` | Add photos/videos to sim | -| `simctl openurl "url"` | Open URL / deep link | -| `simctl push bundle payload.json` | Simulate push notification | -| `simctl privacy grant location bundle` | Grant permissions | -| `simctl location set 37.33,-122.03` | Set GPS location | -| `simctl pbcopy ` | Copy stdin to clipboard | -| `simctl pbpaste ` | Read clipboard | -| `simctl get_app_container bundle` | App container path | -| `simctl listapps ` | Installed apps | - -## Troubleshooting - -- **Mac Catalyst blank/white screen after crash**: macOS shows a "reopen windows" dialog after - a crash, blocking the app from rendering. All MAUI elements appear as `[hidden] [disabled]` - with `-1x-1` sizes. Fix: clear saved state before launch: - ```bash - rm -rf ~/Library/Saved\ Application\ State/.savedState - ``` - Or detect and dismiss via AppleScript: - ```bash - osascript -e 'tell application "System Events" to tell process "AppName" to click button "Reopen" of window 1' - ``` -- **"Unable to lookup in current state: Shutdown"**: Simulator not booted. Run `xcrun simctl boot `. -- **Build error NETSDK1005 "Assets file doesn't have a target"**: Wrong TFM. Check - `` in .csproj and use matching version (e.g. `net10.0-ios` not `net9.0-ios`). -- **Agent not connecting after deploy**: The app may still be launching. Poll - `maui-devflow MAUI status` every few seconds. If it hasn't connected after ~60-90s, read the - async shell output from `dotnet build -t:Run` for build/launch errors. -- **Mac Catalyst app name vs binary name**: The `.app` bundle name may differ from the project - name (e.g. `MauiTodo.app` vs `SampleMauiApp`). Check the `ApplicationTitle` in .csproj. - Find the bundle: `find bin/Debug/net10.0-maccatalyst -name "*.app" -maxdepth 3` - -## Permission & Dialog Handling - -### Pre-grant permissions (prevents dialogs from appearing) -```bash -# Grant specific permission before the app requests it -xcrun simctl privacy grant location com.company.appid -xcrun simctl privacy grant camera com.company.appid -xcrun simctl privacy grant photos com.company.appid -xcrun simctl privacy grant contacts com.company.appid -xcrun simctl privacy grant microphone com.company.appid - -# Grant all permissions at once -xcrun simctl privacy grant all com.company.appid - -# Revoke (deny) a permission -xcrun simctl privacy revoke location com.company.appid - -# Reset (next request will show dialog again) -xcrun simctl privacy reset all com.company.appid - -# Via apple CLI -apple simulator privacy grant location com.company.appid -``` - -Available services: `all`, `calendar`, `contacts`, `contacts-limited`, `location`, `location-always`, `photos`, `photos-add`, `media-library`, `microphone`, `motion`, `reminders`, `siri`. - -### Using MauiDevFlow.Driver for permissions -```csharp -var driver = new iOSSimulatorAppDriver(); -driver.DeviceUdid = ""; -driver.BundleId = "com.company.appid"; - -// Pre-grant before running the app -await driver.GrantPermissionAsync(PermissionService.Location); -await driver.GrantPermissionAsync(PermissionService.Camera); - -// Reset to test the dialog flow -await driver.ResetPermissionAsync(PermissionService.Location); -``` - -### Detecting and dismissing alerts (accessibility tree + HID tap) -When a dialog appears unexpectedly (permission prompt, app alert, action sheet), the driver can -detect it via the iOS accessibility tree and tap a button to dismiss it: - -```csharp -// Check if an alert is currently showing -var alert = await driver.DetectAlertAsync(); -if (alert is not null) -{ - Console.WriteLine($"Alert: {alert.Title}"); - foreach (var btn in alert.Buttons) - Console.WriteLine($" Button: {btn.Label} at ({btn.CenterX},{btn.CenterY})"); -} - -// Dismiss by tapping the first "accept" button (Allow, OK, etc.) -await driver.DismissAlertAsync(); - -// Dismiss by tapping a specific button -await driver.DismissAlertAsync("Don't Allow"); - -// Convenience: detect + dismiss if present, no-op if not -await driver.HandleAlertIfPresentAsync(); -``` - -### Example workflow: permission dialog handling -``` -1. App requests location → system shows "Allow location?" dialog -2. Agent detects dialog via DetectAlertAsync() -3. Agent sees buttons: ["Allow While Using App", "Allow Once", "Don't Allow"] -4. Agent taps "Allow While Using App" via DismissAlertAsync("Allow While Using App") -5. App receives permission grant, continues normal flow -``` - -### Dialog test page in SampleMauiApp -The SampleMauiApp includes a **Dialogs** tab with buttons that trigger: -- **Permission dialogs**: Location, Camera, Photos, Contacts, Microphone, Notifications -- **App alerts**: OK-only, OK/Cancel, custom buttons (Delete/Keep) -- **Action sheets**: Multiple options with cancel/destructive -- **Prompt dialogs**: Text input with OK/Cancel - -Use these to test and validate dialog detection and dismissal workflows. - -## Dark Mode Testing - -### Toggle dark mode -```bash -# macOS (affects Mac Catalyst apps) -osascript -e 'tell application "System Events" to tell appearance preferences to set dark mode to true' -osascript -e 'tell application "System Events" to tell appearance preferences to set dark mode to false' - -# iOS Simulator -xcrun simctl ui appearance dark -xcrun simctl ui appearance light -``` - -### Verify dark mode via inspection -Use `maui-devflow` to verify colors without relying on screenshots: -```bash -maui-devflow MAUI property BackgroundColor # check MAUI element colors -maui-devflow cdp Runtime evaluate "window.matchMedia('(prefers-color-scheme: dark)').matches" # Blazor -``` +# iOS & Mac Catalyst Reference + +## Table of Contents +- [Simulator Management](#simulator-management) +- [Building and Deploying](#building-and-deploying) +- [Apple CLI Tool](#apple-cli-tool) +- [xcrun simctl Reference](#xcrun-simctl-reference) +- [Troubleshooting](#troubleshooting) + +## Simulator Management + +### Avoiding multi-project conflicts + +When multiple projects (or AI agents) may deploy to iOS simulators simultaneously, each +project should use its own dedicated simulator. Two apps deployed to the same simulator +will replace each other — only the last-deployed app survives. + +**Before creating or booting a simulator, check what's already in use:** +```bash +maui devflow list # shows agents with platform + port +xcrun simctl list devices booted # shows all booted simulators +``` + +If a booted simulator is already running another project's agent, create a new one: +```bash +xcrun simctl create "ProjectName-iPhone17Pro" "iPhone 17 Pro" "iOS 26.2" +# Use the returned UDID in your build command +``` + +**Naming convention:** Use `-` (e.g. `TodoApp-iPhone17Pro`) so +it's clear which simulator belongs to which project. + +### List simulators +```bash +xcrun simctl list devices # all devices by runtime +xcrun simctl list devices booted # only booted +xcrun simctl list devices available # only available +apple simulator list # formatted table +apple simulator list --booted # booted only +``` + +### Create simulator +```bash +# List available device types and runtimes first +xcrun simctl list devicetypes # e.g. "iPhone 16 Pro" +xcrun simctl list runtimes # e.g. "iOS 18.2" + +xcrun simctl create "My iPhone" "iPhone 16 Pro" "iOS 18.2" +apple simulator create "My iPhone" --device-type "iPhone 16 Pro" --runtime "iOS 18.2" +``` + +### Boot / shutdown +```bash +xcrun simctl boot +xcrun simctl shutdown +apple simulator boot +apple simulator shutdown +``` + +### Install and launch app +```bash +xcrun simctl install booted /path/to/App.app +xcrun simctl launch booted com.company.appid +``` + +### Screenshots (iOS Simulator) +```bash +xcrun simctl io booted screenshot output.png +apple simulator screenshot --output output.png +``` + +### Screenshots (Mac Catalyst) + +**Use `maui devflow ui screenshot`** for Mac Catalyst apps — it captures the UI in-process +and does NOT require the app to be in the foreground. Never use `osascript` to bring the window +to the front or `screencapture` for Mac Catalyst screenshots; they are unnecessary and unreliable. + +```bash +maui devflow ui screenshot --output screen.png +``` + +### Delete / erase +```bash +xcrun simctl erase # factory reset +xcrun simctl delete # permanently remove +xcrun simctl delete unavailable # clean up old sims +``` + +## Building and Deploying + +### Mac Catalyst + +**⚠️ Entitlements required:** Mac Catalyst apps are sandboxed by default and need the +`com.apple.security.network.server` entitlement for MAUI DevFlow's in-app HTTP server. +Without it, the agent fails to bind its port and the app may crash silently. + +**Quick fix (disable sandbox for Debug):** Create `Platforms/MacCatalyst/Entitlements.Debug.plist`: +```xml + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + +``` + +Then reference it in `.csproj` for Debug only: +```xml + + Platforms/MacCatalyst/Entitlements.Debug.plist + +``` + +If sandbox must stay enabled (e.g. testing App Store builds), add `network.server` explicitly. +See [setup.md Step 5](setup.md#5-mac-catalyst-entitlements) for the full sandbox-enabled plist. + +```bash +dotnet build -f net10.0-maccatalyst # build only +dotnet build -f net10.0-maccatalyst -t:Run # build + run +open path/to/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/AppName.app # run existing +``` + +### iOS Simulator +```bash +# Find UDID of booted simulator +UDID=$(xcrun simctl list devices booted -j | python3 -c " +import json,sys +d=json.load(sys.stdin) +for r in d['devices'].values(): + for dev in r: + if dev['state']=='Booted': print(dev['udid']); break +" 2>/dev/null | head -1) + +# Build and deploy +dotnet build -f net10.0-ios -t:Run -p:_DeviceName=:v2:udid=$UDID +``` + +The `-t:Run` target keeps the process alive while the app runs — it **blocks until the app exits**. +Always run in an async/background shell, then poll `maui devflow ui status` to detect when the +app is ready. Do NOT wait for the process to finish. + +### Determining the correct TFM +Check the project file for ``: +```bash +grep -i TargetFramework *.csproj +``` +Common values: `net9.0-ios`, `net9.0-maccatalyst`, `net10.0-ios`, `net10.0-maccatalyst`. + +## Apple CLI Tool + +The `apple` command (from `appledev.tools` NuGet) provides higher-level wrappers. + +### Simulator commands +``` +apple simulator list [--booted|--available|--unavailable|--name "..."] +apple simulator create --device-type "..." [--runtime "..."] +apple simulator boot +apple simulator shutdown +apple simulator erase +apple simulator delete +apple simulator screenshot [--output path.png] +apple simulator app install +apple simulator app launch +apple simulator app uninstall +apple simulator open [] +apple simulator open-url +apple simulator logs [--filter "..."] +apple simulator push [--payload "..."] +apple simulator location set --lat --lon +apple simulator privacy grant +``` + +### Device commands +``` +apple device list +apple xcode list # installed Xcode versions +``` + +## xcrun simctl Reference + +Key subcommands beyond the basics: + +| Command | Use | +|---------|-----| +| `simctl addmedia file.jpg` | Add photos/videos to sim | +| `simctl openurl "url"` | Open URL / deep link | +| `simctl push bundle payload.json` | Simulate push notification | +| `simctl privacy grant location bundle` | Grant permissions | +| `simctl location set 37.33,-122.03` | Set GPS location | +| `simctl pbcopy ` | Copy stdin to clipboard | +| `simctl pbpaste ` | Read clipboard | +| `simctl get_app_container bundle` | App container path | +| `simctl listapps ` | Installed apps | + +## Troubleshooting + +- **Mac Catalyst blank/white screen after crash**: macOS shows a "reopen windows" dialog after + a crash, blocking the app from rendering. All MAUI elements appear as `[hidden] [disabled]` + with `-1x-1` sizes. Fix: clear saved state before launch: + ```bash + rm -rf ~/Library/Saved\ Application\ State/.savedState + ``` + If the "Reopen windows?" dialog is already on screen, ask the user to dismiss it manually, + then relaunch. Do not use AppleScript here by default — it steals focus from the user's + desktop session. +- **"Unable to lookup in current state: Shutdown"**: Simulator not booted. Run `xcrun simctl boot `. +- **Build error NETSDK1005 "Assets file doesn't have a target"**: Wrong TFM. Check + `` in .csproj and use matching version (e.g. `net10.0-ios` not `net9.0-ios`). +- **Agent not connecting after deploy**: The app may still be launching. Poll + `maui devflow ui status` every few seconds. If it hasn't connected after ~60-90s, read the + async shell output from `dotnet build -t:Run` for build/launch errors. +- **Mac Catalyst app name vs binary name**: The `.app` bundle name may differ from the project + name (e.g. `MauiTodo.app` vs `SampleMauiApp`). Check the `ApplicationTitle` in .csproj. + Find the bundle: `find bin/Debug/net10.0-maccatalyst -name "*.app" -maxdepth 3` + +## Permission & Dialog Handling + +### Pre-grant permissions (prevents dialogs from appearing) +```bash +# Grant specific permission before the app requests it +xcrun simctl privacy grant location com.company.appid +xcrun simctl privacy grant camera com.company.appid +xcrun simctl privacy grant photos com.company.appid +xcrun simctl privacy grant contacts com.company.appid +xcrun simctl privacy grant microphone com.company.appid + +# Grant all permissions at once +xcrun simctl privacy grant all com.company.appid + +# Revoke (deny) a permission +xcrun simctl privacy revoke location com.company.appid + +# Reset (next request will show dialog again) +xcrun simctl privacy reset all com.company.appid + +# Via apple CLI +apple simulator privacy grant location com.company.appid +``` + +Available services: `all`, `calendar`, `contacts`, `contacts-limited`, `location`, `location-always`, `photos`, `photos-add`, `media-library`, `microphone`, `motion`, `reminders`, `siri`. + +### Using MAUI DevFlow Driver for permissions +```csharp +var driver = new iOSSimulatorAppDriver(); +driver.DeviceUdid = ""; +driver.BundleId = "com.company.appid"; + +// Pre-grant before running the app +await driver.GrantPermissionAsync(PermissionService.Location); +await driver.GrantPermissionAsync(PermissionService.Camera); + +// Reset to test the dialog flow +await driver.ResetPermissionAsync(PermissionService.Location); +``` + +### Detecting and dismissing alerts (accessibility tree + HID tap) +When a dialog appears unexpectedly (permission prompt, app alert, action sheet), the driver can +detect it via the iOS accessibility tree and tap a button to dismiss it: + +```csharp +// Check if an alert is currently showing +var alert = await driver.DetectAlertAsync(); +if (alert is not null) +{ + Console.WriteLine($"Alert: {alert.Title}"); + foreach (var btn in alert.Buttons) + Console.WriteLine($" Button: {btn.Label} at ({btn.CenterX},{btn.CenterY})"); +} + +// Dismiss by tapping the first "accept" button (Allow, OK, etc.) +await driver.DismissAlertAsync(); + +// Dismiss by tapping a specific button +await driver.DismissAlertAsync("Don't Allow"); + +// Convenience: detect + dismiss if present, no-op if not +await driver.HandleAlertIfPresentAsync(); +``` + +### Example workflow: permission dialog handling +``` +1. App requests location → system shows "Allow location?" dialog +2. Agent detects dialog via DetectAlertAsync() +3. Agent sees buttons: ["Allow While Using App", "Allow Once", "Don't Allow"] +4. Agent taps "Allow While Using App" via DismissAlertAsync("Allow While Using App") +5. App receives permission grant, continues normal flow +``` + +### Dialog test page in SampleMauiApp +The SampleMauiApp includes a **Dialogs** tab with buttons that trigger: +- **Permission dialogs**: Location, Camera, Photos, Contacts, Microphone, Notifications +- **App alerts**: OK-only, OK/Cancel, custom buttons (Delete/Keep) +- **Action sheets**: Multiple options with cancel/destructive +- **Prompt dialogs**: Text input with OK/Cancel + +Use these to test and validate dialog detection and dismissal workflows. + +## Dark Mode Testing + +### Toggle dark mode +```bash +# Preferred when available: use an in-app theme toggle so the host desktop is unaffected. +# +# iOS Simulator (safe: affects the simulator only) +xcrun simctl ui appearance dark +xcrun simctl ui appearance light +``` + +For **Mac Catalyst**, changing system appearance affects the user's entire macOS desktop. Only do +that with explicit user approval; otherwise prefer app-level theme controls and verify via +`maui devflow ui property` / WebView inspection. + +### Verify dark mode via inspection +Use `maui devflow` to verify colors without relying on screenshots: +```bash +maui devflow ui property BackgroundColor # check MAUI element colors +maui devflow webview Runtime evaluate "window.matchMedia('(prefers-color-scheme: dark)').matches" # Blazor +``` diff --git a/.claude/skills/maui-devflow-debug/references/linux.md b/.claude/skills/maui-devflow-debug/references/linux.md new file mode 100644 index 00000000..e6feabd4 --- /dev/null +++ b/.claude/skills/maui-devflow-debug/references/linux.md @@ -0,0 +1,172 @@ +# Linux / GTK Platform Guide + +Platform-specific setup and usage for .NET MAUI apps running on Linux via Maui.Gtk (GTK4). + +## Overview + +Maui.Gtk apps target `net10.0` (not a platform-specific TFM like `net10.0-ios`) and use +GTK4 via GirCore bindings. MAUI DevFlow provides dedicated Linux packages that work with +this architecture. + +## NuGet Packages + +| Package | Purpose | +|---------|---------| +| `Microsoft.Maui.DevFlow.Agent.Gtk` | In-app agent (visual tree, screenshots, tapping, logging) | +| `Microsoft.Maui.DevFlow.Blazor.Gtk` | CDP bridge for WebKitGTK BlazorWebView | + +These replace `Microsoft.Maui.DevFlow.Agent` and `Microsoft.Maui.DevFlow.Blazor` which target +standard MAUI platforms (iOS, Android, macCatalyst, Windows). + +```xml + + + + + +``` + +## Registration + +### MauiProgram.cs + +```csharp +using Microsoft.Maui.DevFlow.Agent.Gtk; +using Microsoft.Maui.DevFlow.Blazor.Gtk; // Blazor Hybrid only + +var builder = MauiApp.CreateBuilder(); +// ... your existing setup ... + +#if DEBUG +builder.AddMauiDevFlowAgent(); +builder.AddMauiBlazorDevFlowTools(); // Blazor Hybrid only +#endif +``` + +### Application Startup + +The agent must be started after the MAUI Application is available. In your GTK app +startup (e.g., `GtkMauiApplication.OnActivate` or equivalent): + +```csharp +#if DEBUG +app.StartDevFlowAgent(); + +// For Blazor Hybrid, wire CDP to the agent: +var blazorService = app.Handler?.MauiContext?.Services + .GetService(); +blazorService?.WireBlazorCdpToAgent(); +#endif +``` + +## Building and Running + +Linux/GTK apps use `dotnet run` (not `dotnet build -t:Run` which is MAUI-specific): + +```bash +# Build and run (in background/async shell) +dotnet run --project + +# Build only +dotnet build +``` + +Build times are typically fast (~5-10s) since there's no device deployment step. + +## Network Setup + +**No special setup needed.** Linux apps run directly on localhost — the CLI connects +directly to `http://localhost:`. No port forwarding (unlike Android) or entitlements +(unlike Mac Catalyst) required. + +## Key Simulation + +The `LinuxAppDriver` automatically detects the display server and uses the appropriate +**driver-mediated** key simulation backend. This is an implementation detail for Linux +automation support, **not** a recommendation for an AI agent to invoke these tools directly +from the shell. Prefer `maui devflow ui fill`, `maui devflow ui tap`, and `maui devflow batch` +for normal interaction. + +- **X11 sessions**: Uses `xdotool` (human-readable key names, no daemon needed) +- **Wayland sessions**: Uses `ydotool` (Linux input event keycodes, requires `ydotoold` daemon) + +Detection uses `XDG_SESSION_TYPE` and `WAYLAND_DISPLAY` environment variables. If the +preferred tool isn't installed, it falls back to whichever is available. + +### Installing xdotool (X11) + +```bash +sudo apt install xdotool # Debian/Ubuntu +sudo dnf install xdotool # Fedora +``` + +### Installing ydotool (Wayland) + +```bash +sudo apt install ydotool # Debian/Ubuntu +sudo dnf install ydotool # Fedora +``` + +**Required setup for ydotool** (to run without root): + +```bash +# Add your user to the input group for /dev/uinput access +sudo usermod -aG input $USER + +# Create udev rule for persistent permissions +echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-uinput.rules +sudo udevadm control --reload-rules && sudo udevadm trigger + +# Log out and back in, then start the daemon +ydotoold & +``` + +Key simulation is used by the driver for alert dismissal and keyboard input. +Only the driver backend should reach for `xdotool` or `ydotool`. + +## Platform Differences + +| Feature | Standard MAUI | Linux/GTK | +|---------|--------------|-----------| +| NuGet packages | `Agent`, `Blazor` | `Agent.Gtk`, `Blazor.Gtk` | +| TFM | `net10.0-` | `net10.0` | +| Build command | `dotnet build -f $TFM -t:Run` | `dotnet run --project ` | +| Agent startup | Automatic (lifecycle hook) | Manual (`app.StartDevFlowAgent()`) | +| Network | Varies by platform | Direct localhost | +| Screenshots | `VisualDiagnostics` | GTK `WidgetPaintable` → `Texture.SaveToPng()` | +| Native tap | Platform gesture system | `Gtk.Widget.Activate()` | +| Key simulation | Driver-mediated backend | `xdotool` (X11) / `ydotool` (Wayland) | +| Screen recording | Platform-specific | `ffmpeg` with `x11grab` (X11) / `pipewire` (Wayland) | +| Blazor WebView | WKWebView / WebView2 / Chrome | WebKitGTK 6.0 | + +## Troubleshooting + +### Agent Not Starting + +1. Ensure `app.StartDevFlowAgent()` is called after the app is activated +2. Check that `Application.Current` is available when `StartDevFlowAgent()` runs +3. Verify the port isn't in use: `lsof -i :` or `ss -tlnp | grep ` + +### xdotool / ydotool Not Working + +- On Wayland, `xdotool` does not work — install `ydotool` and start `ydotoold` +- On X11, `xdotool` is preferred over `ydotool` (simpler, no daemon) +- Prefer DevFlow commands over direct key injection wherever possible +- If `ydotool` fails silently, check that `ydotoold` daemon is running: `pgrep -x ydotoold` +- If `ydotool` gives permission errors, ensure your user is in the `input` group and `/dev/uinput` is group-writable +- Ensure the app window has focus for key events +- Check `XDG_SESSION_TYPE` to verify which display server is active: `echo $XDG_SESSION_TYPE` + +### Screen Recording on Wayland + +- Wayland screen recording uses `ffmpeg -f pipewire` instead of `x11grab` +- Requires PipeWire to be installed and running (standard on modern Wayland desktops) +- Check ffmpeg PipeWire support: `ffmpeg -devices | grep pipewire` +- If PipeWire is not available, you can force X11 with `GDK_BACKEND=x11` and use `x11grab` +- The first recording on Wayland may trigger a system permission dialog for screen sharing + +### WebKitGTK CDP Issues + +- WebKitGTK uses `EvaluateJavascriptAsync` for JS evaluation +- The same two-eval CDP pattern (send + poll) applies as other platforms +- Check that `chobitsu.js` is properly loaded in the WebView diff --git a/.claude/skills/maui-ai-debugging/references/macos.md b/.claude/skills/maui-devflow-debug/references/macos.md similarity index 88% rename from .claude/skills/maui-ai-debugging/references/macos.md rename to .claude/skills/maui-devflow-debug/references/macos.md index 72883989..f2e777d7 100644 --- a/.claude/skills/maui-ai-debugging/references/macos.md +++ b/.claude/skills/maui-devflow-debug/references/macos.md @@ -1,205 +1,205 @@ -# macOS (AppKit) Platform Guide - -Platform-specific setup and usage for .NET MAUI apps running on macOS via Platform.Maui.MacOS (AppKit). - -## Table of Contents -- [Overview](#overview) -- [Project Structure](#project-structure) -- [NuGet Packages](#nuget-packages) -- [Registration](#registration) -- [Building and Running](#building-and-running) -- [Blazor Hybrid](#blazor-hybrid) -- [Platform Differences](#platform-differences) -- [Troubleshooting](#troubleshooting) - -## Overview - -macOS (AppKit) apps use the community `Platform.Maui.MacOS` packages to run MAUI on native -AppKit (not Mac Catalyst). The TFM is `net10.0-macos`. Like Linux/GTK, macOS apps typically -use a **separate app head project** rather than adding `-macos` to the standard MAUI project's -TargetFrameworks. - -Detect macOS projects: -```bash -grep -i 'Platform\.Maui\.MacOS\|net.*-macos' *.csproj Directory.Build.props 2>/dev/null -``` - -## Project Structure - -macOS apps use a separate app head project (similar to Linux/GTK): - -``` -src/ -├── MyApp/ # Standard MAUI project (iOS, Android, Mac Catalyst, Windows) -├── MyApp.MacOS/ # macOS AppKit app head -│ ├── Program.cs # Entry point: MacOSMauiApplication -│ ├── MauiProgram.cs # macOS-specific builder (UseMauiAppMacOS, AddMacOSEssentials) -│ └── MyApp.MacOS.csproj # References Platform.Maui.MacOS packages -``` - -Shared source files (pages, view models, services) are typically linked from the main project. - -## NuGet Packages - -The app project needs the Platform.Maui.MacOS packages plus the standard MauiDevFlow packages: - -```xml - - - - - - - - - - -``` - -The standard `Redth.MauiDevFlow.Agent` and `Redth.MauiDevFlow.Blazor` packages include -`net10.0-macos` targets — no separate macOS-specific MauiDevFlow packages needed. - -## Registration - -### Program.cs (Entry Point) - -```csharp -using AppKit; -using Microsoft.Maui.Platform.MacOS; -using ObjCRuntime; - -namespace MyApp.MacOS; - -[Register("Program")] -public class Program : MacOSMauiApplication -{ - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); - - static void Main(string[] args) - { - NSApplication.Init(); - NSApplication.Main(args); - } -} -``` - -The `[Register]` attribute is required. - -### MauiProgram.cs - -```csharp -using Microsoft.Maui.Platform.MacOS; -using Microsoft.Maui.Platform.MacOS.Controls; - -#if DEBUG -using MauiDevFlow.Agent; -using MauiDevFlow.Blazor; -#endif - -public static class MauiProgram -{ - public static MauiApp CreateMauiApp() - { - var builder = MauiApp.CreateBuilder(); - builder - .UseMauiAppMacOS() // NOT UseMauiApp — macOS-specific - .AddMacOSEssentials() // REQUIRED — without this, no window appears - .AddMacOSBlazorWebView() // Blazor only - .ConfigureFonts(fonts => { /* ... */ }); - -#if DEBUG - builder.AddMauiDevFlowAgent(); - builder.AddMauiBlazorDevFlowTools(); // Blazor only -#endif - - return builder.Build(); - } -} -``` - -**Critical:** `AddMacOSEssentials()` is required — without it the app runs but no window appears. - -## Building and Running - -macOS apps do NOT use `-t:Run`. Build first, then launch with `open`: - -```bash -# Build -dotnet build -f net10.0-macos path/to/MyApp.MacOS - -# Find and launch the .app bundle -open path/to/MyApp.MacOS/bin/Debug/net10.0-macos/osx-arm64/AppName.app -``` - -**Code signing:** A clean `dotnet build` produces a valid ad-hoc signature. Do NOT manually -re-sign the app — it breaks the signature (SIGKILL on launch). If the app fails to launch, -clean rebuild: `rm -rf bin obj && dotnet build`. - -**Finding the .app bundle:** -```bash -find bin/Debug/net10.0-macos -name "*.app" -maxdepth 3 -``` - -## Network Setup - -**No special setup needed.** macOS apps run directly on localhost — the CLI connects -directly to `http://localhost:`. No port forwarding or entitlements required. - -## Blazor Hybrid - -Use `MacOSBlazorWebView` instead of the standard `BlazorWebView`: - -```csharp -using Microsoft.Maui.Platform.MacOS.Controls; - -// In page code-behind, replace BlazorWebView with MacOSBlazorWebView -var blazorWebView = new MacOSBlazorWebView(); -blazorWebView.HostPage = "wwwroot/index.html"; -blazorWebView.RootComponents.Add(new RootComponent { ... }); -``` - -Chobitsu.js is auto-injected via the Blazor JS module initializer — no manual ` -``` - -The library detects both approaches — manual script tags take priority over auto-injection. - -### What if it's not working? - -The library checks at runtime and logs a message: -``` -[BlazorDevFlow] ⚠️ No chobitsu script tag found. Auto-injection via JS initializer may not have run. -``` - -### How the file gets there - -The `chobitsu.js` file is included in the NuGet package as a static web asset. It is -automatically available at the root of your app's `wwwroot/` — no `.targets` file copying, -no manual downloads. It works in both Debug and Release builds (though MauiDevFlow itself -should only be referenced in Debug configurations). - -## 5. Mac Catalyst: Entitlements - -Mac Catalyst apps need the `com.apple.security.network.server` entitlement to allow the -agent and CDP servers to bind ports. Without this, the app will crash or fail silently. - -### Option A: Sandbox disabled (simpler for development) - -Create or update `Platforms/MacCatalyst/Entitlements.plist` for Debug builds: - -```xml - - - - - com.apple.security.app-sandbox - - com.apple.security.network.client - - - -``` - -### Option B: Sandbox enabled (required for App Store) - -```xml - - - - - com.apple.security.app-sandbox - - com.apple.security.network.client - - com.apple.security.network.server - - - -``` - -Reference in your `.csproj` (Debug only, so Release uses the default entitlements): - -```xml - - Platforms/MacCatalyst/Entitlements.Debug.plist - -``` - -**Avoiding TCC permission dialogs:** Even with sandbox disabled, macOS prompts for access to -`~/Documents`, `~/Downloads`, `~/Desktop`, and dotfiles in `~/` on every rebuild (ad-hoc signing -changes the code signature each build). To avoid this, store app data in -`Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)` (`~/Library/Application Support/`) -instead of the home directory root. This path is not TCC-protected. - -## 6. Android: Port Forwarding - -After deploying to an Android emulator, set up port forwarding for the broker and agent: - -```bash -adb reverse tcp:19223 tcp:19223 # Broker (lets agent register with host broker) -adb forward tcp: tcp: # Agent (lets CLI reach agent — get port from `maui-devflow list`) -``` - -The broker reverse (`tcp:19223`) is needed so the agent inside the emulator can connect to -the host's broker daemon. Set this up once per emulator session. - -The agent forward uses the port shown in `maui-devflow list` after the agent registers -(range 10223–10899). - -**Fallback (no broker):** If using direct mode with a `.mauidevflow` config file: -```bash -adb reverse tcp:9223 tcp:9223 # Direct agent port (single port for Agent + CDP) -``` - -## 7. Verify Setup - -After building and running the app: - -```bash -maui-devflow list # Should show registered agents (via broker) -maui-devflow MAUI status # Should show agent info, platform, app name -maui-devflow cdp status # Should show "Connected" (Blazor Hybrid only) -``` - -If status commands fail: -- **Broker not running?** `maui-devflow broker status` — CLI auto-starts the broker, but check if it's healthy -- **Agent not registered?** `maui-devflow list` — wait a few seconds for the agent to register -- **Mac Catalyst:** Check entitlements (Step 5) -- **macOS (AppKit):** Ensure `AddMacOSEssentials()` is called — see [references/macos.md](macos.md) -- **Android:** Check port forwarding (Step 6) — need both `adb reverse tcp:19223` and `adb forward tcp:` -- **iOS Simulator:** Should work without extra config -- **Linux/GTK:** Should work without extra config — runs directly on localhost -- **All platforms:** Ensure the app is running and the `#if DEBUG` block is active -- **Port conflict:** Check if another process holds the port: `lsof -i :9223` (or your configured port) -- **Wrong port:** Use `maui-devflow list` to find the assigned port, or ensure CLI is run from the project directory - -## Quick Checklist - -For an AI agent setting up MauiDevFlow in a new project: - -1. [ ] `Redth.MauiDevFlow.Agent` NuGet package added (or `Redth.MauiDevFlow.Agent.Gtk` for Linux) -2. [ ] `Redth.MauiDevFlow.Blazor` NuGet package added (Blazor Hybrid only; or `Redth.MauiDevFlow.Blazor.Gtk` for Linux) -3. [ ] `builder.AddMauiDevFlowAgent(...)` in MauiProgram.cs inside `#if DEBUG` -4. [ ] `builder.AddMauiBlazorDevFlowTools(...)` in MauiProgram.cs (Blazor Hybrid only) -5. [ ] Chobitsu auto-injected via JS initializer (Blazor Hybrid — no manual step needed) -6. [ ] Mac Catalyst entitlements include `network.server` (Mac Catalyst only) -7. [ ] `adb reverse tcp:19223` for broker + `adb forward tcp:` for agent (Android only) -8. [ ] Linux/GTK: `app.StartDevFlowAgent()` called after app activation -9. [ ] macOS (AppKit): `UseMauiAppMacOS()`, `AddMacOSEssentials()`, `MacOSBlazorWebView` — see [macos.md](macos.md) -10. [ ] Verify with `maui-devflow list` and `maui-devflow MAUI status` - -## Checking for Updates - -At the start of each session (or periodically), check whether the CLI, skill, and NuGet -packages are up to date. Outdated components can cause confusing failures or missing features. - -### Check CLI version -```bash -maui-devflow --version -dotnet tool search Redth.MauiDevFlow.CLI | head -5 -``` - -If a newer version is available: -```bash -dotnet tool update --global Redth.MauiDevFlow.CLI -``` - -### Update the skill -```bash -# Check if the skill is up to date (compares local commit SHA against remote) -maui-devflow skill-version - -# Download the latest skill files from GitHub -maui-devflow update-skill -``` - -The `update-skill` command writes a `.skill-version` file tracking the installed commit SHA. -The `skill-version` command reads this file and compares against the latest remote commit. - -**AI agents should check at session start:** If `.claude/skills/maui-ai-debugging/.skill-version` -exists, run `maui-devflow skill-version` to see if an update is available. If the remote SHA -differs from the installed SHA, ask the user if they'd like to update before proceeding. - -### Check NuGet packages in the project -```bash -grep -i 'Redth.MauiDevFlow' *.csproj Directory.Build.props Directory.Packages.props 2>/dev/null -``` - -If packages are outdated: -```bash -dotnet add package Redth.MauiDevFlow.Agent -dotnet add package Redth.MauiDevFlow.Blazor # only if Blazor Hybrid -# For Linux/GTK: use .Gtk variants instead -``` - -### Re-run setup verification -After any updates, walk through the checklist above to ensure everything is still properly -configured. A CLI update may introduce new setup requirements. +# Setup & Installation + +Complete guide for integrating MAUI DevFlow into a .NET MAUI app. + +## Table of Contents +- [Install CLI Tools](#1-install-cli-tools) +- [Add NuGet Packages](#2-add-nuget-packages) +- [Register in MauiProgram.cs](#3-register-in-mauiprogramcs) +- [Port Configuration](#3b-port-configuration) +- [Blazor Hybrid Setup](#4-blazor-hybrid-chobitsu-auto-injection) +- [Mac Catalyst Entitlements](#5-mac-catalyst-entitlements) +- [Android Port Forwarding](#6-android-port-forwarding) +- [Verify Setup](#7-verify-setup) +- [Checking for Updates](#checking-for-updates) + +## 1. Install CLI Tools + +```bash +dotnet tool install --global Microsoft.Maui.Cli --prerelease +dotnet tool install --global androidsdk.tool # android (Android only) +dotnet tool install --global appledev.tools # apple (iOS/Mac only) +``` + +Verify: `maui devflow version` + +## 2. Add NuGet Packages + +First, determine whether the project is a standard MAUI app or a Linux/GTK app. +There is no `-linux` TFM — Linux/GTK apps target plain `net10.0` (or `net9.0`) and use +the community `Maui.Gtk` package. Detect this by checking the `.csproj`: + +```bash +# Check for GTK indicators in the project +grep -i 'GirCore\|Maui\.Gtk\|Gtk-4\.0' *.csproj Directory.Build.props 2>/dev/null +``` + +If GTK/GirCore references are found, use the **Linux/GTK packages** below. +Otherwise, use the **standard MAUI packages**. + +### Standard MAUI Apps (iOS, Android, Mac Catalyst, Windows, macOS) + +Add to your MAUI app's `.csproj`: + +```xml + + + + + +``` + +- `Microsoft.Maui.DevFlow.Agent` — Required for all MAUI apps (iOS, Android, Mac Catalyst, Windows, macOS AppKit). Provides the in-app agent + for visual tree inspection, screenshots, tapping, filling text, etc. +- `Microsoft.Maui.DevFlow.Blazor` — Required for Blazor Hybrid apps. Provides the CDP bridge + for DOM inspection, JavaScript evaluation, and Blazor debugging. + +**macOS (AppKit) apps** also need the `Platform.Maui.MacOS` packages — see [references/macos.md](macos.md) +for the full project setup including entry point, builder configuration, and BlazorWebView differences. + +### Linux/GTK Apps + +Linux/GTK apps (using Maui.Gtk) use separate packages: + +```xml + + + + + +``` + +- `Microsoft.Maui.DevFlow.Agent.Gtk` — Agent for Linux/GTK apps. Uses GirCore.Gtk-4.0 for native GTK integration. +- `Microsoft.Maui.DevFlow.Blazor.Gtk` — CDP bridge for WebKitGTK-based BlazorWebView on Linux. + +## 3. Register in MauiProgram.cs + +```csharp +using Microsoft.Maui.DevFlow.Agent; +using Microsoft.Maui.DevFlow.Blazor; // Blazor Hybrid only + +var builder = MauiApp.CreateBuilder(); +// ... your existing setup ... + +#if DEBUG +builder.Services.AddBlazorWebViewDeveloperTools(); // Blazor Hybrid only +builder.AddMauiDevFlowAgent(); +builder.AddMauiBlazorDevFlowTools(); // Blazor Hybrid only +#endif +``` + +### Linux/GTK Registration + +For Linux/GTK apps, use the GTK-specific namespaces and add the agent startup call: + +```csharp +using Microsoft.Maui.DevFlow.Agent.Gtk; +using Microsoft.Maui.DevFlow.Blazor.Gtk; // Blazor Hybrid only + +var builder = MauiApp.CreateBuilder(); +// ... your existing setup ... + +#if DEBUG +builder.AddMauiDevFlowAgent(); +builder.AddMauiBlazorDevFlowTools(); // Blazor Hybrid only +#endif +``` + +After the MAUI app is activated (e.g., in `OnActivate` or after `Application.Current` is available): + +```csharp +#if DEBUG +app.StartDevFlowAgent(); +// For Blazor, wire CDP to agent: +var blazorService = app.Handler?.MauiContext?.Services.GetService(); +blazorService?.WireBlazorCdpToAgent(); +#endif +``` + +**Agent options:** +- `Port` — HTTP port for the agent REST API (default: 9223). Also configurable via `.mauidevflow` or `-p:MauiDevFlowPort=XXXX`. +- `Enabled` — Enable/disable the agent (default: true) +- `MaxTreeDepth` — Max depth for visual tree queries, 0 = unlimited (default: 0) + +## 3b. Port Configuration + +**Automatic (via broker):** The CLI includes a broker daemon that automatically assigns +ports to agents. No manual port configuration is needed — the broker handles it. The CLI +auto-starts the broker on first use. See the main SKILL.md for details on the broker. + +**Manual fallback (.mauidevflow):** If the broker isn't available, create a `.mauidevflow` +file in the project directory to set an explicit port: + +```json +{ + "port": 9347 +} +``` + +Both the MSBuild targets and the CLI read this file automatically: +- **Build**: `dotnet build -t:Run` — agent starts on the configured port +- **CLI**: `maui devflow ui status` — connects to the configured port (when run from project dir) + +**Port priority:** Explicit `--agent-port` > Broker discovery > `.mauidevflow` > default 9223. + +**How port discovery works:** When you run any `MAUI` or `cdp` command, the CLI: +1. Auto-starts the broker if not running +2. Queries the broker for agents matching the current project (`.csproj` in cwd) +3. If one agent matches → uses its port automatically +4. If multiple match → prints a disambiguation table to stderr +5. Falls back to `.mauidevflow` config file → default 9223 + +**Multiple apps simultaneously:** The broker assigns unique ports from range 10223–10899. +Use `maui devflow list` to see all agents, then target a specific one: +```bash +maui devflow ui status --agent-port 10224 # target specific agent +``` + +**Blazor options:** +- `Enabled` — Enable/disable CDP support (default: true) +- `EnableWebViewInspection` — Enable WebView inspection (default: true) +- `EnableLogging` — Log debug messages (default: true in DEBUG) + +## 4. Blazor Hybrid: Chobitsu Auto-Injection + +**No manual setup needed for Blazor Hybrid apps.** The `Microsoft.Maui.DevFlow.Blazor` NuGet package +automatically injects `chobitsu.js` (the CDP implementation) via a Blazor JS initializer. +Just add the NuGet package and register in `MauiProgram.cs` — that's it. + +### Fallback: Manual Script Tag + +If auto-injection doesn't work in your setup (e.g., older .NET versions), add this line +before `` in `wwwroot/index.html`: + +```html + +``` + +The library detects both approaches — manual script tags take priority over auto-injection. + +### What if it's not working? + +The library checks at runtime and logs a message: +``` +[BlazorDevFlow] ⚠️ No chobitsu script tag found. Auto-injection via JS initializer may not have run. +``` + +### How the file gets there + +The `chobitsu.js` file is included in the NuGet package as a static web asset. It is +automatically available at the root of your app's `wwwroot/` — no `.targets` file copying, +no manual downloads. It works in both Debug and Release builds (though MAUI DevFlow itself +should only be referenced in Debug configurations). + +## 5. Mac Catalyst: Entitlements + +Mac Catalyst apps need the `com.apple.security.network.server` entitlement to allow the +agent and CDP servers to bind ports. Without this, the app will crash or fail silently. + +### Option A: Sandbox disabled (simpler for development) + +Create or update `Platforms/MacCatalyst/Entitlements.plist` for Debug builds: + +```xml + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + +``` + +### Option B: Sandbox enabled (required for App Store) + +```xml + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + + +``` + +Reference in your `.csproj` (Debug only, so Release uses the default entitlements): + +```xml + + Platforms/MacCatalyst/Entitlements.Debug.plist + +``` + +**Avoiding TCC permission dialogs:** Even with sandbox disabled, macOS prompts for access to +`~/Documents`, `~/Downloads`, `~/Desktop`, and dotfiles in `~/` on every rebuild (ad-hoc signing +changes the code signature each build). To avoid this, store app data in +`Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)` (`~/Library/Application Support/`) +instead of the home directory root. This path is not TCC-protected. + +## 6. Android: Port Forwarding + +After deploying to an Android emulator, set up port forwarding for the broker and agent: + +```bash +adb reverse tcp:19223 tcp:19223 # Broker (lets agent register with host broker) +adb forward tcp: tcp: # Agent (lets CLI reach agent — get port from `maui devflow list`) +``` + +The broker reverse (`tcp:19223`) is needed so the agent inside the emulator can connect to +the host's broker daemon. Set this up once per emulator session. + +The agent forward uses the port shown in `maui devflow list` after the agent registers +(range 10223–10899). + +**Fallback (no broker):** If using direct mode with a `.mauidevflow` config file: +```bash +adb forward tcp:9223 tcp:9223 # Direct agent port (single port for Agent + CDP) +``` + +## 7. Verify Setup + +After building and running the app: + +```bash +maui devflow list # Should show registered agents (via broker) +maui devflow ui status # Should show agent info, platform, app name +maui devflow webview status # Should show "Connected" (Blazor Hybrid only) +``` + +If status commands fail: +- **Broker not running?** `maui devflow broker status` — CLI auto-starts the broker, but check if it's healthy +- **Agent not registered?** `maui devflow list` — wait a few seconds for the agent to register +- **Mac Catalyst:** Check entitlements (Step 5) +- **macOS (AppKit):** Ensure `AddMacOSEssentials()` is called — see [references/macos.md](macos.md) +- **Android:** Check port forwarding (Step 6) — need both `adb reverse tcp:19223` and `adb forward tcp:` +- **iOS Simulator:** Should work without extra config +- **Linux/GTK:** Should work without extra config — runs directly on localhost +- **All platforms:** Ensure the app is running and the `#if DEBUG` block is active +- **Port conflict:** Check if another process holds the port: `lsof -i :9223` (or your configured port) +- **Wrong port:** Use `maui devflow list` to find the assigned port, or ensure CLI is run from the project directory + +## Quick Checklist + +For an AI agent setting up MAUI DevFlow in a new project: + +1. [ ] `Microsoft.Maui.DevFlow.Agent` NuGet package added (or `Microsoft.Maui.DevFlow.Agent.Gtk` for Linux) +2. [ ] `Microsoft.Maui.DevFlow.Blazor` NuGet package added (Blazor Hybrid only; or `Microsoft.Maui.DevFlow.Blazor.Gtk` for Linux) +3. [ ] `builder.AddMauiDevFlowAgent(...)` in MauiProgram.cs inside `#if DEBUG` +4. [ ] `builder.AddMauiBlazorDevFlowTools(...)` in MauiProgram.cs (Blazor Hybrid only) +5. [ ] Chobitsu auto-injected via JS initializer (Blazor Hybrid — no manual step needed) +6. [ ] Mac Catalyst entitlements include `network.server` (Mac Catalyst only) +7. [ ] `adb reverse tcp:19223` for broker + `adb forward tcp:` for agent (Android only) +8. [ ] Linux/GTK: `app.StartDevFlowAgent()` called after app activation +9. [ ] macOS (AppKit): `UseMauiAppMacOS()`, `AddMacOSEssentials()`, `MacOSBlazorWebView` — see [macos.md](macos.md) +10. [ ] Verify with `maui devflow list` and `maui devflow ui status` + +## Checking for Updates + +At the start of each session (or periodically), check whether the CLI, skill, and NuGet +packages are up to date. Outdated components can cause confusing failures or missing features. + +### Check CLI version +```bash +maui devflow version +dotnet tool search Microsoft.Maui.Cli | head -5 +``` + +If a newer version is available: +```bash +dotnet tool update --global Microsoft.Maui.Cli +``` + +### Update the skill +```bash +maui devflow skills check +maui devflow skills update +``` + +The skills manager compares installed files against the skills bundled in the running +`Microsoft.Maui.Cli` and records local install state under `~/.maui/devflow`. + +**AI agents should check at session start:** run `maui devflow skills check`. If it reports +`update-available-from-current-cli`, ask the user if they want to run +`maui devflow skills update` before proceeding. + +### Check NuGet packages in the project +```bash +grep -i 'Microsoft.Maui.DevFlow' *.csproj Directory.Build.props Directory.Packages.props 2>/dev/null +``` + +If packages are outdated: +```bash +dotnet add package Microsoft.Maui.DevFlow.Agent +dotnet add package Microsoft.Maui.DevFlow.Blazor # only if Blazor Hybrid +# For Linux/GTK: use .Gtk variants instead +``` + +### Re-run setup verification +After any updates, walk through the checklist above to ensure everything is still properly +configured. A CLI update may introduce new setup requirements. diff --git a/.claude/skills/maui-ai-debugging/references/troubleshooting.md b/.claude/skills/maui-devflow-debug/references/troubleshooting.md similarity index 89% rename from .claude/skills/maui-ai-debugging/references/troubleshooting.md rename to .claude/skills/maui-devflow-debug/references/troubleshooting.md index 899632aa..685871de 100644 --- a/.claude/skills/maui-ai-debugging/references/troubleshooting.md +++ b/.claude/skills/maui-devflow-debug/references/troubleshooting.md @@ -1,93 +1,93 @@ -# Troubleshooting - -## Table of Contents -- [Connection Refused](#connection-refused--cannot-connect) -- [Build Failures](#build-failures) -- [CDP Not Connecting](#cdp-not-connecting-blazor-hybrid) -- [Mac Catalyst Permission Dialogs](#mac-catalyst-repeated-permission-dialogs-on-rebuild) - -## Connection Refused / Cannot Connect - -If `maui-devflow MAUI status` fails with connection refused: - -1. **App not running?** Verify the app launched: check the build output for errors. -2. **Check the broker:** Run `maui-devflow list` to see if the agent registered. If the list - is empty, the app may not have connected to the broker yet (wait a few seconds and retry). -3. **Wrong port?** If using `.mauidevflow`, ensure the port matches between build and CLI. - Run CLI from the project directory so it auto-detects the config file. -4. **Port already in use?** Another process may hold the port. Check with: - ```bash - lsof -i : # macOS/Linux - ``` - With the broker, this is less common since ports are auto-assigned. -5. **Android?** Did you run `adb reverse tcp:19223 tcp:19223` (for broker) and - `adb forward tcp: tcp:` (for agent)? Re-run after each deploy. -6. **Mac Catalyst?** Check entitlements include `network.server` (see setup.md step 5). -7. **macOS (AppKit)?** Ensure `AddMacOSEssentials()` is called and the app window appeared. - See [references/macos.md](macos.md) for troubleshooting. -8. **Linux/GTK?** No special network setup needed — runs directly on localhost. Check if the app started successfully. -9. **Broker issues?** `maui-devflow broker status` to check. `maui-devflow broker stop` then - retry (CLI will auto-restart it). - -## Build Failures - -**Missing workloads:** -``` -error NETSDK1147: To build this project, the following workloads must be installed: maui-ios -``` -Fix: `dotnet workload install maui` (installs all MAUI workloads). - -**SDK version mismatch:** -``` -error : The current .NET SDK does not support targeting .NET 10.0 -``` -Fix: Install the required .NET SDK version, or check `global.json` for version pins. - -**Android SDK not found:** -``` -error XA0000: Could not find Android SDK -``` -Fix: Install Android SDK via `android sdk install` or set `$ANDROID_HOME`. - -**iOS provisioning / signing errors:** -Fix: For simulators, ensure no signing is configured (default). For devices, set up provisioning -profiles via `apple appstoreconnect profiles list`. - -**General build failure recovery:** -1. `dotnet clean` then retry the build -2. Delete `bin/` and `obj/` directories: `rm -rf bin obj` then rebuild -3. Check the full build output (not just the last error) — earlier warnings often reveal the root cause - -## CDP Not Connecting (Blazor Hybrid) - -If `maui-devflow cdp status` fails but `MAUI status` works: - -1. **Chobitsu not loading?** Check logs for `[BlazorDevFlow]` messages. If auto-injection failed, add `` manually to `wwwroot/index.html` -2. **Blazor not initialized?** Navigate to a Blazor page first, then retry -3. Check app logs: `maui-devflow MAUI logs --limit 20` — look for `[BlazorDevFlow]` errors - -## Mac Catalyst: Repeated Permission Dialogs on Rebuild - -If macOS prompts "App would like to access your Documents folder" on every rebuild: - -**Cause:** TCC permissions are tied to the app's code signature. Ad-hoc Debug builds produce a -different signature each rebuild → macOS forgets the grant and re-prompts. This happens even -with App Sandbox disabled. - -**Fix:** Don't access TCC-protected directories (`~/Documents`, `~/Downloads`, `~/Desktop`, -or dotfiles like `~/.myapp/` in the home root) programmatically. Instead use: -- `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)` → `~/Library/Application Support/` (not TCC-protected) -- `NSOpenPanel`/`NSSavePanel` for user-initiated file access (grants automatic TCC exemption) - -If you can't avoid TCC paths, sign Debug builds with a stable Apple Development certificate -so the code signature stays consistent across rebuilds. - -## macOS (AppKit) Issues - -For detailed macOS (AppKit) troubleshooting, see [references/macos.md](macos.md#troubleshooting). - -Common issues: -- **No window appears** → Missing `AddMacOSEssentials()` in builder -- **SIGKILL on launch** → Don't re-sign manually; clean rebuild instead -- **Blazor stuck on "Loading..."** → Use `MacOSBlazorWebView`, not standard `BlazorWebView` -- **No sidebar content** → Add `MacOSShell.SetUseNativeSidebar(shell, true)` + `FlyoutBehavior.Locked` +# Troubleshooting + +## Table of Contents +- [Connection Refused](#connection-refused--cannot-connect) +- [Build Failures](#build-failures) +- [CDP Not Connecting](#cdp-not-connecting-blazor-hybrid) +- [Mac Catalyst Permission Dialogs](#mac-catalyst-repeated-permission-dialogs-on-rebuild) + +## Connection Refused / Cannot Connect + +If `maui devflow ui status` fails with connection refused: + +1. **App not running?** Verify the app launched: check the build output for errors. +2. **Check the broker:** Run `maui devflow list` to see if the agent registered. If the list + is empty, the app may not have connected to the broker yet (wait a few seconds and retry). +3. **Wrong port?** If using `.mauidevflow`, ensure the port matches between build and CLI. + Run CLI from the project directory so it auto-detects the config file. +4. **Port already in use?** Another process may hold the port. Check with: + ```bash + lsof -i : # macOS/Linux + ``` + With the broker, this is less common since ports are auto-assigned. +5. **Android?** Did you run `adb reverse tcp:19223 tcp:19223` (for broker) and + `adb forward tcp: tcp:` (for agent)? Re-run after each deploy. +6. **Mac Catalyst?** Check entitlements include `network.server` (see setup.md step 5). +7. **macOS (AppKit)?** Ensure `AddMacOSEssentials()` is called and the app window appeared. + See [references/macos.md](macos.md) for troubleshooting. +8. **Linux/GTK?** No special network setup needed — runs directly on localhost. Check if the app started successfully. +9. **Broker issues?** `maui devflow broker status` to check. `maui devflow broker stop` then + retry (CLI will auto-restart it). + +## Build Failures + +**Missing workloads:** +``` +error NETSDK1147: To build this project, the following workloads must be installed: maui-ios +``` +Fix: `dotnet workload install maui` (installs all MAUI workloads). + +**SDK version mismatch:** +``` +error : The current .NET SDK does not support targeting .NET 10.0 +``` +Fix: Install the required .NET SDK version, or check `global.json` for version pins. + +**Android SDK not found:** +``` +error XA0000: Could not find Android SDK +``` +Fix: Install Android SDK via `android sdk install` or set `$ANDROID_HOME`. + +**iOS provisioning / signing errors:** +Fix: For simulators, ensure no signing is configured (default). For devices, set up provisioning +profiles via `apple appstoreconnect profiles list`. + +**General build failure recovery:** +1. `dotnet clean` then retry the build +2. Delete `bin/` and `obj/` directories: `rm -rf bin obj` then rebuild +3. Check the full build output (not just the last error) — earlier warnings often reveal the root cause + +## CDP Not Connecting (Blazor Hybrid) + +If `maui devflow webview status` fails but `ui status` works: + +1. **Chobitsu not loading?** Check logs for `[BlazorDevFlow]` messages. If auto-injection failed, add `` manually to `wwwroot/index.html` +2. **Blazor not initialized?** Navigate to a Blazor page first, then retry +3. Check app logs: `maui devflow ui logs --limit 20` — look for `[BlazorDevFlow]` errors + +## Mac Catalyst: Repeated Permission Dialogs on Rebuild + +If macOS prompts "App would like to access your Documents folder" on every rebuild: + +**Cause:** TCC permissions are tied to the app's code signature. Ad-hoc Debug builds produce a +different signature each rebuild → macOS forgets the grant and re-prompts. This happens even +with App Sandbox disabled. + +**Fix:** Don't access TCC-protected directories (`~/Documents`, `~/Downloads`, `~/Desktop`, +or dotfiles like `~/.myapp/` in the home root) programmatically. Instead use: +- `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)` → `~/Library/Application Support/` (not TCC-protected) +- `NSOpenPanel`/`NSSavePanel` for user-initiated file access (grants automatic TCC exemption) + +If you can't avoid TCC paths, sign Debug builds with a stable Apple Development certificate +so the code signature stays consistent across rebuilds. + +## macOS (AppKit) Issues + +For detailed macOS (AppKit) troubleshooting, see [references/macos.md](macos.md#troubleshooting). + +Common issues: +- **No window appears** → Missing `AddMacOSEssentials()` in builder +- **SIGKILL on launch** → Don't re-sign manually; clean rebuild instead +- **Blazor stuck on "Loading..."** → Use `MacOSBlazorWebView`, not standard `BlazorWebView` +- **No sidebar content** → Add `MacOSShell.SetUseNativeSidebar(shell, true)` + `FlyoutBehavior.Locked` diff --git a/.claude/skills/maui-devflow-onboard/SKILL.md b/.claude/skills/maui-devflow-onboard/SKILL.md new file mode 100644 index 00000000..36b6ab76 --- /dev/null +++ b/.claude/skills/maui-devflow-onboard/SKILL.md @@ -0,0 +1,140 @@ +--- +name: maui-devflow-onboard +description: >- + Add MAUI DevFlow to a .NET MAUI project with agent package references, + MauiProgram.cs registration, Blazor WebView support, GTK variants, Central + Package Management guidance, and verification commands. USE FOR: first-time + DevFlow setup, reviewing what files to edit, choosing DevFlow packages, or + continuing after `maui devflow init` installs skills. DO NOT USE FOR: + troubleshooting an already-integrated app that cannot connect, iterative app + debugging, UI inspection, or generic MAUI build failures (use + maui-devflow-debug). INVOKES: maui devflow CLI and dotnet CLI. +--- + +# DevFlow Onboard + +Use this skill to add MAUI DevFlow to a project after `maui devflow init` has installed the DevFlow skills. + +## When to Use + +- The project has no `Microsoft.Maui.DevFlow.*` package references yet. +- The user asks how to onboard, initialize, install, integrate, or set up DevFlow. +- The agent needs to choose between standard, Blazor, GTK, or GTK + Blazor DevFlow packages. +- The repo uses Central Package Management and package edits need to be split correctly. +- `maui devflow init` has installed skills and the user asks for the next project edits. + +## Route Elsewhere + +- If package references and `AddMauiDevFlowAgent()` are already present but the CLI cannot connect, use `maui-devflow-debug`. +- If an agent is reachable and the user wants to inspect, tap, screenshot, or debug UI, use `maui-devflow-debug`. + +## Workflow + +1. Optionally run `maui devflow skills check` and update bundled skills before editing if it reports `update-available-from-current-cli`. +2. Find MAUI app projects in the workspace. Prefer app projects with `UseMaui`, platform TFMs such as `net*-android`/`net*-ios`/`net*-maccatalyst`/`net*-windows`, or GTK MAUI package references. +3. Determine whether each target project is standard MAUI, MAUI + Blazor WebView, GTK, or GTK + Blazor. +4. Add the correct DevFlow package references. Respect Central Package Management if `Directory.Packages.props` is present. +5. Register DevFlow in `MauiProgram.cs` inside `#if DEBUG`. +6. Build and run the app. +7. Verify with: + + ```bash + maui devflow diagnose + maui devflow wait + maui devflow ui tree --depth 1 + ``` + +If verification fails after integration, switch to `maui-devflow-debug` for connectivity recovery. + +## Stop Signals + +- Stop before editing if multiple MAUI app projects exist and the user has not indicated which one to onboard. +- Stop and ask before enabling DevFlow outside Debug builds. +- Stop after package/registration edits and verify with a build before doing runtime debugging. + +## Critical Anti-patterns + +- Do not add versions to project `PackageReference` items when `Directory.Packages.props` is managing package versions. +- Do not add Blazor DevFlow packages unless the app uses Blazor WebView. +- Do not register DevFlow outside `#if DEBUG` unless the user explicitly asks. +- Do not use the old `builder.Services.AddMauiDevFlowAgent()` pattern; use `builder.AddMauiDevFlowAgent()`. + +## Package Selection + +| Project flavor | Required packages | +| --- | --- | +| Standard MAUI | `Microsoft.Maui.DevFlow.Agent` | +| MAUI + Blazor WebView | `Microsoft.Maui.DevFlow.Agent`, `Microsoft.Maui.DevFlow.Blazor` | +| GTK MAUI | `Microsoft.Maui.DevFlow.Agent.Gtk` | +| GTK MAUI + Blazor WebView | `Microsoft.Maui.DevFlow.Agent.Gtk`, `Microsoft.Maui.DevFlow.Blazor.Gtk` | + +Blazor WebView indicators include a `Microsoft.AspNetCore.Components.WebView.Maui` package reference or `AddMauiBlazorWebView()` in `MauiProgram.cs`. + +GTK indicators include package references such as `Maui.Gtk`, `Platform.Maui.Linux.Gtk4`, `GirCore.Gtk-4.0`, or `Platform.Maui.Linux.Gtk4.BlazorWebView`. + +## Central Package Management + +If the repo uses `Directory.Packages.props`, put versions there and leave project `PackageReference` entries versionless. + +```xml + + +``` + +```xml + + +``` + +If the repo does not use Central Package Management, put the version on the `PackageReference`. + +## MauiProgram.cs Registration + +For standard MAUI: + +```csharp +using Microsoft.Maui.DevFlow.Agent; + +// inside CreateMauiApp(), before return builder.Build(); +#if DEBUG +builder.AddMauiDevFlowAgent(); +#endif +``` + +For MAUI + Blazor WebView: + +```csharp +using Microsoft.Maui.DevFlow.Agent; +using Microsoft.Maui.DevFlow.Blazor; + +// inside CreateMauiApp(), before return builder.Build(); +#if DEBUG +builder.AddMauiDevFlowAgent(); +builder.AddMauiBlazorDevFlowTools(); +#endif +``` + +For GTK, use the `.Gtk` namespaces and packages. GTK apps also need to start the agent after app activation, for example `app.StartDevFlowAgent()` in the platform app activation flow. + +For Mac Catalyst, ensure the Debug entitlements allow the in-app HTTP server: + +```xml +com.apple.security.network.server + +``` + +## Validation Checklist + +- `MauiProgram.cs` registers DevFlow only in Debug builds. +- The app project references the package flavor that matches the target platform. +- Blazor DevFlow tools are added only when the app uses Blazor WebView. +- GTK apps start the DevFlow agent after app activation. +- Mac Catalyst Debug entitlements include `com.apple.security.network.server`. +- `dotnet build` succeeds. +- A running app appears in `maui devflow list`. +- `maui devflow ui tree --depth 1` returns a visual tree. + +## References + +- See `references/package-selection.md` for package/flavor details. +- See `references/mauiprogram-registration.md` for registration patterns. diff --git a/.claude/skills/maui-devflow-onboard/references/mauiprogram-registration.md b/.claude/skills/maui-devflow-onboard/references/mauiprogram-registration.md new file mode 100644 index 00000000..70db0b3e --- /dev/null +++ b/.claude/skills/maui-devflow-onboard/references/mauiprogram-registration.md @@ -0,0 +1,34 @@ +# MauiProgram.cs Registration + +Add DevFlow registration in `CreateMauiApp()` before `return builder.Build();`. + +Standard MAUI: + +```csharp +using Microsoft.Maui.DevFlow.Agent; + +#if DEBUG +builder.AddMauiDevFlowAgent(); +#endif +``` + +MAUI + Blazor WebView: + +```csharp +using Microsoft.Maui.DevFlow.Agent; +using Microsoft.Maui.DevFlow.Blazor; + +#if DEBUG +builder.AddMauiDevFlowAgent(); +builder.AddMauiBlazorDevFlowTools(); +#endif +``` + +GTK uses the `.Gtk` namespaces: + +```csharp +using Microsoft.Maui.DevFlow.Agent.Gtk; +using Microsoft.Maui.DevFlow.Blazor.Gtk; +``` + +Keep the calls inside `#if DEBUG` unless the user explicitly wants DevFlow available in non-Debug builds. diff --git a/.claude/skills/maui-devflow-onboard/references/package-selection.md b/.claude/skills/maui-devflow-onboard/references/package-selection.md new file mode 100644 index 00000000..13a92649 --- /dev/null +++ b/.claude/skills/maui-devflow-onboard/references/package-selection.md @@ -0,0 +1,23 @@ +# Package Selection + +Choose packages based on the app flavor: + +| Project flavor | Packages | +| --- | --- | +| Standard MAUI | `Microsoft.Maui.DevFlow.Agent` | +| MAUI + Blazor WebView | `Microsoft.Maui.DevFlow.Agent`, `Microsoft.Maui.DevFlow.Blazor` | +| GTK MAUI | `Microsoft.Maui.DevFlow.Agent.Gtk` | +| GTK MAUI + Blazor WebView | `Microsoft.Maui.DevFlow.Agent.Gtk`, `Microsoft.Maui.DevFlow.Blazor.Gtk` | + +MAUI indicators: + +- `true`; +- platform TFMs such as `net10.0-android`, `net10.0-ios`, `net10.0-maccatalyst`, or `net10.0-windows10.0.19041.0`; +- GTK package references such as `Maui.Gtk`, `Platform.Maui.Linux.Gtk4`, or `GirCore.Gtk-4.0`. + +Blazor WebView indicators: + +- package reference to `Microsoft.AspNetCore.Components.WebView.Maui`; +- call to `AddMauiBlazorWebView()` in `MauiProgram.cs`. + +Use Central Package Management if `Directory.Packages.props` exists. Otherwise place versions directly on project package references. diff --git a/AGENTS.md b/AGENTS.md index 48b86a32..640931e8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -226,25 +226,25 @@ input.dispatchEvent(new Event('input', { bubbles: true })); ``` Use `@bind:event="oninput"` on inputs for this to work (requires `input` events, not `change`). -## MauiDevFlow (AI Debugging) +## MAUI DevFlow (AI Debugging) -The project uses [MauiDevFlow](https://github.com/nicoleeldridge/MauiDevFlow) for AI-assisted debugging. Broker discovery is preferred; no `.mauidevflow` file is committed in this repo. +The project uses [MAUI DevFlow](https://github.com/dotnet/maui-labs/tree/main/src/DevFlow) from the unified `Microsoft.Maui.Cli` tool for AI-assisted debugging. Broker discovery is preferred; no `.mauidevflow` file is committed in this repo. ```bash # Always run CLI commands from src/MauiSherpa/ for auto port detection cd src/MauiSherpa # Check agent connectivity -dotnet maui-devflow MAUI status +dotnet maui devflow ui status # Take screenshots -dotnet maui-devflow MAUI screenshot --output screen.png +dotnet maui devflow ui screenshot --output screen.png # Blazor DOM snapshot (best for AI) -dotnet maui-devflow cdp snapshot +dotnet maui devflow webview snapshot # Inject dark/light mode for testing (avoids navigating to Settings) -dotnet maui-devflow cdp Runtime evaluate "document.body.classList.remove('theme-light'); document.body.classList.add('theme-dark'); document.querySelector('.main-layout').classList.remove('theme-light'); document.querySelector('.main-layout').classList.add('theme-dark');" +dotnet maui devflow webview Runtime evaluate "document.body.classList.remove('theme-light'); document.body.classList.add('theme-dark'); document.querySelector('.main-layout').classList.remove('theme-light'); document.querySelector('.main-layout').classList.add('theme-dark');" ``` ## CI/CD diff --git a/Directory.Build.props b/Directory.Build.props index 4b678b53..50d1e00b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ true - + 9231 diff --git a/README.md b/README.md index dcc09ee0..a857071c 100644 --- a/README.md +++ b/README.md @@ -346,5 +346,5 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file - [Shiny.Mediator](https://github.com/shinyorg/mediator) - Mediator pattern with caching - [AndroidSdk](https://github.com/redth/androidsdk.tool) - Android SDK management APIs - [AppleDev.Tools](https://github.com/redth/appledev.tools) - Apple Developer Tools APIs and AppStoreConnect API client -- [MauiDevFlow](https://github.com/Redth/MauiDevFlow) - Remote app inspection agent +- [MAUI DevFlow](https://github.com/dotnet/maui-labs/tree/main/src/DevFlow) - Remote app inspection agent - [GitHub Copilot](https://github.com/github/copilot-sdk) - AI-powered assistance via Copilot SDK diff --git a/docs/SCREENSHOTS.md b/docs/SCREENSHOTS.md index a873e528..698177b8 100644 --- a/docs/SCREENSHOTS.md +++ b/docs/SCREENSHOTS.md @@ -4,7 +4,7 @@ This document describes how to capture a complete set of screenshots for MAUI Sh ## Prerequisites -1. **MauiDevFlow CLI** installed and configured (see `dotnet-tools.json`) +1. **MAUI DevFlow CLI** installed and configured (see `dotnet-tools.json`) 2. **Android emulator** available (any API level at or above `SupportedOSPlatformVersion`) 3. **iOS simulator** booted (e.g., iPhone 17 Pro) 4. App built and running on Mac Catalyst @@ -25,8 +25,8 @@ open "bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/MAUI Sherpa.app" ```bash cd src/MauiSherpa -dotnet maui-devflow MAUI status # Agent connection -dotnet maui-devflow cdp status # CDP (Blazor WebView) +dotnet maui devflow ui status # Agent connection +dotnet maui devflow webview status # CDP (Blazor WebView) ``` ### Enable Demo Mode @@ -35,17 +35,17 @@ Demo Mode blurs sensitive values (Apple identity keys, cloud secrets, device UDI ```bash # Navigate to Settings and enable Demo Mode toggle -dotnet maui-devflow cdp Input dispatchClickEvent "a.nav-item[href='settings']" +dotnet maui devflow webview Input dispatchClickEvent "a.nav-item[href='settings']" sleep 2 -dotnet maui-devflow cdp Input dispatchClickEvent ".toggle-switch" +dotnet maui devflow webview Input dispatchClickEvent ".toggle-switch" # Verify it's on: -dotnet maui-devflow cdp Runtime evaluate "document.querySelector('.toggle-switch input[type=\"checkbox\"]').checked" +dotnet maui devflow webview Runtime evaluate "document.querySelector('.toggle-switch input[type=\"checkbox\"]').checked" ``` ### Set Dark Mode (Optional) ```bash -dotnet maui-devflow cdp Runtime evaluate "document.body.classList.remove('theme-light'); document.body.classList.add('theme-dark'); document.querySelector('.main-layout').classList.remove('theme-light'); document.querySelector('.main-layout').classList.add('theme-dark');" +dotnet maui devflow webview Runtime evaluate "document.body.classList.remove('theme-light'); document.body.classList.add('theme-dark'); document.querySelector('.main-layout').classList.remove('theme-light'); document.querySelector('.main-layout').classList.add('theme-dark');" ``` ### Start Devices @@ -70,7 +70,7 @@ Examples: ```bash # Navigate via sidebar link -dotnet maui-devflow cdp Input dispatchClickEvent "a.nav-item[href='']" +dotnet maui devflow webview Input dispatchClickEvent "a.nav-item[href='']" # Page hrefs: (empty string)=Dashboard, doctor, settings, devices, emulators, # android-sdk, keystores, apple-simulators, apple-devices, bundle-ids, @@ -82,14 +82,14 @@ dotnet maui-devflow cdp Input dispatchClickEvent "a.nav-item[href=''] ```bash # Always wait 2-3 seconds after navigation/interaction before capturing sleep 2 -dotnet maui-devflow MAUI screenshot --output docs/screenshots/MAUI.Sherpa_.png +dotnet maui devflow ui screenshot --output docs/screenshots/MAUI.Sherpa_.png ``` ### Fill Form Fields (Blazor) ```bash # Use the native value setter pattern to trigger Blazor binding -dotnet maui-devflow cdp Runtime evaluate " +dotnet maui devflow webview Runtime evaluate " const input = document.querySelector(''); Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set.call(input, ''); input.dispatchEvent(new Event('input', { bubbles: true })); @@ -100,7 +100,7 @@ dotnet maui-devflow cdp Runtime evaluate " ```bash # Blazor scrollable container is main.content, NOT document.body -dotnet maui-devflow cdp Runtime evaluate "document.querySelector('main.content').scrollTo(0, )" +dotnet maui devflow webview Runtime evaluate "document.querySelector('main.content').scrollTo(0, )" ``` ## Screenshot Inventory diff --git a/dotnet-tools.json b/dotnet-tools.json index bb73a594..ca815210 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -2,10 +2,10 @@ "version": 1, "isRoot": true, "tools": { - "redth.mauidevflow.cli": { - "version": "0.18.0", + "microsoft.maui.cli": { + "version": "0.1.0-preview.7.26230.1", "commands": [ - "maui-devflow" + "maui" ], "rollForward": false } diff --git a/src/MauiSherpa.Core/Interfaces.cs b/src/MauiSherpa.Core/Interfaces.cs index 14e21be1..cbd52ef3 100644 --- a/src/MauiSherpa.Core/Interfaces.cs +++ b/src/MauiSherpa.Core/Interfaces.cs @@ -2612,7 +2612,7 @@ public interface ICopilotToolsService public interface IProfilingContextService { /// - /// Gets the currently available local profiling targets discovered from MauiDevFlow. + /// Gets the currently available local profiling targets discovered from MAUI DevFlow. /// Task> GetAvailableTargetsAsync(CancellationToken ct = default); diff --git a/src/MauiSherpa.Core/Models/DevFlow/DevFlowModels.cs b/src/MauiSherpa.Core/Models/DevFlow/DevFlowModels.cs index 70604f54..e93e6f90 100644 --- a/src/MauiSherpa.Core/Models/DevFlow/DevFlowModels.cs +++ b/src/MauiSherpa.Core/Models/DevFlow/DevFlowModels.cs @@ -4,7 +4,7 @@ namespace MauiSherpa.Core.Models.DevFlow; /// -/// Agent session registered with the MauiDevFlow broker. +/// Agent session registered with the MAUI DevFlow broker. /// public class BrokerAgent { diff --git a/src/MauiSherpa.Core/Services/CopilotToolsService.cs b/src/MauiSherpa.Core/Services/CopilotToolsService.cs index 6b1ae673..f5669f0d 100644 --- a/src/MauiSherpa.Core/Services/CopilotToolsService.cs +++ b/src/MauiSherpa.Core/Services/CopilotToolsService.cs @@ -159,7 +159,7 @@ private void InitializeTools() // Profiling Tools AddTool(AIFunctionFactory.Create(ListProfilingTargetsAsync, "list_profiling_targets", - "List currently available local profiling targets discovered via MauiDevFlow."), isReadOnly: true); + "List currently available local profiling targets discovered via MAUI DevFlow."), isReadOnly: true); AddTool(AIFunctionFactory.Create(GetProfilingCatalogAsync, "get_profiling_catalog", "Get the supported profiling scenarios and platform capabilities available in Maui Sherpa. Optionally filter to a single platform."), isReadOnly: true); AddTool(AIFunctionFactory.Create(ListProfilingArtifactsAsync, "list_profiling_artifacts", @@ -1544,7 +1544,7 @@ private async Task ListDeviceDefinitionsAsync( #region Profiling Tools - [Description("List currently available local profiling targets discovered via MauiDevFlow")] + [Description("List currently available local profiling targets discovered via MAUI DevFlow")] private async Task ListProfilingTargetsAsync() { _logger.LogDebug("Tool: list_profiling_targets called"); @@ -1552,7 +1552,7 @@ private async Task ListProfilingTargetsAsync() var targets = await _profilingContextService.GetAvailableTargetsAsync(); if (targets.Count == 0) { - return "No local profiling targets are available. Start a MAUI app with MauiDevFlow enabled, then try again."; + return "No local profiling targets are available. Start a MAUI app with MAUI DevFlow enabled, then try again."; } return JsonSerializer.Serialize(targets, new JsonSerializerOptions { WriteIndented = true }); diff --git a/src/MauiSherpa.Core/Services/DevFlowAgentClient.cs b/src/MauiSherpa.Core/Services/DevFlowAgentClient.cs index 18a174eb..21843a18 100644 --- a/src/MauiSherpa.Core/Services/DevFlowAgentClient.cs +++ b/src/MauiSherpa.Core/Services/DevFlowAgentClient.cs @@ -6,7 +6,7 @@ namespace MauiSherpa.Core.Services; /// -/// HTTP/WebSocket client for communicating with a MauiDevFlow agent and broker. +/// HTTP/WebSocket client for communicating with a MAUI DevFlow agent and broker. /// public class DevFlowAgentClient : IDisposable { diff --git a/src/MauiSherpa.Core/Services/ProfilingContextService.cs b/src/MauiSherpa.Core/Services/ProfilingContextService.cs index db59b4a5..fb11cb99 100644 --- a/src/MauiSherpa.Core/Services/ProfilingContextService.cs +++ b/src/MauiSherpa.Core/Services/ProfilingContextService.cs @@ -5,7 +5,7 @@ namespace MauiSherpa.Core.Services; /// -/// Builds lightweight profiling summaries from live MauiDevFlow data. +/// Builds lightweight profiling summaries from live MAUI DevFlow data. /// public class ProfilingContextService : IProfilingContextService { @@ -70,7 +70,7 @@ public async Task GetSnapshotAsync(ProfilingSnapshotOpt { return new ProfilingSnapshotResult( null, - "No local profiling targets are available. Start a MAUI app with MauiDevFlow enabled, then try again."); + "No local profiling targets are available. Start a MAUI app with MAUI DevFlow enabled, then try again."); } var resolvedTarget = ResolveTarget(targets, options.TargetId); @@ -230,7 +230,7 @@ internal static ProfilingVisualTreeSummary BuildVisualTreeSummary(IEnumerable - - - - - - + + + + + + diff --git a/src/MauiSherpa.MacOS/MacOSMauiProgram.cs b/src/MauiSherpa.MacOS/MacOSMauiProgram.cs index d3d75571..e759f498 100644 --- a/src/MauiSherpa.MacOS/MacOSMauiProgram.cs +++ b/src/MauiSherpa.MacOS/MacOSMauiProgram.cs @@ -10,8 +10,8 @@ using Shiny.Mediator; using Sentry.Maui; #if DEBUG -using MauiDevFlow.Agent; -using MauiDevFlow.Blazor; +using Microsoft.Maui.DevFlow.Agent; +using Microsoft.Maui.DevFlow.Blazor; #endif namespace MauiSherpa; diff --git a/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj b/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj index 63ec0864..e42f96d5 100644 --- a/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj +++ b/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj @@ -42,8 +42,8 @@ - - + + diff --git a/src/MauiSherpa.ProfilingSample/Components/MainLayout.razor b/src/MauiSherpa.ProfilingSample/Components/MainLayout.razor index 9646dd6e..72e9eca6 100644 --- a/src/MauiSherpa.ProfilingSample/Components/MainLayout.razor +++ b/src/MauiSherpa.ProfilingSample/Components/MainLayout.razor @@ -12,7 +12,7 @@
-
Debug builds expose MauiDevFlow for local profiling snapshots.
+
Debug builds expose MAUI DevFlow for local profiling snapshots.
diff --git a/src/MauiSherpa.ProfilingSample/MauiProgram.cs b/src/MauiSherpa.ProfilingSample/MauiProgram.cs index 81dd53b3..9604cac4 100644 --- a/src/MauiSherpa.ProfilingSample/MauiProgram.cs +++ b/src/MauiSherpa.ProfilingSample/MauiProgram.cs @@ -1,8 +1,8 @@ using Microsoft.Extensions.Logging; using MauiSherpa.ProfilingSample.Services; #if DEBUG -using MauiDevFlow.Agent; -using MauiDevFlow.Blazor; +using Microsoft.Maui.DevFlow.Agent; +using Microsoft.Maui.DevFlow.Blazor; #endif namespace MauiSherpa.ProfilingSample; diff --git a/src/MauiSherpa.ProfilingSample/MauiSherpa.ProfilingSample.csproj b/src/MauiSherpa.ProfilingSample/MauiSherpa.ProfilingSample.csproj index fcaa66be..e6dcde6a 100644 --- a/src/MauiSherpa.ProfilingSample/MauiSherpa.ProfilingSample.csproj +++ b/src/MauiSherpa.ProfilingSample/MauiSherpa.ProfilingSample.csproj @@ -26,8 +26,8 @@ - - + + diff --git a/src/MauiSherpa.ProfilingSample/Pages/Home.razor b/src/MauiSherpa.ProfilingSample/Pages/Home.razor index f72c626f..843130ad 100644 --- a/src/MauiSherpa.ProfilingSample/Pages/Home.razor +++ b/src/MauiSherpa.ProfilingSample/Pages/Home.razor @@ -215,7 +215,7 @@ @ScenarioService.Network.Status
-

These runs fire fetches from JavaScript inside the Blazor WebView so MauiDevFlow and Sherpa can observe them. Local mode always works; remote mixed mode intentionally includes slow and failing requests when available.

+

These runs fire fetches from JavaScript inside the Blazor WebView so MAUI DevFlow and Sherpa can observe them. Local mode always works; remote mixed mode intentionally includes slow and failing requests when available.