feat(cua-driver-rs): agent-guidance refactor + uninstall converge + warnings cleanup - #1665
Conversation
…-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>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis 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. ChangesUninstall Consolidation and Installation Fixes
Skill Documentation Restructuring and Protocol Updates
CLI Extensions and Supporting Infrastructure
Tool Documentation Refinements and Code Quality
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 winAdd language identifier to code block.
The fenced code block showing CLI command examples should specify
bashorshellas 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.mdaround 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 openingtobash 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 winConsider 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⛔ Files ignored due to path filters (1)
libs/cua-driver-rs/Cargo.lockis excluded by!**/*.lock📒 Files selected for processing (19)
.github/workflows/cd-rust-cua-driver.ymldocs/content/docs/cua-driver/guide/getting-started/installation.mdxlibs/cua-driver-rs/Skills/cua-driver-rs/MACOS.mdlibs/cua-driver-rs/Skills/cua-driver-rs/SKILL.mdlibs/cua-driver-rs/crates/cua-driver/src/bundle.rslibs/cua-driver-rs/crates/cua-driver/src/cli.rslibs/cua-driver-rs/crates/mcp-server/src/protocol.rslibs/cua-driver-rs/crates/platform-linux/src/tools/impl_.rslibs/cua-driver-rs/crates/platform-macos/src/tools/click.rslibs/cua-driver-rs/crates/platform-macos/src/tools/screenshot.rslibs/cua-driver-rs/crates/platform-windows/src/capture.rslibs/cua-driver-rs/crates/platform-windows/src/overlay.rslibs/cua-driver-rs/crates/platform-windows/src/tools/impl_.rslibs/cua-driver-rs/crates/platform-windows/src/uia/mod.rslibs/cua-driver-rs/crates/platform-windows/src/uia/windows_enum.rslibs/cua-driver-rs/scripts/install-local.ps1libs/cua-driver/scripts/_uninstall-rust.shlibs/cua-driver/scripts/uninstall.ps1libs/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
| ``` | ||
| osascript -e 'tell application "<App Name>" to activate' | ||
| ``` |
There was a problem hiding this comment.
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).
| ``` | ||
| get_window_state({pid, window_id, javascript: "document.title"}) | ||
| ``` |
There was a problem hiding this comment.
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 -->
| # 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" |
There was a problem hiding this comment.
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>
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.ps1now self-elevates via UAC when it detects an-AutoStartinstall (thecua-driver-servetask atRunLevel=Highestplus the High-IL daemon it spawns can't be torn down from a non-elevated same-user shell — silentAccess Deniedonschtasks /DeleteandStop-Processleft dangling state otherwise).uninstall.shinlines what_uninstall-rust.shused to do — single canonical script per shell, mirroringuninstall.ps1's shape._uninstall-rust.shdeleted; 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 -Rawdefaults 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 sopost-install-hints.txtstays BOM-free.3.
chore(cua-driver-rs): clean up 30 build warnings in -p cua-driver path(5986430b)cargo build --release -p cua-driverwas 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 externalUIA_*ControlTypeIdconstants.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:
MACOS.mdmirroring the existingWINDOWS.md/LINUX.md/WEB_APPS.mdcompanion files.AGENT_INSTRUCTIONS(MCPinstructionsfield): converted fromconst &strtofn -> Stringtemplated per-host viacfg!(target_os = ...). macOS clients see "AX", Windows "UIA", Linux "AT-SPI" — Goose'sComputerControllerpattern. Added a closing line pointing skill-aware harnesses atSKILL.md+ the per-OS companion (free description-match hint for Claude Code / Codex / OpenClaw / OpenCode; ignored by Hermes / Cursor / generic MCP clients).click+screenshot(all 3 platforms): "prefer element_index over pixel coords" editorial onclick,max_image_dimension=1568default + pointer toget_window_stateonscreenshot. Per-call gating rather than per-session — Anthropic computer-use cookbook shape.Out of scope (flagged here for follow-up)
libs/cua-driver/Skills/cua-driver/SKILL.mdis 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.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-driverclean (zero warnings)install-local.ps1runs end-to-end on a freshly-wiped Windows VMNext steps:block shows proper•bullets and—em-dashesuninstall.ps1self-elevates correctly after an-AutoStartinstall (UAC prompt, fully removes daemon + task +~\.cua-driver\+ skill junctions)uninstall.shsmoke on macOS + Linux (needs reviewer host to verify — no Mac/Linux VM available this session)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 retestinstructionsfield from an MCP client (handshake response shows OS-templated content + skill pointer)🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Documentation
Refactoring