# Qwen CUA Driver Qwen Code's vendored distribution of the cross-platform Cua Driver runtime. It provides native desktop and browser automation over MCP, a one-shot CLI, and in-process Python and TypeScript SDKs. This tree is based on upstream `cua-driver-rs-v0.20.0`. The upstream snapshot is recorded in [`.vendored-from`](.vendored-from); Qwen-owned differences are documented in [`.vendored-patches.md`](.vendored-patches.md) and [`docs/relative-coordinates-design.md`](docs/relative-coordinates-design.md). ## Install The commands below target release **0.27.0** and require its GitHub Release (`cua-driver-rs-v0.27.0`) to be published. The native driver does not require Node.js or npm. Install the MCP client you want to use separately. macOS and Linux: ```bash CUA_DRIVER_RS_VERSION=0.27.0 \ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/QwenLM/qwen-code/main/packages/cua-driver/scripts/install.sh)" ``` Windows PowerShell: ```powershell $env:CUA_DRIVER_RS_VERSION = "0.27.0" irm https://raw.githubusercontent.com/QwenLM/qwen-code/main/packages/cua-driver/scripts/install.ps1 | iex ``` The default executable is `~/.local/bin/qwen-cua-driver` on macOS/Linux and `%LOCALAPPDATA%\Programs\Qwen\qwen-cua-driver\bin\qwen-cua-driver.exe` on Windows. Check the installation: ```bash # macOS / Linux "$HOME/.local/bin/qwen-cua-driver" --version ``` ```powershell # Windows PowerShell $driver = Join-Path $env:LOCALAPPDATA "Programs\Qwen\qwen-cua-driver\bin\qwen-cua-driver.exe" & $driver --version ``` Expected: qwen-cua-driver 0.27.0. If you chose a custom install directory, use its absolute executable path in the client commands below. The released product uses Qwen-owned identities throughout: - executable: `qwen-cua-driver` / `qwen-cua-driver.exe` - macOS app: `/Applications/QwenCuaDriver.app` - bundle identifier: `com.qwencode.cua-driver` - state home: `~/.cua-driver` - Windows task: `qwen-cua-driver-serve` Source builds install as the separate `qwen-cua-driver-local` product. The Qwen executable, app, service, and local-build identities are distinct from upstream CuaDriver. The release state home remains `~/.cua-driver` for compatibility with existing Qwen releases, so installing both release distributions for the same user is not supported: they can share or overwrite that state directory. ## Agent integration Choose an interface for your agent: | Interface | Install and configure | | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Direct native MCP tools | Install this driver, then follow the client instructions below. | | Persistent JavaScript with preloaded `cua` (Node REPL + SDK) | Follow the [Node REPL README](../node-repl/README.md#usage). It installs the matching SDK dependencies automatically and does not require this standalone driver installation. | Both interfaces work with Qwen Code, Claude Code, and Codex over stdio MCP. Claude Code and Codex can use them independently of Qwen Code. The version `0.27.0` here belongs to the CUA components; it does not require a Qwen Code CLI or Web Shell release with that version. ### Qwen Code On macOS/Linux, register the installed executable at user scope: ```bash qwen mcp add --scope user cua-driver "$HOME/.local/bin/qwen-cua-driver" mcp ``` This writes `mcpServers.cua-driver` in `~/.qwen/settings.json`. Use `--scope project` for the current project's `.qwen/settings.json` instead. ### Claude Code On macOS/Linux: ```bash claude mcp add --scope user --transport stdio cua-driver -- "$HOME/.local/bin/qwen-cua-driver" mcp ``` User scope is stored in `~/.claude.json`. Use `--scope project` to write the current project's `.mcp.json` instead. See the [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp). ### Codex On macOS/Linux: ```bash codex mcp add cua-driver -- "$HOME/.local/bin/qwen-cua-driver" mcp ``` Alternatively, add this table to `~/.codex/config.toml`, replacing the path with your actual installed executable. TOML command strings are literal paths; do not use `$HOME` or `~` in place of the absolute path. ```toml [mcp_servers.cua-driver] command = "/absolute/path/to/.local/bin/qwen-cua-driver" args = ["mcp"] ``` See the [official OpenAI MCP documentation](https://learn.chatgpt.com/docs/extend/mcp). ### Windows client commands In PowerShell, use the installed executable's absolute path. Run the command for your chosen client: ```powershell $driver = Join-Path $env:LOCALAPPDATA "Programs\Qwen\qwen-cua-driver\bin\qwen-cua-driver.exe" # Qwen Code qwen mcp add --scope user cua-driver $driver mcp # Claude Code claude mcp add --scope user --transport stdio cua-driver -- $driver mcp # Codex codex mcp add cua-driver -- $driver mcp ``` ### Permissions and connection check Restart the client after registration. Check its server list with `qwen mcp list`, `claude mcp list`, or `codex mcp list`, and use `/mcp` inside the session to inspect the connection and available tools. The default native MCP interface exposes 19 Computer Use tools; advanced tools require the explicit `CUA_DRIVER_EXTRA_TOOLS=1` opt-in. On macOS, grant Accessibility and Screen Recording to `/Applications/QwenCuaDriver.app`; normal `mcp` uses its app-owned daemon. On Windows, run the installer in the logged-in desktop user's session and allow its UAC prompt. On Linux, use an X11 desktop (including X11 apps under XWayland); native Wayland apps are unsupported. Launch the client with that desktop session's environment. Codex needs the matching environment allowlist shown in [Linux desktop sessions](../node-repl/README.md#linux-desktop-sessions), applied to its `mcp_servers.cua-driver` table. Clients start `qwen-cua-driver mcp` themselves; a separately started MCP process is unnecessary. Shell-oriented automation can instead call tools through `qwen-cua-driver call`. The native agent cursor is enabled by default. On macOS, a local PiP also updates the two most recently observed, authorized windows in each session, including while the agent is idle. Drag a card or its Move preview handle to move the borderless window. Hover to reveal its floating controls, or close it to stop that preview; a later authorized observation can recreate it. It does not forward input to the target app. Use `--no-overlay` and `--no-pip` when starting the owning host to disable them; `experimental_pip: false` in `~/.cua-driver/config.json` also disables PiP. Restart the owning host after changing flags or editing the file, preserving its other keys. For the installed app's default MCP proxy, restart the app-owned daemon. Restarting only the MCP client or proxy does not reconfigure an existing daemon. CLI flags take precedence: remove an explicit `--pip` or `--experimental-pip` if the file should control the setting. Disable PiP and restart its owning host before sharing or recording the desktop if its mirrored windows should not be visible. Closing the panel alone is temporary; screen sharing is not detected automatically. Windows and X11 retain cursor support; PiP is macOS-only. ## 0.20 runtime and SDK surface The 0.20 base includes the SDK-owned runtime and versioned C ABI, generated Python and TypeScript UniFFI bindings, typed browser automation, permission modes, runtime-owned consent adapters, transport-owned implicit lifecycle sessions, per-action target selection, capability manifests across permission profiles, snapshot-bound element tokens, closed action results, `verify_state`, foreground-focus verification, native menu and clipboard operations, window framing, and semantic cursor themes. Browser approval tokens are retired; existing-profile access now requires a trusted launch grant, bounded manifest, or embedding-host authorization. Python applications import `cua_driver`. TypeScript applications import the Qwen-owned `@qwen-code/cua-sdk` package. Both use the same in-process native runtime; MCP remains the agent-facing boundary implemented by `qwen-cua-driver`. The stable C ABI is declared in [`rust/include/cua_driver_abi.h`](rust/include/cua_driver_abi.h). The contract and generated bindings are documented in [`contract/README.md`](contract/README.md). ## Permission modes `standard` is the promptless default for ordinary automation. `bounded` admits only reviewed tools and resources. `unrestricted` requires `--dangerously-bypass-approvals`. The mode belongs to the process that owns the runtime and is fixed at launch: `qwen-cua-driver serve` takes the flags, while `qwen-cua-driver mcp` and embedding hosts use the matching `CUA_DRIVER_PERMISSION_MODE`, `CUA_DRIVER_CAPABILITY_MANIFEST_FILE`, and `CUA_DRIVER_CAPABILITY_MANIFEST_APPROVED` variables. Choose it before starting the daemon; a running daemon must be restarted to change it. Attaching to an existing logged-in Chromium profile remains explicit: ```bash qwen-cua-driver mcp --grant existing-profile ``` An embedding application can instead provide `DriverAuthorizationHost` and own the permission prompt and grant lifecycle. ## Qwen normalized coordinates Pixel coordinates remain the default. Set: ```bash export CUA_DRIVER_RS_COORDINATE_SPACE=1 export CUA_DRIVER_RS_COORDINATE_SCALE=1000 # optional; 1000 is the default ``` to expose and accept a 0-1000 coordinate grid. Translation happens at the canonical tool-registry boundary shared by MCP, CLI, daemon, private worker, replay, and direct SDK execution. Window-local actions use the most recent snapshot dimensions; screen-space actions use the logical screen dimensions. Missing or stale coordinate bases fail closed instead of being guessed. Browser CSS coordinates are deliberately not normalized. In normalized mode, use a fresh browser element reference for `browser_click` and `browser_pointer`; raw CSS coordinates are rejected. ## Model-visible payload filtering Set `MCP_MODEL_PAYLOAD_FILTER=1` to filter affected Qwen-facing textual MCP payloads. The filter covers both text and structured content and leaves binary image/media payloads opaque. It is off by default and does not change the direct SDK contract. ## Telemetry boundary Telemetry is disabled by default in the Qwen distribution. It can be enabled explicitly with `qwen-cua-driver telemetry enable` or the documented `CUA_DRIVER_RS_TELEMETRY_ENABLED=1` environment override. Explicit opt-in sends the upstream content-free event schema to Cua's PostHog endpoint; no Qwen telemetry service or proxy is involved. Use `qwen-cua-driver telemetry status` to inspect the effective decision and `qwen-cua-driver telemetry disable` to turn it off. A normal uninstall preserves the preference and pseudonymous installation identifier; use `--purge` on Unix or `CUA_DRIVER_RS_UNINSTALL_PURGE=1` on Windows to remove them. ## macOS identity and permissions macOS attributes Accessibility and Screen Recording grants to the responsible app identity. Install and grant permissions to `QwenCuaDriver.app`. The installed CLI can proxy through that app-owned daemon. `qwen-cua-driver mcp --direct` deliberately uses the spawning host's TCC attribution and is not a substitute for a certified embedding host. Do not grant permissions to an arbitrary loose binary path in production. Signed and notarized release artifacts are produced only by the Qwen-owned release workflow. ## Repository layout | Path | Purpose | | ----------------- | -------------------------------------------------------------------- | | `rust/` | Cargo workspace for the CLI, daemon, SDK, platform crates, and tests | | `python/` | Python SDK and bundled-runtime wrapper | | `typescript/` | TypeScript SDK and native runtime loader | | `contract/` | Generated portable contract and fixtures | | `tests/fixtures/` | Cross-platform GUI harness applications | | `scripts/` | Release/local install, uninstall, generation, and sync helpers | | `docs/` | Package-local architecture and behavior notes | Start with [`rust/README.md`](rust/README.md), [`docs/test-matrix.md`](docs/test-matrix.md), and [`tests/fixtures/README.md`](tests/fixtures/README.md) when changing runtime behavior or test coverage. ## Development ```bash cd packages/cua-driver/rust cargo fmt --all -- --check cargo check -p cua-driver -p cua-driver-core -p cua-driver-sdk cargo test -p cua-driver-core ``` Generated contract and language bindings must be checked with the package-local scripts before release. Signed/notarized macOS, Windows UIAccess, Linux X11, and real MCP/model verification remain platform release gates.