Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
55 changes: 25 additions & 30 deletions .github/workflows/cd-rust-cua-driver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ jobs:
path: |
~/.cargo/registry
~/.cargo/git
libs/cua-driver-rs/target
key: rust-cua-driver-rs-linux-x86_64-${{ hashFiles('libs/cua-driver-rs/Cargo.lock', 'libs/cua-driver-rs/**/Cargo.toml') }}
libs/cua-driver/rust/target
key: rust-cua-driver-rs-linux-x86_64-${{ hashFiles('libs/cua-driver/rust/Cargo.lock', 'libs/cua-driver/rust/**/Cargo.toml') }}
restore-keys: |
rust-cua-driver-rs-linux-x86_64-
- name: Build (release)
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
run: cargo build -p cua-driver --release --target x86_64-unknown-linux-gnu
- name: Package
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
run: |
VERSION="${{ steps.version.outputs.version }}"
LABEL="linux-x86_64"
Expand All @@ -78,7 +78,7 @@ jobs:
- uses: actions/upload-artifact@v4
with:
name: cua-driver-rs-linux-x86_64
path: libs/cua-driver-rs/release/cua-driver-rs-*-linux-x86_64*.tar.gz
path: libs/cua-driver/rust/release/cua-driver-rs-*-linux-x86_64*.tar.gz
if-no-files-found: error

# ── Windows (x86_64 + arm64) ─────────────────────────────────────────────────
Expand Down Expand Up @@ -117,19 +117,19 @@ jobs:
path: |
~/.cargo/registry
~/.cargo/git
libs/cua-driver-rs/target
key: rust-cua-driver-rs-windows-${{ matrix.arch }}-${{ hashFiles('libs/cua-driver-rs/Cargo.lock', 'libs/cua-driver-rs/**/Cargo.toml') }}
libs/cua-driver/rust/target
key: rust-cua-driver-rs-windows-${{ matrix.arch }}-${{ hashFiles('libs/cua-driver/rust/Cargo.lock', 'libs/cua-driver/rust/**/Cargo.toml') }}
restore-keys: |
rust-cua-driver-rs-windows-${{ matrix.arch }}-
- name: Build (release)
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
# Build both the main CLI/MCP binary AND the uiAccess'd worker.
# `cua-driver-uia.exe` is the Windows-only sibling daemon that runs
# at UIAccess integrity so SendInput / UI Automation can cross UIPI
# into UWP apps — see crates/cua-driver-uia/ and #1602.
run: cargo build -p cua-driver -p cua-driver-uia --release --target ${{ matrix.target }}
- name: Package
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
shell: pwsh
run: |
$version = "${{ steps.version.outputs.version }}"
Expand Down Expand Up @@ -158,7 +158,7 @@ jobs:
- uses: actions/upload-artifact@v4
with:
name: cua-driver-rs-windows-${{ matrix.arch }}
path: libs/cua-driver-rs/release/cua-driver-rs-*-windows-${{ matrix.arch }}*.zip
path: libs/cua-driver/rust/release/cua-driver-rs-*-windows-${{ matrix.arch }}*.zip
if-no-files-found: error

