@bastani/atomic 0.9.28-alpha.3 → 0.9.28-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/README.md +3 -2
- package/dist/builtin/intercom/broker/broker.ts +90 -14
- package/dist/builtin/intercom/broker/paths.ts +4 -0
- package/dist/builtin/intercom/broker/socket-liveness.ts +32 -0
- package/dist/builtin/intercom/broker/socket-replacement-lock.ts +104 -0
- package/dist/builtin/intercom/broker/spawn.ts +108 -63
- package/dist/builtin/intercom/index.bundle.mjs +114 -61
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +6 -0
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/subagents/skills/agent-browser/SKILL.md +1 -1
- package/dist/builtin/subagents/skills/cua-driver/BROWSER.md +60 -39
- package/dist/builtin/subagents/skills/cua-driver/EMBEDDING.md +119 -36
- package/dist/builtin/subagents/skills/cua-driver/LINUX.md +225 -183
- package/dist/builtin/subagents/skills/cua-driver/MACOS.md +120 -89
- package/dist/builtin/subagents/skills/cua-driver/README.md +16 -7
- package/dist/builtin/subagents/skills/cua-driver/RECORDING.md +85 -115
- package/dist/builtin/subagents/skills/cua-driver/RUNTIME.md +113 -0
- package/dist/builtin/subagents/skills/cua-driver/SKILL.md +55 -1071
- package/dist/builtin/subagents/skills/cua-driver/VISUAL.md +125 -0
- package/dist/builtin/subagents/skills/cua-driver/WINDOWS.md +145 -185
- package/dist/builtin/subagents/skills/cua-driver/WORKFLOW.md +173 -0
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +16 -0
- package/dist/builtin/workflows/README.md +1 -1
- package/dist/builtin/workflows/builtin/{chunk-aqv8ny38.js → chunk-9ywkdsa9.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-p6jagvyf.js → chunk-bnz4knhy.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-br4ac9a3.js → chunk-dx5sjaxe.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-p3xmajmj.js → chunk-v4scsq3y.js} +41 -13
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +8 -2
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +6 -0
- package/dist/builtin/workflows/skills/impeccable/reference/audit.md +2 -1
- package/dist/builtin/workflows/skills/impeccable/reference/component-review.md +63 -0
- package/dist/builtin/workflows/skills/impeccable/reference/degraded/asset-producer.md +5 -0
- package/dist/builtin/workflows/skills/impeccable/reference/degraded/finish-reviewer.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/generate.md +101 -0
- package/dist/builtin/workflows/skills/impeccable/reference/harden.md +9 -0
- package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +3 -1
- package/dist/builtin/workflows/skills/impeccable/reference/mode-operate.md +21 -0
- package/dist/builtin/workflows/skills/impeccable/reference/mode-persuade.md +19 -0
- package/dist/builtin/workflows/skills/impeccable/reference/mode-read.md +21 -0
- package/dist/builtin/workflows/skills/impeccable/reference/new-work.md +19 -12
- package/dist/builtin/workflows/skills/impeccable/reference/region-map.md +26 -0
- package/dist/builtin/workflows/skills/impeccable/reference/routing.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/visualize.md +5 -5
- package/dist/builtin/workflows/skills/impeccable/scripts/VERSION +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +4 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/impeccable.cmd +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser-session.js +5 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +524 -4
- package/dist/builtin/workflows/skills/prompt-engineer/SKILL.md +1 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/claude_haiku_5_5.md +81 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +38 -14
- package/dist/builtin/workflows/src/index.js +38 -14
- package/dist/cli/startup-ui.d.ts +3 -2
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +19 -4
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/codemode-worker.js +2 -2
- package/dist/core/agent-session-compaction.d.ts +3 -3
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +5 -1
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +1 -0
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +4 -0
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +6 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +3 -2
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +5 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +13 -9
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +1 -0
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/agent-events.d.ts +2 -0
- package/dist/core/extensions/agent-events.d.ts.map +1 -1
- package/dist/core/extensions/agent-events.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +2 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/mcp-server-registry.d.ts +4 -1
- package/dist/core/extensions/mcp-server-registry.d.ts.map +1 -1
- package/dist/core/extensions/mcp-server-registry.js +7 -4
- package/dist/core/extensions/mcp-server-registry.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +19 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/session-events.d.ts +2 -0
- package/dist/core/extensions/session-events.d.ts.map +1 -1
- package/dist/core/extensions/session-events.js.map +1 -1
- package/dist/core/extensions/tool-types.d.ts +2 -0
- package/dist/core/extensions/tool-types.d.ts.map +1 -1
- package/dist/core/extensions/tool-types.js.map +1 -1
- package/dist/core/fast-model-variants.d.ts.map +1 -1
- package/dist/core/fast-model-variants.js +3 -2
- package/dist/core/fast-model-variants.js.map +1 -1
- package/dist/core/model-resolver-defaults.d.ts.map +1 -1
- package/dist/core/model-resolver-defaults.js +2 -0
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/nested-tool-calls.d.ts +1 -0
- package/dist/core/nested-tool-calls.d.ts.map +1 -1
- package/dist/core/nested-tool-calls.js +1 -0
- package/dist/core/nested-tool-calls.js.map +1 -1
- package/dist/core/provider-alias.d.ts.map +1 -1
- package/dist/core/provider-alias.js +8 -0
- package/dist/core/provider-alias.js.map +1 -1
- package/dist/core/provider-composer-internal.d.ts.map +1 -1
- package/dist/core/provider-composer-internal.js +6 -3
- package/dist/core/provider-composer-internal.js.map +1 -1
- package/dist/core/resource-loader-reload.d.ts.map +1 -1
- package/dist/core/resource-loader-reload.js +1 -0
- package/dist/core/resource-loader-reload.js.map +1 -1
- package/dist/core/resource-loader-types.d.ts +1 -0
- package/dist/core/resource-loader-types.d.ts.map +1 -1
- package/dist/core/resource-loader-types.js.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +7 -3
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.js +1 -1
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +55 -7
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/index.d.ts.map +1 -1
- package/dist/extensions/codemode/index.js +7 -0
- package/dist/extensions/codemode/index.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts +2 -0
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +2 -0
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/herdr/index.d.ts.map +1 -1
- package/dist/extensions/herdr/index.js +20 -2
- package/dist/extensions/herdr/index.js.map +1 -1
- package/dist/extensions/herdr/pane-owner.d.ts +7 -0
- package/dist/extensions/herdr/pane-owner.d.ts.map +1 -1
- package/dist/extensions/herdr/pane-owner.js +53 -11
- package/dist/extensions/herdr/pane-owner.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main-deferred-startup.d.ts +8 -0
- package/dist/main-deferred-startup.d.ts.map +1 -1
- package/dist/main-deferred-startup.js +6 -0
- package/dist/main-deferred-startup.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +11 -3
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +17 -14
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +5 -2
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -0
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +19 -8
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts +3 -2
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-boundary-message.js +7 -4
- package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +8 -2
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +4 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +10 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +3 -1
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-login.js +6 -0
- package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-routing.js +2 -2
- package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-bash-compact.js +2 -2
- package/dist/modes/interactive/interactive-bash-compact.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-dialogs.js +19 -2
- package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +7 -0
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-helpers.js +1 -1
- package/dist/modes/interactive/interactive-mode-helpers.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
- package/dist/modes/interactive/interactive-process-lifecycle.js +1 -1
- package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +7 -5
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +8 -1
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +1 -0
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-startup-trust.d.ts +6 -0
- package/dist/modes/interactive/interactive-startup-trust.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-startup-trust.js +15 -0
- package/dist/modes/interactive/interactive-startup-trust.js.map +1 -0
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +4 -0
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/program-status-reporter.d.ts +24 -0
- package/dist/modes/interactive/program-status-reporter.d.ts.map +1 -0
- package/dist/modes/interactive/program-status-reporter.js +96 -0
- package/dist/modes/interactive/program-status-reporter.js.map +1 -0
- package/dist/modes/interactive-engine/engine-child-liveness.d.ts +1 -0
- package/dist/modes/interactive-engine/engine-child-liveness.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-child-liveness.js +15 -1
- package/dist/modes/interactive-engine/engine-child-liveness.js.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.js +1 -0
- package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
- package/dist/modes/interactive-engine/engine-monitor.d.ts +4 -0
- package/dist/modes/interactive-engine/engine-monitor.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-monitor.js +17 -0
- package/dist/modes/interactive-engine/engine-monitor.js.map +1 -1
- package/dist/modes/interactive-engine/engine-quit-intent.d.ts +16 -0
- package/dist/modes/interactive-engine/engine-quit-intent.d.ts.map +1 -0
- package/dist/modes/interactive-engine/engine-quit-intent.js +27 -0
- package/dist/modes/interactive-engine/engine-quit-intent.js.map +1 -0
- package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.js +3 -1
- package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +1 -0
- package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.js +5 -0
- package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.js +19 -2
- package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
- package/dist/modes/interactive-engine/protocol.d.ts +19 -1
- package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
- package/dist/modes/interactive-engine/protocol.js +7 -0
- package/dist/modes/interactive-engine/protocol.js.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.d.ts +3 -0
- package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.js +7 -0
- package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +11 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +42 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-input-scheduler.js +2 -2
- package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +23 -6
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-provider-auth.js +1 -1
- package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
- package/docs/codemode.md +10 -6
- package/docs/compaction.md +1 -1
- package/docs/computer-use.md +9 -9
- package/docs/custom-provider/streaming.md +4 -0
- package/docs/environment-variables.md +2 -0
- package/docs/extensions/api-reference.md +1 -1
- package/docs/extensions/authoring.md +2 -0
- package/docs/extensions/events.md +8 -1
- package/docs/getting-started/first-session.md +1 -1
- package/docs/herdr.md +11 -2
- package/docs/json.md +6 -1
- package/docs/models/evals.md +34 -3
- package/docs/models.md +1 -1
- package/docs/providers.md +10 -0
- package/docs/sdk.md +8 -2
- package/docs/settings.md +2 -2
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +14 -0
- package/docs/workflows/authoring.md +3 -3
- package/examples/extensions/sandbox/package-lock.json +3 -3
- package/npm-shrinkwrap.json +67 -67
- package/package.json +8 -8
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# cua-driver
|
|
1
|
+
# cua-driver: macOS specifics
|
|
2
2
|
|
|
3
3
|
This file is the macOS-specific extension to `SKILL.md`.
|
|
4
4
|
The cross-platform core (snapshot invariant, CLI/MCP defaults,
|
|
@@ -8,12 +8,14 @@ you're driving an app on macOS.
|
|
|
8
8
|
|
|
9
9
|
## The no-foreground contract
|
|
10
10
|
|
|
11
|
-
**
|
|
11
|
+
**Background window actions must preserve the user's frontmost app.**
|
|
12
|
+
Foreground and desktop actions follow the authorization boundary in
|
|
13
|
+
[RUNTIME.md](RUNTIME.md#foreground-boundary). This is the whole
|
|
12
14
|
reason cua-driver exists. Users pay for the right to keep typing in
|
|
13
15
|
their editor while an agent drives another app in the background.
|
|
14
16
|
Violate this rule and every other nice property the driver gives
|
|
15
17
|
you (no cursor warp, no Space switch, no window raise) stops
|
|
16
|
-
mattering
|
|
18
|
+
mattering: you just shipped the Accessibility Inspector with extra
|
|
17
19
|
steps.
|
|
18
20
|
|
|
19
21
|
Before running any shell command, ask: **"does this raise,
|
|
@@ -22,21 +24,21 @@ Every one of the commands below activates the target on macOS and
|
|
|
22
24
|
is therefore forbidden unless the user **explicitly** asked for
|
|
23
25
|
frontmost state:
|
|
24
26
|
|
|
25
|
-
- **Every form of the `open` CLI
|
|
27
|
+
- **Every form of the `open` CLI: `open -a <App>`, `open -b
|
|
26
28
|
<bundle-id>`, `open <file>`, `open <path-to-App.app>`, `open
|
|
27
|
-
<url
|
|
29
|
+
<url>`: always activates.** macOS routes all forms through
|
|
28
30
|
LaunchServices, which unhides and foregrounds the target
|
|
29
31
|
regardless of whether you passed an app name, a bundle id, a
|
|
30
32
|
document, a URL, or the bundle path itself. The activation
|
|
31
33
|
happens even when the only intent was "start the process."
|
|
32
34
|
**Never use `open` for any app launch.** This includes launching
|
|
33
35
|
a just-built .app from a local build dir (e.g. `open
|
|
34
|
-
build/Build/Products/Debug/MyApp.app`)
|
|
36
|
+
build/Build/Products/Debug/MyApp.app`): resolve the
|
|
35
37
|
`CFBundleIdentifier` from `Info.plist` and use `launch_app`
|
|
36
38
|
with that id. See "The narrow carve-out" below for why
|
|
37
39
|
`launch_app` is safe even when the app internally calls
|
|
38
40
|
`NSApp.activate`.
|
|
39
|
-
- `osascript -e 'tell application "X" to activate'
|
|
41
|
+
- `osascript -e 'tell application "X" to activate'`:
|
|
40
42
|
activates by design. Same for `... to open <file>`,
|
|
41
43
|
`... to launch`, and anything with `activate` in the tell block.
|
|
42
44
|
- `osascript -e 'tell application "System Events" to ... frontmost'`
|
|
@@ -44,7 +46,7 @@ build/Build/Products/Debug/MyApp.app`) — resolve the
|
|
|
44
46
|
- AppleScript files that invoke `activate`, `launch`, or `open`
|
|
45
47
|
against the target app.
|
|
46
48
|
- `cliclick` (moves the user's real cursor to the target coords
|
|
47
|
-
before clicking
|
|
49
|
+
before clicking: a focus-steal-equivalent even if the app's
|
|
48
50
|
window state is unchanged).
|
|
49
51
|
- `CGEventPost` with `cghidEventTap` targeting a coordinate over
|
|
50
52
|
a different app's window (warps the cursor, possibly activates
|
|
@@ -52,13 +54,13 @@ build/Build/Products/Debug/MyApp.app`) — resolve the
|
|
|
52
54
|
- `AppleScriptTask`, `NSAppleScript`, `Process` wrapping `osascript`
|
|
53
55
|
that contains any of the above.
|
|
54
56
|
- `NSRunningApplication.activate(options:)` called from your own
|
|
55
|
-
helper binary
|
|
56
|
-
- Dock clicks and any `open` invocation (see the first bullet
|
|
57
|
+
helper binary: same class.
|
|
58
|
+
- Dock clicks and any `open` invocation (see the first bullet;
|
|
57
59
|
every form of `open` goes through LaunchServices which
|
|
58
60
|
activates, full stop).
|
|
59
|
-
- **Keyboard shortcuts that semantically mean "focus here"
|
|
61
|
+
- **Keyboard shortcuts that semantically mean "focus here":
|
|
60
62
|
most notably Chrome / Safari / Arc's `⌘L` (focus omnibox) and
|
|
61
|
-
Finder's `⌘⇧G` (Go to Folder).** These aren't pure key events
|
|
63
|
+
Finder's `⌘⇧G` (Go to Folder).** These aren't pure key events:
|
|
62
64
|
the receiving app interprets "user wants to type here" as
|
|
63
65
|
activation intent and raises its window to be key. Even when
|
|
64
66
|
delivered to a backgrounded pid via `hotkey`, the downstream app
|
|
@@ -78,7 +80,7 @@ Reading frontmost state is fine (`osascript -e 'tell application
|
|
|
78
80
|
"System Events" to get name of first application process whose
|
|
79
81
|
frontmost is true'`). Mutating it is not.
|
|
80
82
|
|
|
81
|
-
**Corollary
|
|
83
|
+
**Corollary: the AXMenuBar rule.** Do not manually drive a background
|
|
82
84
|
application's `AXMenuBarItem`: the visible macOS menu bar belongs to the
|
|
83
85
|
frontmost app, and command items may be disabled otherwise. Use `invoke_menu`
|
|
84
86
|
for a known application-menu path. It owns the necessary temporary activation,
|
|
@@ -89,7 +91,7 @@ menu bars” below.
|
|
|
89
91
|
|
|
90
92
|
**"Open \<app\>" in user speech means launch, not activate.**
|
|
91
93
|
`cua-driver launch_app` is the one correct path for process
|
|
92
|
-
startup
|
|
94
|
+
startup: it's idempotent (no-op on a running app), returns the
|
|
93
95
|
pid, and has an internal `FocusRestoreGuard` that catches
|
|
94
96
|
`NSApp.activate(ignoringOtherApps:)` calls the target makes during
|
|
95
97
|
`application(_:open:)` and clobbers the frontmost back to what it
|
|
@@ -104,43 +106,40 @@ is safe even for apps that normally foreground on media-load
|
|
|
104
106
|
| ------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
105
107
|
| Open / launch an app | `launch_app({bundle_id})` or `launch_app({bundle_id, urls:[...]})` | `open -a`, `osascript 'tell app … to launch/activate/open'` |
|
|
106
108
|
| Find a pid | `list_apps` or `launch_app`'s return | `pgrep`, `ps`, `osascript frontmost` |
|
|
107
|
-
| Enumerate an app's windows | `list_windows({pid})
|
|
109
|
+
| Enumerate an app's windows | `list_windows({pid})`: or read the `windows` array `launch_app` already returns | `osascript 'every window of app …'` |
|
|
108
110
|
| Move or resize one exact window | `set_window_frame({pid, window_id, x, y, width, height})` | `osascript` position/size writes or title-bar dragging |
|
|
109
111
|
| Click / type / scroll / keys | `click`, `type_text`, `scroll`, `press_key`, `hotkey` | `osascript`, `cliclick`, raw `CGEvent`, `open <url>` |
|
|
110
|
-
| Drag / drag-and-drop / marquee select | `drag({pid, from_x, from_y, to_x, to_y})` (pixel-only
|
|
111
|
-
| Screenshot | `
|
|
112
|
+
| Drag / drag-and-drop / marquee select | `drag({pid, window_id, from_x, from_y, to_x, to_y, delivery_mode:"foreground"})` (pixel-only and foreground-only: macOS AX has no semantic drag, and there is no background drag) | `cliclick dd:`, `osascript drag` |
|
|
113
|
+
| Screenshot | `get_window_state` (window) or authorized `get_desktop_state` (desktop) | `screencapture` |
|
|
112
114
|
| Quit an app | ask the user first, then `hotkey({pid, keys:["cmd","q"]})` | `kill`, `killall`, `pkill` |
|
|
113
115
|
| Hand a file/URL to an app | `launch_app({bundle_id, urls:[<path>]})` | `open -a <App> <path>`, `open <url>` |
|
|
114
116
|
|
|
115
117
|
### The narrow carve-out
|
|
116
118
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
to see X"). Reaching for it because a tool call returned something
|
|
121
|
-
confusing is wrong — that's the skill's classic foot-in-the-door
|
|
122
|
-
failure mode and it steals focus every time.
|
|
119
|
+
For authorized foreground input, use the Cua action's
|
|
120
|
+
`delivery_mode:"foreground"`. For requested persistent foreground state, use
|
|
121
|
+
`bring_to_front`. Neither requires a shell activation workaround.
|
|
123
122
|
|
|
124
123
|
When a cua-driver call surprises you, diagnose cua-driver first:
|
|
125
124
|
|
|
126
125
|
- **Empty `tree_markdown`?** `get_window_state` returns **both** the
|
|
127
|
-
AX tree and a screenshot by default
|
|
126
|
+
AX tree and a screenshot by default: there's nothing to configure and
|
|
128
127
|
no capture mode to pick. An empty tree means the surface isn't AX (a
|
|
129
128
|
non-AX surface: Electron/Chromium/canvas), and the response carries
|
|
130
|
-
`degraded: true
|
|
129
|
+
`degraded: true`, so act by **`px`** off the screenshot that's
|
|
131
130
|
already in the same response. `capture_mode` is **deprecated and
|
|
132
131
|
ignored** (still accepted so old callers don't error, but it has no
|
|
133
|
-
effect
|
|
132
|
+
effect; tree + screenshot come back regardless); don't reach for
|
|
134
133
|
`get_config` to "switch modes," there is no mode to switch.
|
|
135
134
|
- **`has_screenshot: false`?** The window capture failed (transient
|
|
136
135
|
race against a close, or the window has no backing store yet).
|
|
137
136
|
Re-snapshot; if persistent, pick a different `window_id` via
|
|
138
137
|
`list_windows`.
|
|
139
|
-
- **`
|
|
140
|
-
Re-snapshot the exact window and use the new `element_token
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
- **Sparse Chromium AX tree?** Retry `get_window_state` once
|
|
138
|
+
- **`stale_element_token` / no cached AX state?**
|
|
139
|
+
Re-snapshot the exact window and use the new `element_token`. A new
|
|
140
|
+
snapshot of that window invalidates older targets immediately; the refusal
|
|
141
|
+
names the current snapshots so you can tell whether you already hold one.
|
|
142
|
+
- **Sparse Chromium AX tree?** Retry `get_window_state` once: the
|
|
144
143
|
tree populates on second call.
|
|
145
144
|
|
|
146
145
|
Only after those are ruled out, and only if the user's action
|
|
@@ -152,30 +151,30 @@ briefly bring Chrome to the front because …").
|
|
|
152
151
|
|
|
153
152
|
There is no `ax`/`vision` capture toggle. **Every `get_window_state`
|
|
154
153
|
returns both the AX tree and a screenshot** (default), so verifying that
|
|
155
|
-
an action **landed** never means "go grab a screenshot"
|
|
154
|
+
an action **landed** never means "go grab a screenshot": it means
|
|
156
155
|
cross-check the tree diff against the pixels you already have in the same
|
|
157
156
|
response, and only switch _dispatch rung_ on a real signal:
|
|
158
157
|
|
|
159
|
-
1. **Re-snapshot and read the tree diff
|
|
158
|
+
1. **Re-snapshot and read the tree diff**: a changed `AXValue`, a new
|
|
160
159
|
element, a collapsed menu, a disabled button. If the tree shows the
|
|
161
160
|
change, you're done. When you only need the tree diff and don't need
|
|
162
|
-
fresh pixels, pass `include_screenshot:false` to skip the grab
|
|
161
|
+
fresh pixels, pass `include_screenshot:false` to skip the grab: a
|
|
163
162
|
**perf** knob, not a mode flip.
|
|
164
163
|
2. **Trust the screenshot and do an element px action** when the tree
|
|
165
|
-
**lies
|
|
164
|
+
**lies**: the action response carried `effect:"suspected_noop"`, the
|
|
166
165
|
re-snapshot came back `degraded` (empty tree), or the tree looks
|
|
167
166
|
unchanged/unreadable / disagrees with the pixels on a surface where
|
|
168
167
|
it's known to lie:
|
|
169
|
-
- **Canvas-backed editors
|
|
168
|
+
- **Canvas-backed editors**: Monaco (VSCode, Cursor), xterm, Figma,
|
|
170
169
|
WebGL. The AX tree shows the chrome but nothing for the canvas
|
|
171
170
|
content; a snapshot's tree can look unchanged after a successful
|
|
172
171
|
edit while the pixels show it landed.
|
|
173
|
-
- **Catalyst / iOS-on-Mac text views
|
|
172
|
+
- **Catalyst / iOS-on-Mac text views**: see "Known text-input
|
|
174
173
|
limits" above. `AXValue` can lag the rendered pixels or report the
|
|
175
174
|
placeholder while the field is actually populated.
|
|
176
175
|
|
|
177
176
|
On these surfaces you read the result off the screenshot already in the
|
|
178
|
-
response, then address the target by `x,y
|
|
177
|
+
response, then address the target by `x,y`: an **element px action**.
|
|
179
178
|
`px` is your **conscious switch to the pixel addressing path**, not a
|
|
180
179
|
different capture: the screenshot was always there, you just change _how
|
|
181
180
|
you address_ the target. The point is to catch the "type → AX-check
|
|
@@ -184,10 +183,10 @@ the surfaces that warrant it.
|
|
|
184
183
|
|
|
185
184
|
Rule of thumb:
|
|
186
185
|
|
|
187
|
-
- **element ax action** (default)
|
|
188
|
-
AND the first verify after it; you address by `[N]` `
|
|
186
|
+
- **element ax action** (default): the element lookup before a click
|
|
187
|
+
AND the first verify after it; you address by the `[N]` row's `element_token`
|
|
189
188
|
and read the tree diff.
|
|
190
|
-
- **element px action
|
|
189
|
+
- **element px action**: when the tree is unreadable / `suspected_noop`
|
|
191
190
|
/ `degraded` / disagrees with the pixels, or for pure visual
|
|
192
191
|
inspection (reading a chart). You address by `x,y` off the screenshot
|
|
193
192
|
that's already in the snapshot response.
|
|
@@ -198,27 +197,27 @@ Before every `Bash` call whose command line touches any macOS app
|
|
|
198
197
|
(launching, opening, clicking, typing, scripting, screenshotting),
|
|
199
198
|
run the self-check:
|
|
200
199
|
|
|
201
|
-
1. **Does this command foreground the target?** If yes
|
|
200
|
+
1. **Does this command foreground the target?** If yes: stop and
|
|
202
201
|
translate to the cua-driver equivalent from the mapping table.
|
|
203
202
|
2. **Does this command move the user's real cursor?** (`cliclick`,
|
|
204
203
|
any `CGEventPost` at `cghidEventTap` over another app's window).
|
|
205
|
-
If yes
|
|
204
|
+
If yes: stop; use `click({pid, x, y})` which routes per-pid
|
|
206
205
|
via SkyLight and never warps the cursor.
|
|
207
206
|
3. **Does this command bypass cua-driver entirely?** (`osascript`
|
|
208
207
|
mutating GUI state, AppleScript files, external helpers.) If
|
|
209
|
-
yes
|
|
208
|
+
yes: stop; find the cua-driver tool that does the intent.
|
|
210
209
|
|
|
211
210
|
If all three are "no," the command is safe. If you can't answer,
|
|
212
211
|
default to stop and ask rather than proceed. A single `open -a`
|
|
213
212
|
run by accident kills the demo, the trust, and the user's in-flight
|
|
214
213
|
editor state.
|
|
215
214
|
|
|
216
|
-
## Prerequisites
|
|
215
|
+
## Prerequisites: macOS
|
|
217
216
|
|
|
218
217
|
1. `cua-driver` is on `$PATH` (`which cua-driver`). If not, point the
|
|
219
218
|
user at `scripts/install-local.sh` and stop.
|
|
220
219
|
2. Start the daemon with `open -n -g -a CuaDriver --args serve` (the
|
|
221
|
-
recommended form
|
|
220
|
+
recommended form: goes through LaunchServices so TCC attributes
|
|
222
221
|
the process to CuaDriver.app). `cua-driver serve &` also works;
|
|
223
222
|
the CLI auto-relaunches through `open -n -g -a CuaDriver` when it
|
|
224
223
|
detects a wrong-TCC context (any IDE-spawned shell: Claude Code,
|
|
@@ -232,7 +231,7 @@ editor state.
|
|
|
232
231
|
tell the user to run `cua-driver permissions grant` and approve it.
|
|
233
232
|
- If Screen Recording is `false`, continue only when the task can be
|
|
234
233
|
completed and verified from the AX tree. Call `get_window_state` with
|
|
235
|
-
`include_screenshot:false` and use
|
|
234
|
+
`include_screenshot:false` and use `element_token` AX actions. Do not use
|
|
236
235
|
screenshots, pixel coordinates, or pixel-based verification.
|
|
237
236
|
- If the task materially needs pixels, stop and ask the user to run
|
|
238
237
|
`cua-driver permissions grant`. That command explains and deliberately
|
|
@@ -243,26 +242,26 @@ editor state.
|
|
|
243
242
|
the user should click **+**, add `/Applications/CuaDriver.app` (or
|
|
244
243
|
`/Applications/CuaDriverLocal.app`), enable it, and rerun the command.
|
|
245
244
|
|
|
246
|
-
## Resolve
|
|
245
|
+
## Resolve the requested application
|
|
247
246
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
247
|
+
Reuse a discovered live target when available. Otherwise use `launch_app`
|
|
248
|
+
when launch is requested or implied, then select the returned window. If the
|
|
249
|
+
window has not appeared yet, bound retries of `list_windows`.
|
|
251
250
|
|
|
252
|
-
- `launch_app({bundle_id: "com.apple.finder"})
|
|
253
|
-
- `launch_app({name: "Calculator"})
|
|
251
|
+
- `launch_app({bundle_id: "com.apple.finder"})`, preferred, unambiguous.
|
|
252
|
+
- `launch_app({name: "Calculator"})`, when bundle_id isn't known.
|
|
254
253
|
|
|
255
|
-
`launch_app` is a **hidden-launch primitive by design
|
|
254
|
+
`launch_app` is a **hidden-launch primitive by design**: that's the
|
|
256
255
|
entire point of cua-driver: agents drive apps in the background while
|
|
257
256
|
the user keeps typing in their real foreground app. The target's
|
|
258
257
|
window is initialized (AX tree fully populated, clickable via
|
|
259
|
-
`
|
|
258
|
+
`element_token`, the pid appears in `list_apps`) but not drawn on
|
|
260
259
|
screen. The driver never activates or unhides apps on its own; that
|
|
261
260
|
would violate the no-foreground contract the whole driver exists to
|
|
262
261
|
protect.
|
|
263
262
|
|
|
264
263
|
If the user explicitly wants the window visible (usually for a demo
|
|
265
|
-
or recording), they unhide it themselves
|
|
264
|
+
or recording), they unhide it themselves: Dock click, Cmd-Tab, or
|
|
266
265
|
Spotlight. Do not reach for `open` / `osascript activate` as a
|
|
267
266
|
shortcut to make the window visible; those paths break the backgrounded
|
|
268
267
|
invariant on every call, not just the call that "needed" the
|
|
@@ -270,7 +269,7 @@ foreground. Say out loud what the user needs to do ("click the
|
|
|
270
269
|
Todo app in your Dock to bring it forward") and let them do it.
|
|
271
270
|
|
|
272
271
|
Never shell out to **any** form of `open` (including `open
|
|
273
|
-
<path-to-App.app>` for a just-built binary
|
|
272
|
+
<path-to-App.app>` for a just-built binary: resolve the bundle id
|
|
274
273
|
from `Info.plist` and use `launch_app` with that), `osascript 'tell
|
|
275
274
|
app … to launch/open'`, or similar. Those paths activate the target,
|
|
276
275
|
bypass the driver's focus-restore guard, and require a Bash
|
|
@@ -280,7 +279,7 @@ permission prompt the agent loop shouldn't be burning on app launch.
|
|
|
280
279
|
|
|
281
280
|
The pixel click is routed through SkyLight's per-pid event path
|
|
282
281
|
(`SLEventPostToPid`), not the system HID stream. The dispatch recipe
|
|
283
|
-
is the backgrounded "noraise" sequence:
|
|
282
|
+
is the backgrounded "noraise" sequence: focus-without-raise
|
|
284
283
|
SLPS event records followed by an off-screen user-activation primer
|
|
285
284
|
and the real click. The target app becomes AppKit-active for event
|
|
286
285
|
routing but its window does **not** rise to the front of the
|
|
@@ -292,25 +291,43 @@ and the companion `FocusWithoutRaise.swift`.
|
|
|
292
291
|
### `delivery_mode` on the pointer family (macOS)
|
|
293
292
|
|
|
294
293
|
`click`, `double_click`, `right_click`, `drag`, and `scroll` accept
|
|
295
|
-
`delivery_mode` (`"background"` default / `"foreground"`)
|
|
294
|
+
`delivery_mode` (`"background"` default / `"foreground"`): matching the
|
|
296
295
|
breadth Windows and Linux already exposed (`type_text` / `press_key` /
|
|
297
296
|
`hotkey` carry it too). `"background"` is the SkyLight per-pid path above:
|
|
298
297
|
no raise, no focus steal. `"foreground"` briefly fronts the owning app,
|
|
299
|
-
acts, then restores the prior frontmost
|
|
298
|
+
acts, then restores the prior frontmost: the explicit last resort for a
|
|
300
299
|
surface that only accepts events while frontmost (the canvas/viewport/game
|
|
301
|
-
case below). Unmodified
|
|
300
|
+
case below). Unmodified `element_token` (AX) actions remain background-capable
|
|
302
301
|
and hold the no-foreground contract without the flag.
|
|
303
302
|
|
|
303
|
+
`drag` is the exception: macOS has no background drag. A window-scoped
|
|
304
|
+
`drag` needs `delivery_mode:"foreground"` and `window_id`; without them it
|
|
305
|
+
refuses with `background_unavailable` and sends nothing. The foreground drag
|
|
306
|
+
fronts the exact window, moves the physical pointer along the path, and then
|
|
307
|
+
restores the prior frontmost app. Use it only when a drag is the task, and
|
|
308
|
+
expect the hardware pointer to move.
|
|
309
|
+
|
|
310
|
+
A foreground window-scoped **pixel** `click`, `double_click`, or
|
|
311
|
+
`right_click` (`x`/`y` with `window_id`) is delivered like a desktop-scope click, not through the per-pid path: Cua Driver
|
|
312
|
+
activates the exact window (refusing with `foreground_unavailable` when that
|
|
313
|
+
window never becomes focused), moves the hardware pointer to the mapped
|
|
314
|
+
screen point, and posts through the HID event tap. The pointer stays at the
|
|
315
|
+
target afterward, matching Windows `SendInput` and X11 XTest foreground
|
|
316
|
+
clicks, and the prior frontmost app is restored. The result reports
|
|
317
|
+
`route: "global_input"` and says the pointer moved.
|
|
318
|
+
|
|
304
319
|
Modified clicks are the deliberate exception: pass
|
|
305
320
|
`delivery_mode:"foreground"` and a concrete `window_id`. macOS applications
|
|
306
321
|
can discard PID-routed modifier state after initially publishing a transient
|
|
307
322
|
selection, so Cua Driver refuses that background combination. The foreground
|
|
308
|
-
rung holds physical HID modifier keys around the click, restores the
|
|
309
|
-
|
|
310
|
-
|
|
323
|
+
rung holds physical HID modifier keys around the click, restores the prior
|
|
324
|
+
foreground app, and confirms list-like selection changes with a stable AX
|
|
325
|
+
readback. Element-addressed modified clicks also restore the hardware cursor;
|
|
326
|
+
pixel modified clicks leave it at the target like other foreground pixel
|
|
327
|
+
clicks.
|
|
311
328
|
|
|
312
329
|
macOS-specific residuals worth knowing (the rest of the capture/dispatch/
|
|
313
|
-
addressing params are a shared cross-platform contract
|
|
330
|
+
addressing params are a shared cross-platform contract: see `SKILL.md` →
|
|
314
331
|
_Cross-platform parameter contract_):
|
|
315
332
|
|
|
316
333
|
- **`check_permissions.prompt` is macOS-only and public calls are
|
|
@@ -334,37 +351,44 @@ _Cross-platform parameter contract_):
|
|
|
334
351
|
### Canvases, viewports, games (Blender, Unity, GHOST, Qt, wxWidgets)
|
|
335
352
|
|
|
336
353
|
Apps whose main surface is an OpenGL / Metal / Qt / wxWidgets
|
|
337
|
-
viewport expose **no useful AX tree
|
|
354
|
+
viewport expose **no useful AX tree**: the whole surface is one
|
|
338
355
|
opaque `AXGroup` or `AXWindow` from AX's perspective. Per-pid event
|
|
339
356
|
paths (`SLEventPostToPid`, `CGEvent.postToPid`) are filtered by the
|
|
340
|
-
viewport's own event-source check and silently dropped
|
|
357
|
+
viewport's own event-source check and silently dropped: the event
|
|
341
358
|
loop wants "real HID origin".
|
|
342
359
|
|
|
343
360
|
The working pattern:
|
|
344
361
|
|
|
345
|
-
1.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
event (~30 ms before the click). `cua-driver click` when the
|
|
350
|
-
target is frontmost automatically takes this path.
|
|
351
|
-
3. Accept that the real cursor visibly moves — `cghidEventTap` is
|
|
352
|
-
the system HID stream, the cursor warps to the click point.
|
|
362
|
+
1. Observe the target and the background route's refusal or lack of effect.
|
|
363
|
+
2. Obtain authorization for visible foreground control if not already given.
|
|
364
|
+
3. Retry only the necessary Cua action with `delivery_mode:"foreground"`,
|
|
365
|
+
then verify from fresh state. Do not inject raw CGEvents or use shell activation.
|
|
353
366
|
|
|
354
367
|
There is no backgrounded path that reaches these apps today.
|
|
355
368
|
|
|
356
369
|
### Known pixel-click limits
|
|
357
370
|
|
|
371
|
+
- **Toolkits that read the hardware pointer (Tk, some Java and game
|
|
372
|
+
toolkits)** derive a click's location from the real pointer position, not
|
|
373
|
+
from the delivered event. Background delivery never moves the pointer, so a
|
|
374
|
+
background pixel click lands wherever the pointer happens to be. When the
|
|
375
|
+
target maps a Tk library or Python's `_tkinter`, a background window pixel
|
|
376
|
+
click returns `background_unavailable` with `reason:
|
|
377
|
+
"pointer_reading_toolkit"`. Other pointer-reading apps cannot be detected
|
|
378
|
+
cheaply; their background result stays "not driver-verified" and says the
|
|
379
|
+
pointer was not moved. Retry with `delivery_mode:"foreground"`, which moves
|
|
380
|
+
the pointer first.
|
|
381
|
+
|
|
358
382
|
- **Chromium `<video>` play/pause**: pixel click is often rejected
|
|
359
383
|
by HTML5's click-to-play handler on some builds. Use keyboard
|
|
360
384
|
instead: `press_key({pid, key: "k"})` (YouTube) or
|
|
361
385
|
`press_key({pid, key: "space"})` (generic). Keyboard events
|
|
362
386
|
travel through a different auth envelope.
|
|
363
387
|
- **Pixel right-click on Chromium web content** coerces to a
|
|
364
|
-
left-click
|
|
388
|
+
left-click: a known Chromium renderer-IPC limitation that affects
|
|
365
389
|
every non-HID-tap synthesis path. For context menus on
|
|
366
390
|
AX-addressable elements (links, buttons, toolbar items), use
|
|
367
|
-
`right_click({pid,
|
|
391
|
+
`right_click({pid, element_token})` instead.
|
|
368
392
|
|
|
369
393
|
### Known text-input limits (Catalyst + Electron)
|
|
370
394
|
|
|
@@ -373,7 +397,7 @@ anything in `/Applications` that's actually `iOSAppOnMac.app`) and
|
|
|
373
397
|
**Electron** apps (VS Code's Monaco editor, Slack composer, Discord,
|
|
374
398
|
Linear), an AX `type_text` can't reach the rendered text view: the
|
|
375
399
|
`AXSetAttribute(kAXSelectedText)` write succeeds on the AX shim, but
|
|
376
|
-
the UIKit/Chromium view that owns the input never observes it
|
|
400
|
+
the UIKit/Chromium view that owns the input never observes it. On
|
|
377
401
|
Electron the shim _echoes the value straight back through `AXValue`_,
|
|
378
402
|
so a naive read-back "confirms" a value that isn't really there.
|
|
379
403
|
|
|
@@ -383,11 +407,11 @@ AX-path `type_text` on an Electron app returns `effect:"unverifiable"` +
|
|
|
383
407
|
false `effect:"confirmed"`.
|
|
384
408
|
(On Catalyst the AX value reads back unreadable, so it reports
|
|
385
409
|
unverified too.) Bottom line: on these surfaces **do not trust the AX
|
|
386
|
-
confirm
|
|
410
|
+
confirm. The screenshot in the same response is the only truth.**
|
|
387
411
|
|
|
388
|
-
Fix
|
|
389
|
-
`x,y` (no `
|
|
390
|
-
`type_text
|
|
412
|
+
Fix, in **one call**: `type_text({pid, window_id, x, y, text})`. Passing
|
|
413
|
+
`x,y` (no `element_token`) is the **element px action** form of
|
|
414
|
+
`type_text`: the tool pixel-clicks at `(x,y)` to give the Chromium /
|
|
391
415
|
UIKit renderer the real keyboard focus the AX layer can't, then types
|
|
392
416
|
into the now-focused field. Read `x,y` straight off the screenshot in
|
|
393
417
|
the `get_window_state` response (same convention as `click`). This is
|
|
@@ -399,22 +423,22 @@ content. Send Cmd+V only after that read-back succeeds.
|
|
|
399
423
|
|
|
400
424
|
0. **If the control is CLOSED, open it first.** A px focus-click won't
|
|
401
425
|
reliably _open and focus_ a closed control (a search button, a
|
|
402
|
-
collapsed field)
|
|
426
|
+
collapsed field): it lands on whatever is already focused (e.g.
|
|
403
427
|
the message composer), so your text leaks there. **AX-press to
|
|
404
428
|
open/activate the control first** (AX actions work in the
|
|
405
429
|
background), then px-type into the now-open field.
|
|
406
|
-
1. **`type_text({pid, window_id, x, y, text})
|
|
430
|
+
1. **`type_text({pid, window_id, x, y, text})`**: focus + type in a
|
|
407
431
|
single call. Re-snapshot and read the text off the screenshot to
|
|
408
432
|
confirm; the AX value can still lag on Catalyst/Electron.
|
|
409
433
|
2. Only if the keystrokes _still_ drop (a focus-polling app), escalate
|
|
410
434
|
that one `type_text` with `delivery_mode:"foreground"`.
|
|
411
435
|
|
|
412
|
-
The `x,y` (px) form is **mutually exclusive** with `
|
|
413
|
-
(ax)
|
|
436
|
+
The `x,y` (px) form is **mutually exclusive** with `element_token`
|
|
437
|
+
(ax): pass one or the other, not both. Why not `Cmd+V` / `hotkey`: a
|
|
414
438
|
keyboard combo does **not** focus a text field, and `hotkey` /
|
|
415
439
|
`press_key` no longer raise the window on their own (raising is gated
|
|
416
440
|
on `delivery_mode:"foreground"`, like every other tool). The reliable
|
|
417
|
-
move is the px form of `type_text
|
|
441
|
+
move is the px form of `type_text`: focus and type in one call.
|
|
418
442
|
|
|
419
443
|
## Navigating native menu bars (AXMenuBar)
|
|
420
444
|
|
|
@@ -426,6 +450,10 @@ application, resolves each immediate child from live AX state, uses only
|
|
|
426
450
|
on a best-effort basis.
|
|
427
451
|
It refuses missing, duplicate, disabled, or non-actionable segments and never
|
|
428
452
|
falls back to pixels.
|
|
453
|
+
When a path fails after the tool already opened a menu, it cancels that menu
|
|
454
|
+
and the refusal says whether any menu window it opened is still on screen. If
|
|
455
|
+
the refusal says the menu may still be open, press `escape` on the window
|
|
456
|
+
before other input.
|
|
429
457
|
|
|
430
458
|
```bash
|
|
431
459
|
cua-driver invoke_menu \
|
|
@@ -488,7 +516,10 @@ starting point for new browser workflows.
|
|
|
488
516
|
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
489
517
|
| macOS system-alert beep on `press_key` with no visible change | Target window is minimized; Return / Space / Tab commits don't establish real renderer focus on minimized windows | AX-click a clickable equivalent (Go button, Submit button, checkbox) instead of pressing the key; see "Keyboard commits on minimized windows" under the Browser section |
|
|
490
518
|
| `Accessibility permission not granted` | TCC not granted | Stop; tell user to grant in System Settings |
|
|
491
|
-
| `Screen Recording permission not granted` | TCC not granted for capture | Screenshots and pixel actions are unavailable. If the task is AX-completable, use `get_window_state({include_screenshot:false})` and
|
|
519
|
+
| `Screen Recording permission not granted` | TCC not granted for capture | Screenshots and pixel actions are unavailable. If the task is AX-completable, use `get_window_state({include_screenshot:false})` and `element_token` actions; otherwise stop and ask the user to run `cua-driver permissions grant` |
|
|
520
|
+
| `AX action failed: ... returned -25200` (or -25205, -25206) | The app may have acted anyway: some AppKit controls return these after a press they performed | Re-read with `get_window_state` before retrying; a second press on a checkbox toggles it back. A radio button or checkbox whose AXValue settles on the pressed state is reported as performed, naming the error |
|
|
521
|
+
| `set_value refused (file_name_needs_rename)` | A file's name as Finder lists it: an AXValue write changes only the list, never the file | `click` the item, then with Finder frontmost send `press_key` return, `hotkey` cmd+a, `type_text` the full new name, `press_key` return, each with `scope:"desktop"`; re-read to confirm |
|
|
522
|
+
| `set_value refused (file_name_needs_rename)` | A file's name in Finder's Get Info window (AXIdentifier `Name`): an AXValue write changes only the field | foreground `click` at the field's centre in screenshot pixels (with its `capture_id`), then `hotkey` cmd+a, `type_text` the full new name with its extension, `press_key` return, each with `delivery_mode:"foreground"`; a changed extension asks for confirmation first; check the folder listing |
|
|
492
523
|
|
|
493
524
|
## Example end-to-end task (macOS)
|
|
494
525
|
|
|
@@ -497,7 +528,7 @@ starting point for new browser workflows.
|
|
|
497
528
|
1. `launch_app({bundle_id: "com.apple.finder", urls: ["~/Downloads"]})`
|
|
498
529
|
→ `{pid: 844, windows: [{window_id: 6123, title: "Downloads", ...}]}`.
|
|
499
530
|
Idempotent launch; plus Finder opens a hidden window rooted at
|
|
500
|
-
`~/Downloads` via `application(_:open:)
|
|
531
|
+
`~/Downloads` via `application(_:open:)`: zero activation, no
|
|
501
532
|
focus steal. The `windows` array lets you skip a `list_windows` hop.
|
|
502
533
|
2. `get_window_state({pid: 844, window_id: 6123})` → verify an
|
|
503
534
|
`AXWindow` whose title contains "Downloads" is present with a
|
|
@@ -7,7 +7,8 @@ CLI or MCP server.
|
|
|
7
7
|
|
|
8
8
|
It covers the canonical snapshot-action-verify loop, exact window addressing,
|
|
9
9
|
accessibility and pixel actions, background/foreground delivery, typed browser
|
|
10
|
-
automation, session recording, and
|
|
10
|
+
automation, optional visual-region parsing, session recording, and
|
|
11
|
+
platform-specific limitations. The skill
|
|
11
12
|
defaults to background delivery and requires structured refusal or observed
|
|
12
13
|
failure before a caller escalates to foreground input.
|
|
13
14
|
|
|
@@ -57,17 +58,23 @@ Use `--all-platforms` when the agent assists users across operating systems.
|
|
|
57
58
|
|
|
58
59
|
## Reading order
|
|
59
60
|
|
|
60
|
-
- `SKILL.md`:
|
|
61
|
-
|
|
61
|
+
- `SKILL.md`: lean entrypoint, mandatory safety rules, and task-based routing.
|
|
62
|
+
- `WORKFLOW.md`: exact targets, bounded snapshots, coordinates, action semantics,
|
|
63
|
+
verification, filesystem and clipboard proof.
|
|
64
|
+
- `RUNTIME.md`: preflight, transport/session ownership, authorization, cursor,
|
|
65
|
+
and cleanup.
|
|
62
66
|
- `MACOS.md`, `WINDOWS.md`, or `LINUX.md`: host-specific launch, capture,
|
|
63
67
|
accessibility, input delivery, permissions, and refusal boundaries.
|
|
64
68
|
- `BROWSER.md`: exact browser-window binding, explicit profile preparation,
|
|
65
69
|
page refs, trust-classified click/type/navigation, and native fallbacks.
|
|
70
|
+
- `VISUAL.md`: optional model-neutral parsing of one retained screenshot into
|
|
71
|
+
capture-bound text and icon regions.
|
|
66
72
|
- `RECORDING.md`: trajectory evidence, MP4 capture, and replay.
|
|
67
73
|
- `EMBEDDING.md`: embedding the driver into another host application.
|
|
68
74
|
|
|
69
|
-
The agent
|
|
70
|
-
|
|
75
|
+
The agent loads `SKILL.md`, then only the linked guide needed for its next
|
|
76
|
+
step. Every reference ships in the pack; no separate skill installation or
|
|
77
|
+
repository checkout is required. The installer keeps the flat Markdown layout.
|
|
71
78
|
|
|
72
79
|
## Browser model
|
|
73
80
|
|
|
@@ -94,8 +101,10 @@ missing. See `RECORDING.md`.
|
|
|
94
101
|
|
|
95
102
|
## Updates and source builds
|
|
96
103
|
|
|
97
|
-
The skill is versioned with Cua Driver releases.
|
|
98
|
-
|
|
104
|
+
The skill is versioned with Cua Driver releases. Back up personal edits before updating: updates replace the installed pack.
|
|
105
|
+
The pack version does not identify the running daemon; inspect the live tool
|
|
106
|
+
schema when versions differ. For bleeding-edge validation against a matching
|
|
107
|
+
source build (not an arbitrary installed release):
|
|
99
108
|
|
|
100
109
|
```bash
|
|
101
110
|
cua-driver skills install --from main
|