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.
npx -y skills add ChrisLamDev/cua-desktop-automation-skills --skill cua-vision-hybrid-controlAssembled 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 ✅
關鍵發現
cua-driver callCLI mode 係 MCP fallback 最佳方案 — 唔需要 MCP connection,直接echo '{"pid":N,"keys":["cmd","l"]}' | cua-driver call hotkey。context compaction 後 MCP 斷線時用呢個模式。- type_text 回傳
path:"key_events"唔係path:"ax"都照樣 work — CGEvent fallback 插入文字後按 Return 都可以令 page navigate。 - 唔需要 osascript bring Safari to front — hotkey dispatch 去 pid 就夠,唔 steal focus。
- 每次 operation 後 sleep 0.3-3s 好重要 — 尤其係 type_text 同 Return 之間要等 browser 處理完。
cua-driver call list_windows pid=N用 stdin JSON pipe —echo '{"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_taskspawn 新 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.xreverse: 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
陷阱
- Action tools 回傳 text 唔係 JSON —
cua-driver call hotkey/click/press_key回傳 human-readable text。只有list_windows/get_window_state回傳 JSON。用 Pythoncua_call()自動處理。 - Pixel click coordinates — Cua Driver 係 window-local space,唔係 screen space。要用
list_windows攞 bounds 換算。Retina M1 有 2x scaling。 - Permission dialog 係 system-level — dispatch 去 pid 會 miss。用 AppleScript 或手動 dismiss。
- Safari 多 windows — 每次操作可能產生新 window。用
list_windows(pid)check 最新 window_id。 - screencapture filesize — 1600×900 PNG ~400KB-1MB。每次 overwrite 舊 file。
- MCP unreachable caching — 第一次 fail 後成個 session cache。用 raw stdio pipe bypass。