agentsclimarketplace

Cua vision hybrid control

Skill ChrisLamDev/cua-desktop-automation-skills/skills/cua-vision-hybrid-control

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-vision-hybrid-control

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

Hybrid control loop using Cua Driver (Accessibility) + Vision AI (Screenshot Analysis) for macOS desktop apps. Full pipeline: screencapture → vision_analyze → Cua hotkey/click → screencapture verify.

SKILL.md

10.3 KB, as published. Nobody here has run it

Cua + Vision Hybrid Control

時機

當你需要自動化操作 macOS desktop app,但:

  • Cua Driver 嘅 AX element tree 唔夠完整(例如 Safari 只出 MenuBar,唔出 content)
  • Pixel click 嘅 window-local vs screen coordinate mapping 唔準
  • 需要 adaptive vision-based automation loop

Pipeline (支援兩種連接模式)

Mode A: MCP (正常 — 自動 reconnect 需 context 一致)

MCP tools 直接 call → 最快

cua-hotkey / cua-type_text / cua-press_key → screencapture → vision_analyze verify

Mode B: CLI direct (fallback — context compaction/斷線都 work)

cua-driver call stdin JSON pipe,唔依賴 MCP 連接

screencapture → vision_analyze →
echo '{"pid":PID,"keys":["cmd","l"]}' | cua-driver call hotkey →
echo '{"pid":PID,"text":"..."}' | cua-driver call type_text →
echo '{"pid":PID,"key":"return"}' | cua-driver call press_key →
screencapture → vision_analyze verify

場景切換: Hermes session 內第一句 call MCP 就得。Context compaction 後 daemon 仲喺度但 MCP client 斷咗 → 轉 CLI direct mode。

步驟

1. 確認 Cua Driver 狀態

cua-driver status
cua-driver permissions status --json  # accessibility + screen_recording = true

2. Permission bypass

如果未 grant,用 env var 跳過 gate:

CUA_DRIVER_RS_PERMISSIONS_GATE=0 cua-driver serve

bypass 後 AX tree / screenshot 可能唔完整。

3. 截圖(用 Terminal TCC)

screencapture -x /tmp/hybrid_step.png

4. Vision 分析

vision_analyze(
  image_url="/tmp/hybrid_step.png",
  question="目標UI元件嘅坐標範圍?"
)

5. Cua 操作

Hotkey(最可靠):

echo '{"jsonrpc":"2.0","id":1,"method":"tools/call",
  "params":{"name":"hotkey",
    "arguments":{"pid":PID,"keys":["cmd","l"]}}}' | cua-driver mcp

Pixel Click(window-local coordinate!):

echo '{"jsonrpc":"2.0","id":1,"method":"tools/call",
  "params":{"name":"click",
    "arguments":{"pid":PID,"x":X,"y":Y}}}' | cua-driver mcp

Press key(dispatch 去 pid,唔 steal focus):

echo '{"jsonrpc":"2.0","id":1,"method":"tools/call",
  "params":{"name":"press_key",
    "arguments":{"pid":PID,"key":"escape"}}}' | cua-driver mcp

6. Verify

每次操作後都再截圖 + vision_analyze 驗證。

🏆 實戰驗證 2026-06-29:完整端到端 Computer Use 循環

測試場景

Safari → Google → 搜尋 "Hermes Agent" → 確認第一名結果係 hermes-agent.org ✅

關鍵發現

  1. cua-driver call CLI mode 係 MCP fallback 最佳方案 — 唔需要 MCP connection,直接 echo '{"pid":N,"keys":["cmd","l"]}' | cua-driver call hotkey。context compaction 後 MCP 斷線時用呢個模式。
  2. type_text 回傳 path:"key_events" 唔係 path:"ax" 都照樣 work — CGEvent fallback 插入文字後按 Return 都可以令 page navigate。
  3. 唔需要 osascript bring Safari to front — hotkey dispatch 去 pid 就夠,唔 steal focus。
  4. 每次 operation 後 sleep 0.3-3s 好重要 — 尤其係 type_text 同 Return 之間要等 browser 處理完。
  5. cua-driver call list_windows pid=N 用 stdin JSON pipeecho '{"pid":N}' | cua-driver call list_windows

