Skip to content

feat(cua-driver-rs): agent-guidance refactor + uninstall converge + warnings cleanup - #1665

Merged
f-trycua merged 5 commits into
mainfrom
agent-guidance-refactor
May 23, 2026
Merged

feat(cua-driver-rs): agent-guidance refactor + uninstall converge + warnings cleanup#1665
f-trycua merged 5 commits into
mainfrom
agent-guidance-refactor

Conversation

@f-trycua

@f-trycua f-trycua commented May 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Four logically-grouped commits, bundled per request (single PR for easier deploy). All originated from a fresh-install dogfood on the cuademo VM — the dogfood surfaced real bugs and a research-backed restructuring opportunity.

1. fix(cua-driver-rs)(uninstall): converge uninstall.{ps1,sh} + UAC self-elevation (fca003ec)

uninstall.ps1 now self-elevates via UAC when it detects an -AutoStart install (the cua-driver-serve task at RunLevel=Highest plus the High-IL daemon it spawns can't be torn down from a non-elevated same-user shell — silent Access Denied on schtasks /Delete and Stop-Process left dangling state otherwise).

uninstall.sh inlines what _uninstall-rust.sh used to do — single canonical script per shell, mirroring uninstall.ps1's shape. _uninstall-rust.sh deleted; CI workflow + docs updated to match.

2. fix(cua-driver-rs)(install-local.ps1): UTF-8 read for post-install-hints (7bc1cf0b)

PR #1664's rendered Next steps: block came out with mojibake on Windows: •, â€". Cause: Get-Content -Raw defaults to Windows-1252 on PS 5.1 when the source file has no BOM. Surgical fix at the one Windows reader ([System.IO.File]::ReadAllText(..., UTF8)); the other 3 installers were unaffected so post-install-hints.txt stays BOM-free.

3. chore(cua-driver-rs): clean up 30 build warnings in -p cua-driver path (5986430b)

cargo build --release -p cua-driver was emitting 28 + 3 warnings before; zero after. Mechanical: dead imports/mut/writes, #[allow(dead_code)] on cross-platform stubs, let _ = on Win32 teardown calls, module-scope #![allow(non_upper_case_globals)] for external UIA_*ControlTypeId constants.

4. feat(cua-driver-rs): agent-guidance refactor — Skills / MCP-instructions / per-tool (7ab537c1)

Informed by a survey of how OSS computer-use tools (Playwright MCP, browser-use, Goose, Open Interpreter, Anthropic computer-use cookbook) push usage guidance to LLM agents, cross-checked against the MCP spec + Claude Skills convention:

  • SKILL.md: 911 → 493 lines (Anthropic's documented limit is 500). Extracted macOS-specific content (no-foreground contract, AppleScript prohibitions, AXMenuBar navigation, SkyLight click dispatch, Apple-Events JS bridge) into a new MACOS.md mirroring the existing WINDOWS.md / LINUX.md / WEB_APPS.md companion files.
  • AGENT_INSTRUCTIONS (MCP instructions field): converted from const &str to fn -> String templated per-host via cfg!(target_os = ...). macOS clients see "AX", Windows "UIA", Linux "AT-SPI" — Goose's ComputerController pattern. Added a closing line pointing skill-aware harnesses at SKILL.md + the per-OS companion (free description-match hint for Claude Code / Codex / OpenClaw / OpenCode; ignored by Hermes / Cursor / generic MCP clients).
  • Thicker per-tool descriptions on click + screenshot (all 3 platforms): "prefer element_index over pixel coords" editorial on click, max_image_dimension=1568 default + pointer to get_window_state on screenshot. Per-call gating rather than per-session — Anthropic computer-use cookbook shape.

Out of scope (flagged here for follow-up)

  • Sibling Swift skill at libs/cua-driver/Skills/cua-driver/SKILL.md is 887 lines — also over Anthropic's 500-line ceiling. Same refactor pattern applies (extract macOS-specific content into a companion file); not done in this PR because it's the Swift driver's skill, not the Rust port.
  • Pre-existing daemon hot loop on this Windows VM: idle daemon CPU is ~95% (HEAD has the same behaviour — bisected by stashing this PR's changes, rebuilding HEAD, observing the same CPU burn). Likely the cursor-overlay thread's SetTimer(hwnd, 1, 8, None) running at 125 Hz unconditionally. Worth gating to "spin only when the overlay is actually visible/active" in a separate PR.

Test plan

  • cargo build --release -p cua-driver clean (zero warnings)
  • install-local.ps1 runs end-to-end on a freshly-wiped Windows VM
  • Rendered Next steps: block shows proper bullets and em-dashes
  • uninstall.ps1 self-elevates correctly after an -AutoStart install (UAC prompt, fully removes daemon + task + ~\.cua-driver\ + skill junctions)
  • uninstall.sh smoke on macOS + Linux (needs reviewer host to verify — no Mac/Linux VM available this session)
  • Screenshot defaults end-to-end (jpeg @ 85, ≤1568px) — verified via dump-docs schema; runtime call hangs in Claude Code subprocess context (pre-existing daemon hot loop, see "Out of scope"), needs interactive RDP retest
  • Cross-check the rendered MCP instructions field from an MCP client (handshake response shows OS-templated content + skill pointer)

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added platform-specific documentation (macOS, Windows, Linux) for detailed setup and usage guidance.
    • Windows uninstall now auto-elevates when necessary to cleanly remove services and processes.
  • Bug Fixes

    • Fixed post-install hints encoding issue on Windows.
  • Documentation

    • Consolidated uninstall documentation across all platforms.
    • Enhanced tool descriptions for improved clarity.
  • Refactoring

    • Streamlined uninstall workflow by consolidating Rust backend logic into main scripts.

Review Change Stack

f-trycua and others added 4 commits May 23, 2026 17:25
…-elevation

Three changes that together let -AutoStart installs roll back cleanly:

1. uninstall.ps1 self-elevates via UAC when it detects an -AutoStart
   install. The cua-driver-serve task is registered at RunLevel=Highest
   (autostart.rs:127, since 2026-05-21 for UWP/AppContainer support), so
   the daemon spawned by it runs at High IL and a non-elevated process
   — even the same user who installed it — could neither terminate the
   daemon nor delete the task. Detection: schtasks /Query OR a running
   cua-driver.exe. Re-exec via Start-Process -Verb RunAs; supports both
   `-File` invocation and `irm | iex` (materialises body to tempfile).

2. uninstall.sh inlines what _uninstall-rust.sh used to do — single
   canonical script per shell, mirrors uninstall.ps1's shape. Same
   --experimental-rust / --backend=rust / --backend=swift flag set,
   same non-macOS Rust auto-select. _uninstall-rust.sh deleted.

3. cd-rust-cua-driver.yml drops the cp _uninstall-rust.sh release-upload
   line + updated comment. installation.mdx docs page reflects the new
   one-file-per-shell shape and the .ps1 self-elevation behaviour.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The `Next steps:` block rendered with mojibake (`•` for `•`, `â€"`
for `—`) because PowerShell 5.1's `Get-Content -Raw` defaults to
Windows-1252 when the source file has no BOM. The .txt is UTF-8.

Replaced `Get-Content -Raw` with `[System.IO.File]::ReadAllText(...,
UTF8)`. Surgical fix at the one Windows reader; the other 3 installers
(install.ps1 via Invoke-WebRequest HTTP-charset, _install-rust.sh /
install-local.sh via sed on bytes) were never affected, so the .txt
stays BOM-free.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`cargo build --release -p cua-driver` previously emitted 28 warnings
on platform-windows + 3 on cua-driver. After this commit: zero.

Mechanical groups:

1. Dead code (delete):
   - overlay.rs: unused `Duration` import; 2 stray `use Win32::*` lines
     (PR #1662 fallout from rotate_toward extraction); 2 unused `mut`;
     uia/mod.rs lines 173-174 dead writes to `counter`/`total` that
     are never read after the fallback block.
   - cli.rs: deleted unused `run_dump_docs` wrapper — `main.rs` only
     calls `run_dump_docs_with_type`, the wrapper had zero callers.
2. #[allow(dead_code)] on bundle.rs non-macOS/non-unix stubs — they
   exist for cross-platform API symmetry per the module header.
3. `let _ = ` on 10 Win32 teardown calls (ShowWindow, TranslateMessage,
   DeleteDC, UpdateLayeredWindow, DeleteObject) that return BOOL /
   Result. These are fire-and-forget at end-of-scope; the lint wants
   explicit ignore.
4. Module-scope #![allow(non_upper_case_globals)] in uia/windows_enum.rs
   — pattern-matches against `UIA_*ControlTypeId` constants from the
   `windows` crate (we can't rename external symbols). Mirrors the
   existing `#![allow(...)]` at overlay.rs:12.

Cargo.lock picks up the 0.2.7 → 0.2.18 workspace-version-bump that
shipped earlier this session.

The `TypeTextCharsTool { state: _state }` rename + per-tool description
thickening on platform-windows/tools/impl_.rs land in a follow-up
commit alongside the agent-guidance refactor.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…s/per-tool

Three changes informed by a survey of how OSS computer-use tools push
usage guidance to LLM agents (Playwright MCP, browser-use, Goose,
Open Interpreter, Anthropic computer-use cookbook) cross-checked
against the MCP spec + Claude Skills convention.

Findings driving the changes:

- Anthropic's documented Skills tip is "Keep SKILL.md under 500 lines;
  move detailed reference material to separate files"
  (code.claude.com/docs/en/skills). Our SKILL.md was 911 lines.
- The MCP `instructions` field is spec'd as a hint that "MAY be added
  to the system prompt" — eager, every-turn cost. Community ceiling
  ~200 words. Goose templates its `instructions` per-OS (AX vs UIA
  vs AT-SPI) so the agent only sees the path that applies.
- AGENT_INSTRUCTIONS reaches every MCP client uniformly (Hermes,
  Cursor, Copilot CLI, plus Claude-Skills-aware agents over MCP).
  SKILL.md reaches only the 4 agents with a Skills loader. So both
  surfaces should cross-reference each other rather than duplicate.

Changes:

1. **SKILL.md split**: 911 lines → 493-line cross-platform entrypoint
   (snapshot invariant, CLI/MCP defaults, behavior matrix, canonical
   loop, pixel-click contract, common errors) + new MACOS.md (475
   lines) carrying the no-foreground contract, AppleScript / `open`
   prohibitions, AXMenuBar navigation, SkyLight click dispatch, and
   the Apple-Events JS bridge. Existing WINDOWS.md (686), LINUX.md
   (87), WEB_APPS.md (477), RECORDING.md (120) untouched — they were
   already separated. (Sibling Swift driver skill at
   libs/cua-driver/Skills/cua-driver/SKILL.md is 887 lines — also
   over budget but out of scope for this Rust-port PR.)

2. **AGENT_INSTRUCTIONS in crates/mcp-server/src/protocol.rs**:
   - Converted from `const &str` to `fn() -> String` so it can be
     templated at compile time per host (`cfg!(target_os = ...)`).
     macOS clients see "AX (Accessibility)", Windows see "UIA (UI
     Automation)", Linux see "AT-SPI" — same pattern as Goose's
     ComputerController + Open Interpreter's `platform.system()`.
   - Added a closing line pointing skill-aware harnesses at SKILL.md
     + the relevant per-OS companion (e.g. MACOS.md on macOS). MCP
     clients without a skills loader (Hermes, Cursor) ignore the
     pointer; clients with one get a free description-match hint.
   - Tightened the workflow: 5 steps including re-snapshot, dropped
     the redundant list_apps step in favor of launch_app's `windows`
     array. Still under 200 words.

3. **Thicker per-tool descriptions** on click + screenshot (all 3
   platforms): pushed "prefer element_index over pixel coords"
   guidance onto click (per Playwright's "this is better than
   screenshot" editorial pattern), and a pointer to get_window_state
   + max_image_dimension=1568 default onto screenshot. Per-call
   gating rather than per-session — Anthropic computer-use cookbook
   shape.

Also includes the `TypeTextCharsTool { state: _state }` rename on
platform-windows/tools/impl_.rs (the warnings-cleanup change that
overlapped this file — the only field rename, struct still
intentionally unregistered per the comment at impl_.rs:3991).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vercel

vercel Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview May 23, 2026 5:41pm

Request Review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b6a7ed8b-f400-4419-b562-7724affa2ff4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR consolidates uninstall logic by inlining Rust backend support into canonical shell/PowerShell scripts, restructures skill documentation from macOS-centric to cross-platform with platform-specific companions, adds new CLI diagnostic commands, and clarifies tool descriptions across all platforms.

Changes

Uninstall Consolidation and Installation Fixes

Layer / File(s) Summary
Shell uninstall: Rust backend inlined
libs/cua-driver/scripts/uninstall.sh
uninstall.sh now inlines the complete Rust uninstall path (CLI symlink resolution, systemd/LaunchAgent removal, app bundle deletion, package-home cleanup, skill symlink filtering, Claude MCP scrubbing via Python) with auto-selection on non-macOS and environment override support, while keeping Swift logic structurally unchanged with clarified comments.
PowerShell uninstall: UAC self-elevation
libs/cua-driver/scripts/uninstall.ps1
uninstall.ps1 adds Test-IsElevated/Test-NeedsElevation helpers to detect locked binaries and the high-privilege cua-driver-serve Scheduled Task; conditionally re-executes itself elevated via RunAs, forwards -Force, and handles irm|iex invocation by writing to temp file; includes UTF-8 BOM and updated documentation.
PowerShell install: UTF-8 encoding for hints
libs/cua-driver-rs/scripts/install-local.ps1
Switches from Get-Content -Raw to System.IO.File::ReadAllText(..., UTF8) to fix character rendering issues in post-install hints text.
Release workflow: Remove _uninstall-rust.sh staging
.github/workflows/cd-rust-cua-driver.yml
CD workflow no longer packages _uninstall-rust.sh as a release asset; stages only uninstall.sh and uninstall.ps1 with comments asserting both backends are now handled inline.
Installation docs: Consolidated uninstall descriptions
docs/content/docs/cua-driver/guide/getting-started/installation.mdx
Updated documentation to reflect inlined Rust logic in uninstall.sh (no separate helper), auto-detection on non-macOS, Windows uninstall.ps1 self-elevation behavior, and safety invariants for symlink/junction detection across platforms.

Skill Documentation Restructuring and Protocol Updates

Layer / File(s) Summary
macOS skill documentation: Platform-specific guidance
libs/cua-driver-rs/Skills/cua-driver-rs/MACOS.md
New file consolidates macOS-specific guidance: no-foreground contract, forbidden activation patterns, intent→tool mapping, prerequisites, launch_app rules, pixel-click dispatch mechanics, AXMenuBar interaction with two-snapshot flow and focus-steal carve-out, browser JS via Apple Events, common error patterns, and end-to-end Finder example.
SKILL.md: Cross-platform core refactored
libs/cua-driver-rs/Skills/cua-driver-rs/SKILL.md
Refactored from macOS-skewed to cross-platform: delegates platform details to platform-specific docs, defines core no-foreground principle, snapshot invariant, canonical loop, addressing modes; adds Claude Code compatibility mode; revises capture_mode matrix and som response fields with screenshot dimensions and screenshot_out_file workflow; reorganizes canonical loop to skip list_apps; updates end-to-end example to be cross-platform (Finder vs Explorer).
MCP protocol: Dynamic platform-specific instructions
libs/cua-driver-rs/crates/mcp-server/src/protocol.rs
initialize_result() now generates instructions dynamically via agent_instructions() helper which selects platform-specific accessibility-tree provider name and skill document pointer (AX+MACOS.md for macOS, UIA+WINDOWS.md for Windows, AT-SPI+LINUX.md for Linux); includes updated per-turn workflow steps.

CLI Extensions and Supporting Infrastructure

Layer / File(s) Summary
CLI diagnostic commands: diagnose, config, doctor
libs/cua-driver-rs/crates/cua-driver/src/cli.rs
Adds run_diagnose_cmd (multi-section diagnostic report: runtime identity, codesign parsing, TCC live probes, installation/layout checks, sqlite3 TCC DB reads, path existence booleans), run_config_cmd (daemon-first forwarding with in-process persisted JSON config overlay and dotted-key support), and run_doctor_cmd (runs doctor::run() with JSON/text output); extends dump-docs to run_dump_docs_with_type supporting mcp/cli/all output types.
CLI utilities: JSON parsing, telemetry, text helpers
libs/cua-driver-rs/crates/cua-driver/src/cli.rs
Adds read_stdin_json() with UTF-8 BOM stripping and pipe detection (including unit tests); adds telemetry_entry_event(cmd) and sanitize_tool_name() for safe PostHog event naming with input validation; adds first_sentence(text) for tool-listing summaries.

Tool Documentation Refinements and Code Quality

Layer / File(s) Summary
macOS tool documentation: click and screenshot
libs/cua-driver-rs/crates/platform-macos/src/tools/click.rs, libs/cua-driver-rs/crates/platform-macos/src/tools/screenshot.rs
Updates macOS click description to expand addressing modes, emphasize element_index stability, clarify element caching per turn, detail from_zoom coordinate translation; updates screenshot description to recommend get_window_state for UI/accessibility work.
Linux tool documentation: click and screenshot
libs/cua-driver-rs/crates/platform-linux/src/tools/impl_.rs
Updates Linux click description to emphasize element_index over x/y, clarify AT-SPI cache scoping, document from_zoom translation; updates screenshot description to clarify max_image_dimension resizing, recommend get_window_state for UI work, clarify full-display capture without window_id.
Windows tool documentation: click, screenshot, and struct cleanup
libs/cua-driver-rs/crates/platform-windows/src/tools/impl_.rs
Updates Windows click description to recommend element_index with cache scoping per (pid, window_id) and pixel constraints; updates screenshot to recommend get_window_state with element-index cache explanation; renames TypeTextCharsTool.state to _state to suppress dead-code lint; adjusts build_registry touch struct accordingly.
Windows code cleanup: lint attributes and resource handling
libs/cua-driver-rs/crates/cua-driver/src/bundle.rs, libs/cua-driver-rs/crates/platform-windows/src/capture.rs, libs/cua-driver-rs/crates/platform-windows/src/overlay.rs, libs/cua-driver-rs/crates/platform-windows/src/uia/mod.rs, libs/cua-driver-rs/crates/platform-windows/src/uia/windows_enum.rs
Adds #[allow(dead_code)] to platform-gated stubs in bundle.rs; adds #[allow(non_upper_case_globals)] to windows_enum.rs for UIA_*ControlTypeId matches; updates capture.rs and overlay.rs to explicitly ignore return values from DeleteObject/DeleteDC via let _ = assignments; adds DeleteDC on CreateDIBSection failure in overlay.rs; simplifies Win32 imports in overlay.rs message loop.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • trycua/cua#1558: Introduces the separate _uninstall-rust.sh helper that this PR consolidates back into the main scripts.
  • trycua/cua#1630: Registers the cua-driver-serve Scheduled Task at RunLevel=Highest, which directly motivates this PR's UAC self-elevation pre-check in uninstall.ps1.
  • trycua/cua#1606: Refines platform-windows/src/uia/mod.rs's walk_tree fallback handling, which overlaps with this PR's adjustments to the same fallback logic.

Suggested reviewers

  • ddupont808

🐰 Consolidate, elevate, and clarify,
Uninstall scripts now unified and spry;
Docs cross-platform, skill guides astray,
Diagnostics command the driver's display.
Platform specifics have their own home,
Windows rises high, no access denied to roam!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the four main changes bundled in this PR: agent-guidance refactor, uninstall convergence, and warnings cleanup.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent-guidance-refactor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
libs/cua-driver-rs/Skills/cua-driver-rs/SKILL.md (1)

114-121: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language identifier to code block.

The fenced code block showing CLI command examples should specify bash or shell as the language identifier.

📝 Proposed fix
-```
+```bash
 cua-driver serve
 cua-driver launch_app '{"bundle_id":"..."}'
 # → {pid: 844, windows: [{window_id: 10725, ...}]}
 cua-driver get_window_state '{"pid":844,"window_id":10725}'
 cua-driver click '{"pid":844,"window_id":10725,"element_index":14}'
 cua-driver stop
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @libs/cua-driver-rs/Skills/cua-driver-rs/SKILL.md around lines 114 - 121,
Update the fenced code block in SKILL.md that shows CLI examples so it includes
a language identifier (e.g., change the opening tobash or ```shell) to
enable proper syntax highlighting for the commands (the block containing
"cua-driver serve", "cua-driver launch_app ...", "cua-driver get_window_state
...", "cua-driver click ...", "cua-driver stop").


</details>

</blockquote></details>
<details>
<summary>libs/cua-driver/scripts/uninstall.sh (1)</summary><blockquote>

`78-80`: _⚠️ Potential issue_ | _🟠 Major_ | _⚡ Quick win_

**Honor explicit `--backend=swift` before auto-selecting Rust.**

`--backend=swift` is documented as a compatibility no-op on non-Darwin hosts, but this path never records that the user explicitly chose Swift. On Linux it still falls into the auto-Rust branch and removes the Rust install anyway.
 
<details>
<summary>Suggested fix</summary>

```diff
 USE_RUST_BACKEND=0
+BACKEND_EXPLICIT=0
 FORWARDED_ARGS=()
 PASSTHROUGH=0
 while [[ $# -gt 0 ]]; do
@@
-        --experimental-rust) USE_RUST_BACKEND=1; shift ;;
-        --backend=rust)      USE_RUST_BACKEND=1; shift ;;
-        --backend=swift)     shift ;;                 # explicit default — no-op
+        --experimental-rust) USE_RUST_BACKEND=1; BACKEND_EXPLICIT=1; shift ;;
+        --backend=rust)      USE_RUST_BACKEND=1; BACKEND_EXPLICIT=1; shift ;;
+        --backend=swift)     BACKEND_EXPLICIT=1; shift ;;  # explicit default — no-op
@@
-if [[ "$USE_RUST_BACKEND" == "0" && "$OS" != "Darwin" ]]; then
+if [[ "$BACKEND_EXPLICIT" == "0" && "$USE_RUST_BACKEND" == "0" && "$OS" != "Darwin" ]]; then
```
</details>


Also applies to: 95-99

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver/scripts/uninstall.sh` around lines 78 - 80, The option
parsing currently treats "--backend=swift" as a no-op but doesn't record the
user's explicit choice, so later auto-selection still enables USE_RUST_BACKEND;
update the "--backend=swift" case to record the explicit choice (e.g., set
EXPLICIT_BACKEND="swift" or EXPLICIT_SWIFT=1) instead of only shifting, and then
modify the auto-select logic that sets USE_RUST_BACKEND (the branch that
currently enables Rust automatically) to check for that explicit marker and skip
enabling Rust when the user explicitly chose Swift; ensure references to
USE_RUST_BACKEND and the new EXPLICIT_BACKEND/EXPLICIT_SWIFT symbol are used
consistently (also apply the same change in the corresponding parsing block
referenced later).
```

</details>

</blockquote></details>

</blockquote></details>
🧹 Nitpick comments (1)
libs/cua-driver-rs/crates/mcp-server/src/protocol.rs (1)

188-209: ⚡ Quick win

Consider using raw string literals for improved readability.

The multi-line format string with escaped quotes and manual line continuations is functional but harder to read and maintain. Raw string literals (r#"..."#) would eliminate the need for escaped quotes and make the instruction text clearer.

♻️ Proposed refactor
-    format!(
-"cua-driver-rs: cross-platform background computer-use automation.
-
-Tools let you interact with any app without stealing keyboard focus or moving \
-the visible cursor. Prefer element_index ({tree_kind}) paths over pixel \
-coordinates — they work on backgrounded/hidden windows.
-
-Workflow per turn:
-1. launch_app  → idempotent, returns pid + windows array in one call
-2. (skip list_windows when launch_app already returned a single window)
-3. get_window_state(pid, window_id) → refresh the {tree_kind} snapshot, get element indices
-4. click/type_text/press_key using element_index from step 3
-5. get_window_state(pid, window_id) again → verify the action landed
-
-Agent cursor: set_agent_cursor_* tools visualise where the agent is acting \
-without affecting the real mouse pointer.
-
-If a `cua-driver-rs` skill is loaded in your harness (Claude Code / Codex / \
-OpenClaw / OpenCode dirs), prefer its detailed workflow — SKILL.md plus \
-{platform_skill_pointer}. Install with `cua-driver skills install` if not yet present."
-    )
+    format!(
+        r#"cua-driver-rs: cross-platform background computer-use automation.
+
+Tools let you interact with any app without stealing keyboard focus or moving the visible cursor. Prefer element_index ({tree_kind}) paths over pixel coordinates — they work on backgrounded/hidden windows.
+
+Workflow per turn:
+1. launch_app  → idempotent, returns pid + windows array in one call
+2. (skip list_windows when launch_app already returned a single window)
+3. get_window_state(pid, window_id) → refresh the {tree_kind} snapshot, get element indices
+4. click/type_text/press_key using element_index from step 3
+5. get_window_state(pid, window_id) again → verify the action landed
+
+Agent cursor: set_agent_cursor_* tools visualise where the agent is acting without affecting the real mouse pointer.
+
+If a `cua-driver-rs` skill is loaded in your harness (Claude Code / Codex / OpenClaw / OpenCode dirs), prefer its detailed workflow — SKILL.md plus {platform_skill_pointer}. Install with `cua-driver skills install` if not yet present."#
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver-rs/crates/mcp-server/src/protocol.rs` around lines 188 - 209,
Replace the long escaped multi-line format! string with a raw string literal
(e.g., use r#"..."#) inside the same format! call so you can remove all
backslash continuations and escaped quotes, preserving the interpolation
placeholders {tree_kind} and {platform_skill_pointer}; update the format!
invocation around that large text (the existing format!(...)) to use the raw
string content for readability while keeping the same placeholders and returning
value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@libs/cua-driver-rs/Skills/cua-driver-rs/MACOS.md`:
- Around line 414-416: Update the fenced code block that contains
get_window_state({pid, window_id, javascript: "document.title"}) to include a
shell language identifier by changing the opening backticks to ```bash (or
```sh) so the snippet is highlighted as shell/bash.
- Around line 373-375: The fenced code block that contains the osascript command
(the line: osascript -e 'tell application "<App Name>" to activate') needs a
language identifier for proper highlighting; update the backtick fence from ```
to ```bash (or ```shell) so the block starts with ```bash and retains the same
command content inside (in the MACOS.md code block showing the osascript
invocation).

In `@libs/cua-driver/scripts/uninstall.sh`:
- Around line 152-166: The uninstall script currently treats
"/Applications/CuaDriver.app" as a Rust-only indicator which can match Swift
installs; update the logic around USER_BIN_LINK resolution (the block using
resolve_link and the case patterns that include "/Applications/CuaDriver.app")
to only remove the shared bundle when a Rust-specific marker is present (e.g.,
check for HOME_DIR or the ~/.cua-driver-rs directory variable) rather than
matching the path alone; change the case pattern to require both the shared path
and the Rust marker (or perform an explicit if [[ -d "$HOME_DIR" || -d
"$HOME_DIR/.cua-driver-rs" ]] check) before rm -f "$USER_BIN_LINK" and the log,
and apply the same fix to the other similar blocks that match
"/Applications/CuaDriver.app" elsewhere in the file (the other case blocks that
currently include that path).

---

Outside diff comments:
In `@libs/cua-driver-rs/Skills/cua-driver-rs/SKILL.md`:
- Around line 114-121: Update the fenced code block in SKILL.md that shows CLI
examples so it includes a language identifier (e.g., change the opening ``` to
```bash or ```shell) to enable proper syntax highlighting for the commands (the
block containing "cua-driver serve", "cua-driver launch_app ...", "cua-driver
get_window_state ...", "cua-driver click ...", "cua-driver stop").

In `@libs/cua-driver/scripts/uninstall.sh`:
- Around line 78-80: The option parsing currently treats "--backend=swift" as a
no-op but doesn't record the user's explicit choice, so later auto-selection
still enables USE_RUST_BACKEND; update the "--backend=swift" case to record the
explicit choice (e.g., set EXPLICIT_BACKEND="swift" or EXPLICIT_SWIFT=1) instead
of only shifting, and then modify the auto-select logic that sets
USE_RUST_BACKEND (the branch that currently enables Rust automatically) to check
for that explicit marker and skip enabling Rust when the user explicitly chose
Swift; ensure references to USE_RUST_BACKEND and the new
EXPLICIT_BACKEND/EXPLICIT_SWIFT symbol are used consistently (also apply the
same change in the corresponding parsing block referenced later).

---

Nitpick comments:
In `@libs/cua-driver-rs/crates/mcp-server/src/protocol.rs`:
- Around line 188-209: Replace the long escaped multi-line format! string with a
raw string literal (e.g., use r#"..."#) inside the same format! call so you can
remove all backslash continuations and escaped quotes, preserving the
interpolation placeholders {tree_kind} and {platform_skill_pointer}; update the
format! invocation around that large text (the existing format!(...)) to use the
raw string content for readability while keeping the same placeholders and
returning value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: beaef113-b248-4eab-a674-bb057d1b4b57

📥 Commits

Reviewing files that changed from the base of the PR and between 23a9c8a and 7ab537c.

⛔ Files ignored due to path filters (1)
  • libs/cua-driver-rs/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • .github/workflows/cd-rust-cua-driver.yml
  • docs/content/docs/cua-driver/guide/getting-started/installation.mdx
  • libs/cua-driver-rs/Skills/cua-driver-rs/MACOS.md
  • libs/cua-driver-rs/Skills/cua-driver-rs/SKILL.md
  • libs/cua-driver-rs/crates/cua-driver/src/bundle.rs
  • libs/cua-driver-rs/crates/cua-driver/src/cli.rs
  • libs/cua-driver-rs/crates/mcp-server/src/protocol.rs
  • libs/cua-driver-rs/crates/platform-linux/src/tools/impl_.rs
  • libs/cua-driver-rs/crates/platform-macos/src/tools/click.rs
  • libs/cua-driver-rs/crates/platform-macos/src/tools/screenshot.rs
  • libs/cua-driver-rs/crates/platform-windows/src/capture.rs
  • libs/cua-driver-rs/crates/platform-windows/src/overlay.rs
  • libs/cua-driver-rs/crates/platform-windows/src/tools/impl_.rs
  • libs/cua-driver-rs/crates/platform-windows/src/uia/mod.rs
  • libs/cua-driver-rs/crates/platform-windows/src/uia/windows_enum.rs
  • libs/cua-driver-rs/scripts/install-local.ps1
  • libs/cua-driver/scripts/_uninstall-rust.sh
  • libs/cua-driver/scripts/uninstall.ps1
  • libs/cua-driver/scripts/uninstall.sh
💤 Files with no reviewable changes (2)
  • libs/cua-driver/scripts/_uninstall-rust.sh
  • libs/cua-driver-rs/crates/cua-driver/src/cli.rs

Comment on lines +373 to +375
```
osascript -e 'tell application "<App Name>" to activate'
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language identifier to code block.

The fenced code block showing the osascript command should specify bash or shell as the language identifier for proper syntax highlighting and tooling support.

📝 Proposed fix
-```
+```bash
 osascript -e 'tell application "<App Name>" to activate'
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 373-373: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver-rs/Skills/cua-driver-rs/MACOS.md` around lines 373 - 375, The
fenced code block that contains the osascript command (the line: osascript -e
'tell application "<App Name>" to activate') needs a language identifier for
proper highlighting; update the backtick fence from ``` to ```bash (or ```shell)
so the block starts with ```bash and retains the same command content inside (in
the MACOS.md code block showing the osascript invocation).

Comment on lines +414 to +416
```
get_window_state({pid, window_id, javascript: "document.title"})
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language identifier to code block.

The fenced code block showing the get_window_state command should specify bash or shell as the language identifier.

📝 Proposed fix
-```
+```bash
 get_window_state({pid, window_id, javascript: "document.title"})
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 414-414: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @libs/cua-driver-rs/Skills/cua-driver-rs/MACOS.md around lines 414 - 416,
Update the fenced code block that contains get_window_state({pid, window_id,
javascript: "document.title"}) to include a shell language identifier by
changing the opening backticks to bash (or sh) so the snippet is
highlighted as shell/bash.


</details>

<!-- fingerprinting:phantom:triton:puma -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +152 to +166
# Only remove ~/.local/bin/cua-driver when it resolves into a
# cua-driver-rs install. Post-rename, the Rust install lives at
# /Applications/CuaDriver.app — the SAME path the Swift driver uses,
# with the same bundle id `com.trycua.driver`. Path-based detection
# alone can't distinguish them. We rely on the presence of $HOME_DIR
# (~/.cua-driver-rs/) — the Rust-specific state dir — as the marker
# that this is a Rust install. Pre-rename installs at
# /Applications/CuaDriverRs.app are still cleaned up unambiguously
# by path.
if [[ -L "$USER_BIN_LINK" ]]; then
RESOLVED="$(resolve_link "$USER_BIN_LINK")"
case "$RESOLVED" in
*"CuaDriverRs.app"*|*"/Applications/CuaDriver.app"*|*"$HOME_DIR"*|*".cua-driver-rs"*)
rm -f "$USER_BIN_LINK"
log "removed $USER_BIN_LINK -> $RESOLVED"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don't use /Applications/CuaDriver.app as a Rust-only discriminator.

That path is shared by Swift and Rust on macOS. In the Rust uninstall branch it makes a Swift-only install look like Rust, so --experimental-rust can remove the shared app bundle and scrub matching Claude registrations even though the script says Swift won't be touched. Gate the shared-bundle case on a Rust-specific signal instead of the path alone.

Also applies to: 219-231, 314-319

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver/scripts/uninstall.sh` around lines 152 - 166, The uninstall
script currently treats "/Applications/CuaDriver.app" as a Rust-only indicator
which can match Swift installs; update the logic around USER_BIN_LINK resolution
(the block using resolve_link and the case patterns that include
"/Applications/CuaDriver.app") to only remove the shared bundle when a
Rust-specific marker is present (e.g., check for HOME_DIR or the
~/.cua-driver-rs directory variable) rather than matching the path alone; change
the case pattern to require both the shared path and the Rust marker (or perform
an explicit if [[ -d "$HOME_DIR" || -d "$HOME_DIR/.cua-driver-rs" ]] check)
before rm -f "$USER_BIN_LINK" and the log, and apply the same fix to the other
similar blocks that match "/Applications/CuaDriver.app" elsewhere in the file
(the other case blocks that currently include that path).

Six findings, all valid:

1. SKILL.md:114 — added `bash` language identifier to the canonical-
   workflow fenced code block (MD040 lint + syntax highlighting).
2. MACOS.md:373 — added `bash` identifier to the osascript activate
   fallback fence.
3. MACOS.md:414 — added `bash` identifier to the
   get_window_state-with-javascript example fence.
4. uninstall.sh:78-80 — `--backend=swift` was silently overridden by
   the auto-Rust-on-non-Darwin branch (the doc calls it an "explicit
   no-op default" but the code ignored the explicit signal). Added a
   BACKEND_EXPLICIT flag set by every `--backend=*`/`--experimental-rust`
   arm; the auto-Rust dispatch checks it and skips when the user
   pinned a backend.
5. uninstall.sh — `/Applications/CuaDriver.app` is shared between
   Swift and Rust on macOS (same bundle id `com.trycua.driver` since
   cua-driver-rs ≥ 0.2.4), so the prior Rust-branch logic could
   delete a Swift-only Mac's bundle, symlink, and Claude MCP
   registrations on a stray `uninstall.sh --experimental-rust`.
   Added a $RUST_INSTALL_PRESENT marker computed up-front from
   unambiguous Rust artifacts (HOME_DIR, legacy CuaDriverRs.app,
   LaunchAgent plist, systemd unit) and gated every shared-path
   removal on it:
     - CLI symlink case branch (split into "unambiguous Rust paths"
       and "shared path; require marker")
     - .app bundle removal (legacy unconditionally; canonical only
       when marker present)
     - Claude MCP scrub (the Python heredoc now reads
       RUST_INSTALL_PRESENT from env and gates the
       `/Applications/CuaDriver.app` match on it; unambiguous Rust
       anchors still match unconditionally)
6. protocol.rs:188-209 — converted AGENT_INSTRUCTIONS format! string
   to a raw string literal (r#"..."#). Drops the backslash line
   continuations + escaped backticks; identical runtime output, much
   easier to read.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@f-trycua
f-trycua merged commit c52d850 into main May 23, 2026
7 of 9 checks passed
@f-trycua
f-trycua deleted the agent-guidance-refactor branch May 23, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant