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.