# ── macOS universal (arm64 + x86_64 → lipo) ─────────────────────────────────
Expand Down Expand Up @@ -224,18 +224,18 @@ jobs:
path: |
~/.cargo/registry
~/.cargo/git
libs/cua-driver-rs/target
key: rust-cua-driver-rs-darwin-universal-${{ hashFiles('libs/cua-driver-rs/Cargo.lock', 'libs/cua-driver-rs/**/Cargo.toml') }}
libs/cua-driver/rust/target
key: rust-cua-driver-rs-darwin-universal-${{ hashFiles('libs/cua-driver/rust/Cargo.lock', 'libs/cua-driver/rust/**/Cargo.toml') }}
restore-keys: |
rust-cua-driver-rs-darwin-universal-
- name: Build arm64
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
run: cargo build -p cua-driver --release --target aarch64-apple-darwin
- name: Build x86_64
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
run: cargo build -p cua-driver --release --target x86_64-apple-darwin
- name: Create universal binary (lipo)
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
run: |
ARM64="target/aarch64-apple-darwin/release/cua-driver"
X86="target/x86_64-apple-darwin/release/cua-driver"
Expand All @@ -244,7 +244,7 @@ jobs:
lipo -info release/universal/cua-driver
- name: Codesign universal binary (hardened runtime)
if: env.DO_NOTARIZE == 'true'
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
env:
DEVELOPER_NAME: ${{ secrets.DEVELOPER_NAME }}
TEAM_ID: ${{ secrets.TEAM_ID }}
Expand All @@ -254,7 +254,7 @@ jobs:
--sign "$IDENTITY" release/universal/cua-driver
codesign --verify --strict --verbose=2 release/universal/cua-driver
- name: Assemble CuaDriver.app bundle
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
run: |
# Copy the bundle skeleton (Info.plist) from
# scripts/CuaDriverBundle/ and drop the universal binary into
Expand Down Expand Up @@ -297,7 +297,7 @@ jobs:
plutil -p release/CuaDriver.app/Contents/Info.plist | grep -E 'CFBundle(Short)?Version'
- name: Codesign + notarize + staple CuaDriver.app
if: env.DO_NOTARIZE == 'true'
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
env:
DEVELOPER_NAME: ${{ secrets.DEVELOPER_NAME }}
TEAM_ID: ${{ secrets.TEAM_ID }}
Expand Down Expand Up @@ -332,7 +332,7 @@ jobs:
# below builds the final tarballs from the stapled .app.
rm -f release/CuaDriver.app.zip
- name: Package
working-directory: libs/cua-driver-rs
working-directory: libs/cua-driver/rust
run: |
VERSION="${{ steps.version.outputs.version }}"
for LABEL in darwin-arm64 darwin-x86_64 darwin-universal; do
Expand Down Expand Up @@ -360,7 +360,7 @@ jobs:
- uses: actions/upload-artifact@v4
with:
name: cua-driver-rs-darwin
path: libs/cua-driver-rs/release/cua-driver-rs-*-darwin-*.tar.gz
path: libs/cua-driver/rust/release/cua-driver-rs-*-darwin-*.tar.gz
if-no-files-found: error

