Skip to content
AI & Agents
Skill

/cua-driver

Drive a native macOS app via the cua-driver CLI (default) or MCP server — snapshot its AX tree, click/type/scroll by element_index, verify via re-snapshot. Use when the user asks you to operate, drive, automate, or perform a GUI task in a real macOS application on the host (e.g.

BOOST
From plugin
openloomi
1k28 skills10 commands
Install
$ npx -y skills add melandlabs/openloomi --skill cua-driver --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/cua-driver

Context preview

The summary Claude sees to decide when to auto-load this skill.

Drive a native macOS app via the cua-driver CLI (default) or MCP server — snapshot its AX tree, click/type/scroll by element_index, verify via re-snapshot. Use when the user asks you to operate, drive, automate, or perform a GUI task in a real macOS application on the host (e.g.

SKILL.md

cua-driver.SKILL.md
name: cua-driver
description: Drive a native macOS app via the cua-driver CLI (default) or MCP server — snapshot its AX tree, click/type/scroll by element_index, verify via re-snapshot. Use when the user asks you to operate, drive, automate, or perform a GUI task in a real macOS application on the host (e.g. "open a file in TextEdit", "navigate to /Applications in Finder", "click the Save button in Numbers").

cua-driver

Orchestrates macOS app automation via `cua-driver`. Whenever a user asks to drive a native macOS app, follow the loop in this skill rather than calling tools ad-hoc — the snapshot-before-action invariant is not optional and silently breaks if you skip it.

The no-foreground contract — read this first

**The user's frontmost app MUST NOT change.** This is the whole reason cua-driver exists. Users pay for the right to keep typing in their editor while an agent drives another app in the background. Violate this rule and every other nice property the driver gives you (no cursor warp, no Space switch, no window raise) stops mattering — you just shipped the Accessibility Inspector with extra steps.

Before running any shell command, ask: **"does this raise, activate, foreground, or make-key any app?"** If yes, don't run it. Every one of the commands below activates the target on macOS and is therefore forbidden unless the user **explicitly** asked for frontmost state:

  • **Every form of the `open` CLI — `open -a <App>`, `open -b

<bundle-id>`, `open <file>`, `open <path-to-App.app>`, `open <url>` — always activates.** macOS routes all forms through LaunchServices, which unhides and foregrounds the target regardless of whether you passed an app name, a bundle id, a document, a URL, or the bundle path itself. The activation happens even when the only intent was "start the process." **Never use `open` for any app launch.** This includes launching a just-built .app from a local build dir (e.g. `open build/Build/Products/Debug/MyApp.app`) — resolve the `CFBundleIdentifier` from `Info.plist` and use `launch_app` with that id. See "The narrow carve-out" below for why `launch_app` is safe even when the app internally calls `NSApp.activate`.

  • `osascript -e 'tell application "X" to activate'` —

activates by design. Same for `... to open <file>`, `... to launch`, and anything with `activate` in the tell block.

  • `osascript -e 'tell application "System Events" to ... frontmost'`

in a mutating form (setting `frontmost` rather than reading it).

  • AppleScript files that invoke `activate`, `launch`, or `open`

against the target app.

  • `cliclick` (moves the user's real cursor to the target coords

before clicking — a focus-steal-equivalent even if the app's window state is unchanged).

  • `CGEventPost` with `cghidEventTap` targeting a coordinate over

a different app's window (warps the cursor, possibly activates on hit).

  • `AppleScriptTask`, `NSAppleScript`, `Process` wrapping `osascript`

that contains any of the above.

  • `NSRunningApplication.activate(options:)` called from your own

helper binary — same class.

  • Dock clicks and any `open` invocation (see the first bullet —

every form of `open` goes through LaunchServices which activates, full stop).

  • **Keyboard shortcuts that semantically mean "focus here" —

most notably Chrome / Safari / Arc's `⌘L` (focus omnibox) and Finder's `⌘⇧G` (Go to Folder).** These aren't pure key events — the receiving app interprets "user wants to type here" as activation intent and raises its window to be key. Even when delivered to a backgrounded pid via `hotkey`, the downstream app pulls focus. **For omnibox navigation specifically**, the correct path is `launch_app({bundle_id: "com.google.Chrome", urls: ["https://…"]})` — no omnibox dance, no `⌘L`, no focus-steal. Do NOT try `set_value` on the omnibox: Chrome's commit logic requires a "user-typed" signal that neither an AX value write nor `CGEvent.postToPid` keystrokes supply from a backgrounded pid — the URL lands in the field but Return fires as a no-op. See `WEB_APPS.md` → "Navigate to a URL" for the full pattern. The general principle: a shortcut that says "put my cursor inside this app" is a focus-steal; a shortcut that says "do this thing" (copy, save, quit) is fine.

  • **Tab-switching shortcuts in browsers (`⌘1..⌘9`, `⌘]`, `⌘[`,

`⌘⇧[`, `⌘⇧]`) are visibly disruptive even when delivered to a backgrounded pid.** The app's key handler processes the shortcut, the window re-renders the new tab's content, the user sees their tabs flipping. There is no AX-only workaround: page content (HTML, form state, `AXWebArea`) populates only for the focused tab; inspecting a background tab requires activating it, which is the visible flip. Observed with Dia; the same mechanic applies to every Chromium-family browser (Chrome, Arc, Brave, Edge).

**Prefer the windows-over-tabs pattern**: for each URL you need to drive backgrounded, use `launch_app({bundle_id, urls: [url]})` — browsers open each URL in a new **window**. Each window has its own `window_id`, its own AX tree, and can be inspected / interacted with via `element_index` without activating or switching anything. Tabs are a UX grouping for humans; cua-driver workflows should default to windows. See `WEB_APPS.md` → "Tabs vs windows" for the full pattern.

Tab-title enumeration (read-only) IS safe — walk a window's toolbar AX tree for `AXTab` / `AXRadioButton` children and read their `AXTitle`s. Tab switching (activating one) is not.

Reading frontmost state is fine (`osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true'`). Mutating it is not.

**Corollary — the AXMenuBar rule.** `AXMenuBarItem` + AXPick dispatches at the AX layer regardless of which app is frontmost, but macOS's on-screen menu bar always belongs to the frontmost app. If you drive a *backgrounded* app's menu bar, the

Read more
Ships withopenloomi

OpenLoomi is an open-source AI coworker. It connects your work tools, understands what you’re working on, and tells you what needs your attention, why it matters, and what to do next. It’s your open-source Attention Agent.

Get the whole plugin
Stats
1,034
Stars
45
Forks
Active
Maintenance
TypeScript
Language
Apache-2.0
License
21d ago
Last commit
6mo ago
Created
5h ago
Added

Repo: melandlabs/openloomi

Other skills on openloomi.