完整測試日誌

Step 1: screencapture → vision_analyze → 桌面 Finder ✅
Step 2: hotkey cmd+l → type_text google.com → return → verify Google 首頁 ✅
Step 3: type_text "Hermes Agent" → return → verify 搜尋結果頁面 ✅

成個 loop 由 screenshot → vision → action → verify 完整閉環,process 自始至終冇斷過。

Safari AX Tree 限制

Safari window state 只出 MenuBar items(~530 elements),唔出 content 嘅 AXTextField/AXWebArea。 解決:用 AppleScript browser navigation,或用 Cua hotkey Cmd+L focus URL bar。 實戰證明:Cmd+L 有時會觸發 system shortcut 而非 Safari URL bar(尤其係 Bluetooth control panel 彈出時)。 解決:先 click Safari content area(x=400,y=250)focus window,再用 Cmd+L。

type_text 實戰模式

Cua Driver 嘅 type_text 支援兩種 mode:

  • AX path ("path":"ax"):插入 focused AXTextField(最準確)
  • CGEvent fallback ("path":"key_events"):無 focused element 時用,可加 delay_ms 參數 實戰中 type_text + Return 成功令 Safari navigate 去 URL。 經驗: 即使 type_text 回傳 "path":"key_events"(CGEvent fallback mode),文字仍然成功輸入 URL bar。key_events != fail。

cua-driver call CLI syntax(stdio pipe + 輸出注意)

MCP 斷線時嘅最佳替代方案。

🚨 Critical: Action Tools Return Text, Not JSON

cua-driver call hotkey/type_text/press_key/click 呢啲 action tools 回傳 human-readable text,唔係 JSON

list_windows / get_window_state 呢啲 discovery tools 回傳 JSON。

呢個 inconsistency 係已知嘅 API 設計問題(已準備 GitHub PR fix)。用「python 方式 parsing」—— 先 try JSON decode,fail 咗就當 text 處理。

如果直接寫 bash,留意 output 係 text:

# hotkey → "Pressed cmd+l on pid 4354.\n\n🪟 Action opened new window(s): Safari"
echo '{"pid":4354,"keys":["cmd","l"]}' | cua-driver call hotkey

# type_text → "{\n  \"characters\": 22,\n  \"path\": \"ax\"\n}" (JSON!)
echo '{"pid":4354,"text":"hello"}' | cua-driver call type_text

# press_key → "✅ Pressed return on pid 4354."
echo '{"pid":4354,"key":"return"}' | cua-driver call press_key

# click → "✅ Posted click to pid 4354."
echo '{"pid":4354,"x":800,"y":334}' | cua-driver call click

推薦做法:用 temp file pipe 代替 inline echo(避免 shell escaping bug):

cat /tmp/args.json | cua-driver call hotkey
# /tmp/args.json = {"pid":4354,"keys":["cmd","l"]}

Python 做法:用 core.py 嘅 cua_call() — 自動 handle text/JSON 雙重輸出:

from hybrid_vision_loop.core import cua_call
result = cua_call("hotkey", {"pid": 4354, "keys": ["cmd", "l"]})
# result = {"status": "ok", "raw_text": "Pressed cmd+l on pid 4354."}

Permission bypass 完整流程

# Step 1: 確認 daemon 已停
cua-driver stop

# Step 2: 用 env bypass 起 MCP(唔使 pre-grant permissions)
export CUA_DRIVER_RS_PERMISSIONS_GATE=0
cua-driver mcp

# Step 3: 用 raw stdio 測試 tool 是否運作
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call",
  "params":{"name":"get_screen_size","arguments":{}}}' | cua-driver mcp

# 註:bypass 後 screencapture 用 Terminal TCC(通常已有 screen recording grant)

完整端到端 Computer Use Demo(已實戰驗證)

Safari → Google → 搜尋 "Hermes Agent" → 確認結果 ✅

完整指令序列(實戰 work)

