agentsclimarketplace

Cua driver macos automation

Skill ChrisLamDev/cua-desktop-automation-skills/skills/cua-driver-macos-automation

Router Learning System + macOS desktop automation skills for AI agents using Cua Driver — task routing, fallback chains, self-learning history.

Install
npx -y skills add ChrisLamDev/cua-desktop-automation-skills --skill cua-driver-macos-automation

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use Cua Driver for macOS desktop automation — launching apps, clicking UI elements, and controlling web pages via Accessibility API and JavaScript injection.

SKILL.md

6.9 KB, as published. Nobody here has run it

Cua Driver macOS Desktop Automation

When to use

  • User wants to automate macOS desktop apps (browsers, dev tools, etc.)
  • Need to click buttons, type text, or interact with web pages programmatically
  • macOS native Automation (AppleScript/cliclick) is blocked by OS restrictions
  • Want background (non-focus-stealing) desktop control

Version Updates

v0.6.8 (2026-06-28)

  • Hermes 原生支援! 執行 cua-driver mcp-config --client hermes 可直接輸出 Hermes config.yaml
  • 更新後要 restart daemon:cua-driver stop && cua-driver serve
  • TCC grants 理論上保留,但 macOS 可能出一次性 re-grant prompt
  • 如果 permission gate 卡住:cua-driver serve --no-permissions-gate
  • 新增 mcp-config 指令,支援 claude/codex/openclaw/cursor/opencode/hermes 等 client
  • Update 方法:cua-driver update --apply

Installation

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.sh)"

Permissions Setup

After installation, grant two macOS permissions:

  1. Accessibility — System Settings > Privacy & Security > Accessibility > tick CuaDriver
  2. Screen Recording — System Settings > Privacy & Security > Screen Recording > tick CuaDriver

Check status:

cua-driver permissions status

Trigger permission dialogs:

cua-driver permissions grant

Core Workflow

1. List running apps

cua-driver call list_apps

2. Launch app in background (no focus steal)

cua-driver call launch_app '{"bundle_id":"com.google.Chrome","urls":["https://gemini.google.com/app"]}'

Useful flags:

  • creates_new_application_instance: true — force new instance for concurrent sessions
  • urls — array of URLs/file paths to open

3. List windows to find window_id

cua-driver call list_windows '{"pid":<PID>}'
cua-driver call list_windows '{"on_screen_only":true}'

4. Snapshot + get UI tree (element_index)

cua-driver call get_window_state '{"pid":<PID>,"window_id":<WID>}'

Use query to filter large trees:

cua-driver call get_window_state '{"pid":<PID>,"window_id":<WID>,"query":"button|input|search"}'

5. Click by element_index

cua-driver call click '{"pid":<PID>,"window_id":<WID>,"element_index":<N>}'

6. Type text

cua-driver call type_text '{"pid":<PID>,"text":"Hello world"}'

7. Keyboard shortcuts

cua-driver call press_key '{"pid":<PID>,"key":"return"}'
cua-driver call hotkey '{"pid":<PID>,"keys":["cmd","c"]}'

Web Page Automation (Critical Path)

For interacting with web pages, element_index + type_text often fail due to web component shadow DOMs.

Enable JavaScript Apple Events (one-time per browser)

echo '{"action":"enable_javascript_apple_events","bundle_id":"com.google.Chrome","user_has_confirmed_enabling":true}' | cua-driver call page

This restarts the browser.

Execute JavaScript directly in the page

Method A — Short JS (inline):

echo '{"pid":<PID>,"window_id":<WID>,"action":"execute_javascript","javascript":"document.title"}' | cua-driver call page

Method B — Long JS (file → stdin pipe, preferred):

# Write JS to file first, then pipe via python for proper JSON escaping
cat /tmp/script.js | python3 -c "
import sys, json
js = sys.stdin.read()
payload = json.dumps({'pid': <PID>, 'window_id': <WID>, 'action': 'execute_javascript', 'javascript': js})
with open('/tmp/payload.json', 'w') as f:
    f.write(payload)
" && cat /tmp/payload.json | cua-driver call page

Method C — AppleScript fallback (for Safari when page tool times out):

osascript -e 'tell application "Safari" to do JavaScript (read posix file "/tmp/script.js") in current tab of window 1'

Other page actions

echo '{"pid":<PID>,"window_id":<WID>,"action":"get_text"}' | cua-driver call page
echo '{"pid":<PID>,"window_id":<WID>,"action":"query_dom","css_selector":"button"}' | cua-driver call page

React SPA Text Input Strategy (e.g. X.com, Medium)

For React controlled components, standard textContent assignment doesn't trigger React's state update. Use this 3-layer approach:

Layer 1 — execCommand('insertText'): Best for React Draft.js editors (X.com compose box).

const el = document.querySelector('[data-testid="tweetTextarea_0"]');
el.focus();
const sel = window.getSelection();
const range = document.createRange();
range.selectNodeContents(el);
sel.removeAllRanges();
sel.addRange(range);
document.execCommand('insertText', false, tweetText);

Layer 2 — Cua type_text (method='key_events'): Cua's type_text tool synthesises CGEvent keystrokes. Works when JS execCommand fails but may cause character duplication on SPA inputs. Use delay_ms: 10 for stability.

# Step 1: Click the input area first (use screenshot+vision to find pixel coords)
cua-driver call click '{"pid":<PID>,"window_id":<WID>,"x":<X>,"y":<Y>}'
# Step 2: Type text via keystroke synthesis
cua-driver call type_text '{"pid":<PID>,"text":"Your tweet content here","delay_ms":10}'

Layer 3 — ClipboardEvent paste: Dispatches a programmatic paste event that React Draft.js recognizes.

const dataTransfer = new DataTransfer();
dataTransfer.setData('text/plain', tweetText);
el.dispatchEvent(new ClipboardEvent('paste', {
  bubbles: true, cancelable: true, clipboardData: dataTransfer
}));

X.com specific:

  • Post button [data-testid="tweetButtonInline"] is disabled until React state has content
  • Pixel coordinates for clicking Post button typically ~(610, 420) on 1600×796 Safari window
  • After typing via type_text, use screenshot + vision_analyze to verify Post button state
  • If Safari shows "確定要離開此網頁嗎?" dialog, click "停留在網頁" to dismiss

Common Pitfalls

  1. Shell quoting: When passing JSON with long JS strings, prefer stdin piping.
  2. element_index is per-snapshot: Always call get_window_state before using element_index.
  3. Web apps ignore AX type_text: Chromium/Electron web inputs often don't implement kAXSelectedText.
  4. After "Allow JS Apple Events": Chrome restarts with a NEW pid.
  5. list_windows can return no windows: Some Electron apps report 0 windows on main PID but have windows on child Renderer process PID.
  6. hotkey vs press_key: Use hotkey for keyboard shortcuts (more reliable on Electron apps).
  7. Screenshot capture: v0.5.3 get_window_state does NOT include screenshot despite capture_mode. Use macOS screencapture -x /tmp/screen.png as fallback.

Verification

cua-driver status
cua-driver permissions status
cua-driver list-tools

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.