# ── Release ──────────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -463,12 +463,12 @@ jobs:
VERSION="${{ steps.version.outputs.version }}"
SKILLS_STAGE="cua-driver-rs-v${VERSION}-skills"
mkdir -p "${SKILLS_STAGE}/cua-driver-rs"
if [ -d libs/cua-driver-rs/Skills/cua-driver-rs ]; then
cp -R libs/cua-driver-rs/Skills/cua-driver-rs/* "${SKILLS_STAGE}/cua-driver-rs/"
if [ -d libs/cua-driver/rust/Skills/cua-driver-rs ]; then
cp -R libs/cua-driver/rust/Skills/cua-driver-rs/* "${SKILLS_STAGE}/cua-driver-rs/"
tar -czf "release-upload/${SKILLS_STAGE}.tar.gz" "${SKILLS_STAGE}"
echo "Packaged skill pack: release-upload/${SKILLS_STAGE}.tar.gz"
else
echo "Note: libs/cua-driver-rs/Skills/cua-driver-rs not present; skipping skill-pack asset."
echo "Note: libs/cua-driver/rust/Skills/cua-driver-rs not present; skipping skill-pack asset."
fi

echo "Release files:"
Expand Down Expand Up @@ -496,9 +496,9 @@ jobs:
| grep -v "^${{ github.ref_name }}$" \
| head -n 1 || echo "")
if [ -n "$PREV_TAG" ]; then
NOTES=$(git log ${PREV_TAG}..HEAD --pretty=format:"* %s (%h) by @%an" -- "libs/cua-driver-rs" | head -50)
NOTES=$(git log ${PREV_TAG}..HEAD --pretty=format:"* %s (%h) by @%an" -- "libs/cua-driver/rust" | head -50)
else
NOTES=$(git log --pretty=format:"* %s (%h) by @%an" -- "libs/cua-driver-rs" | head -50)
NOTES=$(git log --pretty=format:"* %s (%h) by @%an" -- "libs/cua-driver/rust" | head -50)
fi
[ -z "$NOTES" ] && NOTES="* No path-specific changes found"
{
Expand Down Expand Up @@ -557,11 +557,6 @@ jobs:
irm https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.ps1 | iex
```

> Note: both canonical installer URLs now live under
> `libs/cua-driver/scripts/`. Old URLs at
> `libs/cua-driver-rs/scripts/install.{sh,ps1}` still work via a
> deprecation shim that fetches the canonical script.

The installer auto-detects host architecture (x86_64 / arm64) and uses
directory junctions for the install layout, so it runs without admin
and without Developer Mode.
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-bump-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ jobs:
echo "type=cua-driver" >> $GITHUB_OUTPUT
;;
"cua-driver-rs")
echo "directory=libs/cua-driver-rs" >> $GITHUB_OUTPUT
echo "directory=libs/cua-driver/rust" >> $GITHUB_OUTPUT
echo "type=cua-driver-rs" >> $GITHUB_OUTPUT
;;
"docker/cuabot")
Expand Down Expand Up @@ -408,7 +408,7 @@ jobs:
if: ${{ inputs.service == 'cua-driver-rs' }}
id: cua_driver_rs_version
run: |
VERSION=$(grep -m1 -oP '^version = "\K[^"]+' libs/cua-driver-rs/Cargo.toml)
VERSION=$(grep -m1 -oP '^version = "\K[^"]+' libs/cua-driver/rust/Cargo.toml)
echo "cua-driver-rs version: $VERSION"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

Expand Down
10 changes: 5 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import PackageDescription

// Root shim: re-exports CuaDriverCore and CuaDriverServer so Swift packages
// can consume them directly from the trycua/cua monorepo without knowing the
// internal layout. Sources live in libs/cua-driver/Sources/; this file uses
// path: to forward there.
// internal layout. Sources live in libs/cua-driver/swift/Sources/; this file
// uses path: to forward there.
//
// IMPORTANT — SPM version resolution:
// SPM's `from:` / `upToNextMajor` only recognises semver tags ("0.1.0",
Expand Down Expand Up @@ -41,20 +41,20 @@ let package = Package(
),
],
targets: [
// NOTE: if libs/cua-driver/Package.swift ever gains resources:,
// NOTE: if libs/cua-driver/swift/Package.swift ever gains resources:,
// swiftSettings:, linkerSettings:, or exclude: on these targets,
// mirror those changes here to avoid a silent build mismatch.
.target(
name: "CuaDriverCore",
path: "libs/cua-driver/Sources/CuaDriverCore"
path: "libs/cua-driver/swift/Sources/CuaDriverCore"
),
.target(
name: "CuaDriverServer",
dependencies: [
"CuaDriverCore",
.product(name: "MCP", package: "swift-sdk"),
],
path: "libs/cua-driver/Sources/CuaDriverServer"
path: "libs/cua-driver/swift/Sources/CuaDriverServer"
),
]
)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Drive any native macOS app **in the background** — agents click, type, and ver
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.sh)"
```

> Want to try the cross-platform Rust port early? Add `-- --experimental-rust` to the line above — it delegates to the [`cua-driver-rs`](libs/cua-driver-rs/) installer (separate bundle, coexists with the Swift binary).
> Want to try the cross-platform Rust port early? Add `-- --experimental-rust` to the line above — it delegates to the [`cua-driver-rs`](libs/cua-driver/rust/) installer (separate bundle, coexists with the Swift binary).

Full tool reference, architecture notes, and the Claude Code skill ship with the package: [`libs/cua-driver/README.md`](libs/cua-driver/README.md).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ cua-driver autostart disable # remove the entry
| Platform | Mechanism | Where it lives |
|---|---|---|
| Windows | Scheduled Task `cua-driver-serve` with `LogonType: Interactive` | Task Scheduler (`schtasks /Query /TN cua-driver-serve`) |
| macOS | Not yet implemented in the Rust port — use the manual `LaunchAgent` recipe ([`scripts/install-local.sh --autostart`](https://github.com/trycua/cua/blob/main/libs/cua-driver-rs/scripts/install-local.sh)) | `~/Library/LaunchAgents/com.trycua.cua-driver-rs.plist` |
| Linux | Not yet implemented in the Rust port — use the manual `systemd --user` unit ([`scripts/install-local.sh --autostart`](https://github.com/trycua/cua/blob/main/libs/cua-driver-rs/scripts/install-local.sh)) | `~/.config/systemd/user/cua-driver-rs.service` |
| macOS | Not yet implemented in the Rust port — use the manual `LaunchAgent` recipe ([`scripts/install-local.sh --autostart`](https://github.com/trycua/cua/blob/main/libs/cua-driver/rust/scripts/install-local.sh)) | `~/Library/LaunchAgents/com.trycua.cua-driver-rs.plist` |
| Linux | Not yet implemented in the Rust port — use the manual `systemd --user` unit ([`scripts/install-local.sh --autostart`](https://github.com/trycua/cua/blob/main/libs/cua-driver/rust/scripts/install-local.sh)) | `~/.config/systemd/user/cua-driver-rs.service` |

<Callout type="info">
**Platform parity status.** `cua-driver autostart` is currently a Windows-only verb in the Rust port — the macOS / Linux cases return an error pointing at the manual recipe. A cross-platform native impl is tracked as a follow-up. The verb is documented as the cross-platform interface so existing scripts and skill-pack instructions land in the right place once parity ships.
Expand All @@ -38,7 +38,7 @@ cua-driver autostart enable
# cua-driver serve will start at every interactive logon.
```

The registered task pins to `LogonType: Interactive` — load-bearing, because the alternative (`S4U` / `Password`) would land the daemon back in Session 0. The exact PowerShell that gets run is in [`autostart.rs`](https://github.com/trycua/cua/blob/main/libs/cua-driver-rs/crates/cua-driver/src/autostart.rs) and stays in lock-step with `scripts/install.ps1`.
The registered task pins to `LogonType: Interactive` — load-bearing, because the alternative (`S4U` / `Password`) would land the daemon back in Session 0. The exact PowerShell that gets run is in [`autostart.rs`](https://github.com/trycua/cua/blob/main/libs/cua-driver/rust/crates/cua-driver/src/autostart.rs) and stays in lock-step with `scripts/install.ps1`.

### `kick`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ Both canonical installers live under `libs/cua-driver/scripts/`. On macOS the `.
irm https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.ps1 | iex
```

The legacy `libs/cua-driver-rs/scripts/install.{sh,ps1}` URLs continue to work via backward-compat shims that redirect to the canonical installers — Hermes and any other integration that hardcodes the old URLs keep working unchanged.

<Callout type="warn">
**Known issue on Windows PowerShell 5.1**: `install.ps1` currently fails to parse on stock Windows PowerShell 5.1 (the version shipped with Windows 10 / Server 2019 / Server 2025) due to backtick + ampersand escaping in the post-install hint block — see [#1626](https://github.com/trycua/cua/issues/1626). Workaround until that lands: manual zip install:

Expand Down Expand Up @@ -162,7 +160,7 @@ Re-run the install one-liner with `$env:CUA_DRIVER_RS_VERSION` pinned to the ver

```powershell
$env:CUA_DRIVER_RS_VERSION = "0.2.0"
irm https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver-rs/scripts/install.ps1 | iex
irm https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.ps1 | iex
cua-driver --version # → 0.2.0
```

Expand Down
10 changes: 5 additions & 5 deletions docs/content/docs/cua-driver/guide/getting-started/linux.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Display server (X11 / Wayland), AT-SPI prerequisites, autostart, an

import { Callout } from 'fumadocs-ui/components/callout';

cua-driver-rs supports Linux as a first-class target — every action tool (`click`, `type_text`, `hotkey`, `drag`, `scroll`, `screenshot`, `launch_app`, `list_windows`, etc.) has a Linux implementation under [`crates/platform-linux/`](https://github.com/trycua/cua/tree/main/libs/cua-driver-rs/crates/platform-linux/src). This page covers the bits that diverge from the macOS / Windows quickstart: which display server you're running, what accessibility plumbing needs to be alive, how to keep the daemon up at logon, and how headless / CI workflows look.
cua-driver-rs supports Linux as a first-class target — every action tool (`click`, `type_text`, `hotkey`, `drag`, `scroll`, `screenshot`, `launch_app`, `list_windows`, etc.) has a Linux implementation under [`crates/platform-linux/`](https://github.com/trycua/cua/tree/main/libs/cua-driver/rust/crates/platform-linux/src). This page covers the bits that diverge from the macOS / Windows quickstart: which display server you're running, what accessibility plumbing needs to be alive, how to keep the daemon up at logon, and how headless / CI workflows look.

For the install one-liner itself, see [Installation](/cua-driver/guide/getting-started/installation) — the canonical script auto-detects Linux and routes to the Rust port.

Expand Down Expand Up @@ -63,7 +63,7 @@ The `cua-driver autostart` verb family is **Windows-only today**. On Linux it cu

```text
cua-driver autostart is currently Windows-only. macOS users: see
libs/cua-driver-rs/scripts/install-local.sh --autostart for the
libs/cua-driver/rust/scripts/install-local.sh --autostart for the
LaunchAgent recipe. Linux users: same script registers a systemd
--user unit. A cross-platform impl is tracked as a follow-up.
```
Expand All @@ -72,7 +72,7 @@ The two working alternatives:

### Option A — Use `install-local.sh --autostart`

The dev-loop install script registers a systemd user unit when invoked with `--autostart`. See [`libs/cua-driver-rs/scripts/install-local.sh`](https://github.com/trycua/cua/blob/main/libs/cua-driver-rs/scripts/install-local.sh) — built for local development off a git checkout, but the systemd unit it writes is the same shape you'd use in production.
The dev-loop install script registers a systemd user unit when invoked with `--autostart`. See [`libs/cua-driver/rust/scripts/install-local.sh`](https://github.com/trycua/cua/blob/main/libs/cua-driver/rust/scripts/install-local.sh) — built for local development off a git checkout, but the systemd unit it writes is the same shape you'd use in production.

### Option B — Write your own systemd user unit

Expand Down Expand Up @@ -148,11 +148,11 @@ If `cua-driver doctor` is happy after install, you're set.

## Per-tool Linux verification matrix

See [`libs/cua-driver-rs/PARITY.md`](https://github.com/trycua/cua/blob/main/libs/cua-driver-rs/PARITY.md) for the per-tool Linux-VERIFIED matrix — every action tool is annotated with its Linux source file (`crates/platform-linux/src/tools/impl_.rs`) and which platform features it depends on (X11 root window for `get_cursor_position`, AT-SPI for accessibility tree, `xtest` for synthetic input, etc.).
See [`libs/cua-driver/rust/PARITY.md`](https://github.com/trycua/cua/blob/main/libs/cua-driver/rust/PARITY.md) for the per-tool Linux-VERIFIED matrix — every action tool is annotated with its Linux source file (`crates/platform-linux/src/tools/impl_.rs`) and which platform features it depends on (X11 root window for `get_cursor_position`, AT-SPI for accessibility tree, `xtest` for synthetic input, etc.).

## See also

- [Installation](/cua-driver/guide/getting-started/installation) — canonical one-liner that handles Linux automatically
- [Autostart](/cua-driver/guide/getting-started/autostart) — concept page (Windows-only verb family; Linux uses systemd)
- [Process attribution](/cua-driver/explanation/process-attribution) — Linux has none of the macOS-TCC or Windows-Session-0 weirdness; this page explains what those problems are and why Linux sidesteps them
- [`PARITY.md`](https://github.com/trycua/cua/blob/main/libs/cua-driver-rs/PARITY.md) — per-tool platform verification matrix
- [`PARITY.md`](https://github.com/trycua/cua/blob/main/libs/cua-driver/rust/PARITY.md) — per-tool platform verification matrix
Loading
Loading