Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fe9d31f
docs(cua-driver): add changelog reference page (#1785)
f-trycua May 31, 2026
6c31427
fix(cua-driver)(macos): guard SkyLight auth-message selector for macO…
f-trycua May 31, 2026
88f87eb
feat(cua-driver-rs)(macos): enable Chromium/Electron AX trees for get…
f-trycua May 31, 2026
e8acc6a
Bump cua-driver-rs to v0.4.2
github-actions[bot] May 31, 2026
3dcfb6e
docs(cua-driver): add 0.4.2 changelog entry + fix 0.3.6 wording (#1786)
f-trycua May 31, 2026
3ecfffe
chore(cua-driver-rs): bake version 0.4.2 into install scripts [skip ci]
May 31, 2026
18e2cbb
fix(cua-driver-rs): wire/guide per-session cursors through the real m…
f-trycua May 31, 2026
edbfe51
fix(cua-driver-rs)(macos): run the agent-cursor overlay in the serve …
f-trycua May 31, 2026
8b4c61c
fix(cua-driver-rs)(macos): stop the permissions gate spamming the TCC…
f-trycua May 31, 2026
c9fa72a
feat(cua-driver-rs)(install-local): sign the bundle with a stable sel…
f-trycua May 31, 2026
86e2cc0
Bump cua-driver-rs to v0.4.3
github-actions[bot] May 31, 2026
b8b61f1
docs(cua-driver): add 0.4.3 changelog entry (#1793)
f-trycua May 31, 2026
f966437
chore(cua-driver-rs): bake version 0.4.3 into install scripts [skip ci]
May 31, 2026
58efe39
fix(cua-driver-rs)(install-local): reset a TCC grant pinned to a prev…
f-trycua Jun 1, 2026
d557a0c
fix(cua-driver-rs)(macos): retain cached AX element across action so …
f-trycua Jun 1, 2026
4c54f43
docs(cua-driver-rs)(launch_app): surface creates_new_application_inst…
f-trycua Jun 1, 2026
e1e8c98
feat(cua-driver-rs): caller-declared session identity + Streamable-HT…
f-trycua Jun 1, 2026
0940667
fix(cua-driver-rs)(windows): per-session agent cursors (port macOS #1…
f-trycua Jun 1, 2026
51582fd
Bump cua-driver-rs to v0.5.0
f-trycua Jun 1, 2026
93cfd06
chore(cua-driver-rs): bake version 0.5.0 into install scripts [skip ci]
Jun 1, 2026
33a6893
fix(cua-driver-rs): release installer unifies home on ~/.cua-driver +…
f-trycua Jun 1, 2026
1b1fa3f
Bump cua-driver-rs to v0.5.1
f-trycua Jun 2, 2026
1e2357f
chore(cua-driver-rs): bake version 0.5.1 into install scripts [skip ci]
Jun 2, 2026
11c15e8
Delete JOURNAL.md
f-trycua Jun 2, 2026
02fdd98
Delete JOURNAL_VIDEO.md
f-trycua Jun 2, 2026
bf8fb19
feat(linux): GTK4 focus-free write via clipboard+paste fallback
claude Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
373 changes: 0 additions & 373 deletions JOURNAL.md

This file was deleted.

363 changes: 0 additions & 363 deletions JOURNAL_VIDEO.md

This file was deleted.

37 changes: 37 additions & 0 deletions docs/content/docs/cua-driver/guide/getting-started/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,29 @@ cua-driver call set_agent_cursor_motion '{"glide_duration_ms":300}'

See `set_agent_cursor_motion` in the [MCP tools reference](/cua-driver/reference/mcp-tools) for every knob.

## Concurrency & multiple agents

### Two agents (or subagents) take turns instead of running in parallel. Why?

The daemon is concurrent — it handles each connection on its own task, and proves it: two raw socket connections can drive two cursors simultaneously. The bottleneck is the **stdio MCP transport**: an MCP client (e.g. Claude Code) spawns **one** `cua-driver mcp` process per server config and shares it across all subagents, and a single stdio pipe carries one in-flight request at a time. So tool calls serialize at the transport, upstream of cua-driver. Sessions give concurrent runs distinct **cursors**; they don't give them distinct **connections**, and parallelism needs distinct connections.

Claude Code only parallelizes tool calls it deems concurrency-safe (`readOnlyHint:true`). cua-driver's read-only tools (including `move_cursor`) already parallelize; mutating tools (`click`, `type_text`) serialize by design — parallelizing an ordered sequence like `3 → + → 1 → =` would race.

### How do I run multiple agents truly in parallel?

Give each agent its **own** connection. Two options:

1. **Separate `cua-driver mcp` processes** — e.g. two Claude Code instances. Each spawns its own proxy → its own daemon connection → the (concurrent) daemon runs them in parallel.
2. **The HTTP transport** — start the daemon with `CUA_DRIVER_RS_MCP_HTTP_PORT=<port>` and it also serves MCP over HTTP at `POST http://127.0.0.1:<port>/mcp` (loopback only). Point each agent's MCP client at that URL; each opens its own HTTP connection and they run concurrently (measured 3.6× on 10 parallel calls). Per-connection ordering keeps each agent's sequence correct; the per-`(pid, window_id)` cache + per-session cursor make concurrent cross-connection actions safe.

```bash
# daemon with the HTTP MCP endpoint enabled
CUA_DRIVER_RS_MCP_HTTP_PORT=8787 cua-driver serve
# sanity check
curl -s -XPOST http://127.0.0.1:8787/mcp \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"start_session","arguments":{"session":"agent-1"}}}'
```

## Permissions

### `check_permissions` says `NOT granted` but I granted both.
Expand All @@ -180,6 +203,20 @@ This is the same TCC-attribution issue as the previous question, applied to the

macOS is attributing the process to a different bundle id than the one you granted. Run `cua-driver diagnose` and share the output when filing an issue. It reports cdhash, team id, and which bundle TCC matched against.

### After a rebuild, the driver reports `NOT granted` but System Settings still shows CuaDriver toggled ON.

This is a stale TCC grant. TCC pins each Accessibility / Screen-Recording grant to the app's **designated requirement at grant time**. If you first granted while `CuaDriver.app` was *ad-hoc* signed, the requirement is a bare `cdhash H"…"`, which changes on every rebuild — so the grant row stays `allowed` but its requirement no longer matches the new binary, and re-toggling the switch doesn't help (the row already records a decision, so the prompt never re-fires).

Release builds are CI-signed with a stable identity, so this only affects the local dev loop (`install-local.sh`). That installer now signs with a **stable self-signed certificate** and, when it detects the signing identity changed since the last install, runs `tccutil reset` for you so the next grant re-pins cleanly. After you re-grant once on the certificate-signed build, the grant survives every future rebuild.

To clear it by hand:

```bash
tccutil reset Accessibility com.trycua.driver
tccutil reset ScreenCapture com.trycua.driver
cua-driver permissions grant # re-grant once; now pinned to the stable cert
```

## Config and telemetry

### Where does config live?
Expand Down
34 changes: 22 additions & 12 deletions docs/content/docs/cua-driver/guide/getting-started/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,17 @@ irm https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/in

On macOS, the installer drops `CuaDriver.app` into `/Applications` and symlinks the binary at `~/.local/bin/cua-driver`. The bundle is signed under `com.trycua.driver`, so TCC grants survive every release.

On Linux, the pre-release backend installer downloads the release into `~/.cua-driver-rs/packages/releases/`, retargets `~/.cua-driver-rs/packages/current`, and symlinks `~/.local/bin/cua-driver`.
On Linux, the pre-release backend installer downloads the release into `~/.cua-driver/packages/releases/`, retargets `~/.cua-driver/packages/current`, and symlinks `~/.local/bin/cua-driver`.

<Callout type="info">
**Install home is `~/.cua-driver` on every platform.** Earlier `cua-driver-rs` releases (before
v0.2.16) put the Linux/macOS package home at `~/.cua-driver-rs`; the release installer now writes
to `~/.cua-driver` like the local installer and the runtime already do. Re-running the installer
over an older release **auto-sweeps** a stale `~/.cua-driver-rs`, and also cleans up any prior
`install-local` dev build (`*-local-*` release dirs + the local signing-identity marker) under the
shared home so the downloaded release is the single authoritative install. The `CUA_DRIVER_RS_HOME`
override is still honored for back-compat.
</Callout>

<Callout type="warn">
**Linux is pre-release.** Linux artifacts and install paths are published for early testing, but
Expand Down Expand Up @@ -79,7 +89,7 @@ Linux and Windows installs land in a three-tier layout that makes upgrades and r
**Linux**

```
$CUA_DRIVER_RS_HOME/ (default: ~/.cua-driver-rs)
$CUA_DRIVER_RS_HOME/ (default: ~/.cua-driver)
packages/
releases/
0.2.0-x86_64-unknown-linux-gnu/cua-driver (real binary, immutable)
Expand Down Expand Up @@ -114,10 +124,10 @@ Both platforms ship every release into its own per-version directory under `pack
**Linux — roll back to a specific version**

```bash
# The symlink target is RELATIVE to ~/.cua-driver-rs/packages/, so just
# The symlink target is RELATIVE to ~/.cua-driver/packages/, so just
# "releases/<v>-<target>" (no leading "../") — matches what install.sh writes.
ln -sfn releases/0.2.0-x86_64-unknown-linux-gnu ~/.cua-driver-rs/packages/.current.tmp
mv -Tf ~/.cua-driver-rs/packages/.current.tmp ~/.cua-driver-rs/packages/current
ln -sfn releases/0.2.0-x86_64-unknown-linux-gnu ~/.cua-driver/packages/.current.tmp
mv -Tf ~/.cua-driver/packages/.current.tmp ~/.cua-driver/packages/current
cua-driver --version # → 0.2.0
```

Expand All @@ -141,7 +151,7 @@ Clear `$env:CUA_DRIVER_RS_VERSION` and re-run to roll forward to the newest rele
| ---------------------------------------------------- | ------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CUA_DRIVER_RS_VERSION` | unset → use baked version | unset → use baked version | Pin a specific release (e.g. `0.2.0`). |
| `CUA_DRIVER_RS_INSTALL_DIR` | `~/.local/bin` | `%LOCALAPPDATA%\Programs\Cua\cua-driver\bin` | The visible PATH-entry directory. On Windows this is itself a junction. |
| `CUA_DRIVER_RS_HOME` | `~/.cua-driver-rs` | `%USERPROFILE%\.cua-driver` | Package home — holds `packages/releases/<v>/` and `packages/current`. |
| `CUA_DRIVER_RS_HOME` | `~/.cua-driver` | `%USERPROFILE%\.cua-driver` | Package home — holds `packages/releases/<v>/` and `packages/current`. (Renamed from `~/.cua-driver-rs` in v0.2.16; a stale legacy dir is auto-swept on the next install.) |
| `CUA_DRIVER_RS_NO_MODIFY_PATH` _(Linux/macOS only)_ | `0` | use `-NoPathUpdate` switch on `install.ps1` | Skip the PATH append. On Windows the installer appends `%LOCALAPPDATA%\Programs\Cua\cua-driver\bin` to the User-scope `Path` by default; use the fetch+invoke form with `-NoPathUpdate` to opt out (see the Windows install section above for the exact one-liner). |
| `CUA_DRIVER_RS_KEEP_VERSIONS` _(Linux/Windows only)_ | `5` | `5` | Keep the N most recent per-version release dirs after install (`0` disables GC). See the **Old-version cleanup** callout below for per-target and active-install invariants. |

Expand Down Expand Up @@ -183,13 +193,13 @@ The macOS install path is unaffected — `/Applications/CuaDriver.app` is an in-

```
==> another cua-driver-rs install is already in progress (lock at
~/.cua-driver-rs/packages/.install.lock.d); waiting...
~/.cua-driver/packages/.install.lock.d); waiting...
```

If you see this, the safe action is to let it block — it polls every 1 second and proceeds the moment the holding install finishes. The lock entry stamps the holder's pid, start time, and invocation args so you can confirm what's running:

```bash
cat ~/.cua-driver-rs/packages/.install.lock.d/info
cat ~/.cua-driver/packages/.install.lock.d/info
# pid=43210
# started=2026-05-17T09:14:22Z
# argv=install.sh
Expand Down Expand Up @@ -231,7 +241,7 @@ For a structured environment + install report on any platform, run:
cua-driver doctor
# [ok ] binary: cua-driver 0.2.1 (aarch64-macos)
# [ok ] install dir: /Users/you/.local/bin/cua-driver
# [ok ] home dir: /Users/you/.cua-driver-rs (3 release dirs cached)
# [ok ] home dir: /Users/you/.cua-driver (3 release dirs cached)
# [ok ] telemetry: enabled (install-id present)
# ...
```
Expand Down Expand Up @@ -415,7 +425,7 @@ other value (including unset) leaves the gate active.
Release notes: https://github.com/trycua/cua/releases/tag/cua-driver-rs-v0.1.4
```

The answer is cached at `~/.cua-driver-rs/version_check.json` for ~20
The answer is cached at `~/.cua-driver/version_check.json` for ~20
hours, so subsequent launches reuse the cached result without a network
call. Network failures are silent — the next launch retries.

Expand Down Expand Up @@ -624,8 +634,8 @@ One canonical uninstall URL per platform mirrors the install side:

| Platform | Symlink / bin | App bundle / package home | Autostart entry | Skill links | Claude MCP registrations |
| -------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| macOS | `~/.local/bin/cua-driver` _(when it resolves into `CuaDriver.app` and `~/.cua-driver-rs/` exists)_ | `/Applications/CuaDriver.app` (current), `/Applications/CuaDriverRs.app` (legacy), `~/.cua-driver-rs/` | `~/Library/LaunchAgents/com.trycua.cua-driver-rs.plist` | `cua-driver` and legacy `cua-driver-rs` links under agent skill dirs | Scrubbed from `~/.claude.json` |
| Linux | `~/.local/bin/cua-driver` _(when it resolves into `~/.cua-driver-rs/`)_ | `~/.cua-driver-rs/` | `~/.config/systemd/user/cua-driver-rs.service` (stop + disable + remove) | Same as macOS | Scrubbed from `~/.claude.json` |
| macOS | `~/.local/bin/cua-driver` _(when it resolves into `CuaDriver.app` and a Rust marker exists)_ | `/Applications/CuaDriver.app` (current), `/Applications/CuaDriverRs.app` (legacy), `~/.cua-driver/` (legacy `~/.cua-driver-rs/` also swept) | `~/Library/LaunchAgents/com.trycua.cua-driver-rs.plist` | `cua-driver` and legacy `cua-driver-rs` links under agent skill dirs | Scrubbed from `~/.claude.json` |
| Linux | `~/.local/bin/cua-driver` _(when it resolves into `~/.cua-driver/`)_ | `~/.cua-driver/` (legacy `~/.cua-driver-rs/` also swept) | `~/.config/systemd/user/cua-driver-rs.service` (stop + disable + remove) | Same as macOS | Scrubbed from `~/.claude.json` |
| Windows | `%LOCALAPPDATA%\Programs\Cua\cua-driver\bin` _(directory junction; legacy `Programs\trycua\cua-driver-rs\bin` also swept)_ | `%USERPROFILE%\.cua-driver\` (entire tree, including `packages\current` junction; legacy `~\.cua-driver-rs\` also swept) | Scheduled Task `cua-driver-serve` (`schtasks /Delete`; script self-elevates when needed) | Junctions under `%USERPROFILE%\.claude\skills`, `.agents\skills`, `.openclaw\skills`, `%APPDATA%\opencode\skills`, `.gemini\skills` | Not auto-edited — closing message prints the manual `claude mcp remove` command |

<Callout type="info">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ This is a useful recipe for local CI experiments with the Linux pre-release back

## Distro-specific notes

The canonical install script (`/bin/bash -c "$(curl -fsSL …/install.sh)"`) downloads a Linux x86_64 binary tarball from GitHub Releases, drops it into `~/.cua-driver-rs/packages/releases/<v>-x86_64-unknown-linux-gnu/`, and symlinks `~/.local/bin/cua-driver`. Because Linux support is pre-release, expect distro-specific gaps and prerequisites.
The canonical install script (`/bin/bash -c "$(curl -fsSL …/install.sh)"`) downloads a Linux x86_64 binary tarball from GitHub Releases, drops it into `~/.cua-driver/packages/releases/<v>-x86_64-unknown-linux-gnu/`, and symlinks `~/.local/bin/cua-driver`. Because Linux support is pre-release, expect distro-specific gaps and prerequisites.

The bit that varies is **what accessibility / display tooling is pre-installed**:

Expand Down
Loading