# === STEP 1: 確認 daemon 狀態 ===
cua-driver status                    # 確認 daemon running
screencapture -x /tmp/s1.png         # 截圖現狀
# → vision_analyze 確認目前畫面

# === STEP 2: 導航去 Google ===
# Cmd+L focus Safari URL bar
echo '{"pid":SAFARI_PID,"keys":["cmd","l"]}' | cua-driver call hotkey
sleep 0.5
# Type URL
echo '{"pid":SAFARI_PID,"text":"https://www.google.com"}' | cua-driver call type_text
sleep 0.3
# Press Return
echo '{"pid":SAFARI_PID,"key":"return"}' | cua-driver call press_key
sleep 3
# Verify
screencapture -x /tmp/s2.png
# → vision_analyze 確認 Google 首頁 ✅

# === STEP 3: 搜尋 "Hermes Agent" ===
echo '{"pid":SAFARI_PID,"text":"Hermes Agent"}' | cua-driver call type_text
sleep 0.3
echo '{"pid":SAFARI_PID,"key":"return"}' | cua-driver call press_key
sleep 3
screencapture -x /tmp/s3.png
# → vision_analyze 確認搜尋結果頁面 ✅

System-level dialogs(Edge permission prompt)

唔屬於任何 pid 嘅 child window,dispatch 去 pid 會 miss。 解決:用 AppleScript 或手動 dismiss。

AppleScript keystroke 限制

macOS SIP/TCC block osascript keystroke — 用 Cua hotkey 代替。

Hermes MCP connection caching

第一次連線 fail 後 cache 做 unreachable 直到 session 結束。 解決:

  • raw stdio pipe: echo '...' | cua-driver mcp
  • delegate_task spawn 新 context
  • 唔好糾纏 MCP unreachable

Window-local vs Screen coordinates (with Retina scaling)

Cua Driver pixel click 嘅 (x,y) 係 window-local points,唔係 screen pixels。

Retina M1 嘅要點:

  • screencapture -x 出 3200×1800 pixels(backing store resolution)
  • list_windows 回傳嘅 bounds 係 logical points(1600×900)
  • scale_factor = 2.0
  • 換算公式:
    • window_local_x = (screenshot_pixel_x / scale_factor) - window_bounds.x
    • reverse: screenshot_pixel_x = (window_local_x + window_bounds.x) * scale_factor

實戰驗證 2026-06-29:

  • Safari window bounds = (0.0, 30.0) 1600.0×796.0 logical points
  • Window-local click at (800.0, 334.32) → 成功 hit Google search bar
  • 然後 type "pixel click test" → text 正確顯示 + autosuggestions 出現 ✅

證明 CoordinateConverter 數學完全正確。

# 正確做法
cc = CoordinateConverter(screen_size=(1600, 900), scale_factor=2.0)
wx, wy = cc.screenshot_to_window(sx, sy, window_bounds)
# 然後用 (wx, wy) 去 cua-driver click

常用 shortcuts

  • Cmd+L: Safari/Chrome URL bar focus
  • Cmd+T: New tab
  • Cmd+W: Close tab/window
  • Cmd+R: Refresh
  • Escape: Dismiss dialog
  • Return/Enter: Confirm

陷阱

  1. Action tools 回傳 text 唔係 JSONcua-driver call hotkey/click/press_key 回傳 human-readable text。只有 list_windows/get_window_state 回傳 JSON。用 Python cua_call() 自動處理。
  2. Pixel click coordinates — Cua Driver 係 window-local space,唔係 screen space。要用 list_windows 攞 bounds 換算。Retina M1 有 2x scaling。
  3. Permission dialog 係 system-level — dispatch 去 pid 會 miss。用 AppleScript 或手動 dismiss。
  4. Safari 多 windows — 每次操作可能產生新 window。用 list_windows(pid) check 最新 window_id。
  5. screencapture filesize — 1600×900 PNG ~400KB-1MB。每次 overwrite 舊 file。
  6. MCP unreachable caching — 第一次 fail 後成個 session cache。用 raw stdio pipe bypass。

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.