English | 简体中文
Cross-platform Computer Use Automation runtime and CLI, backed by the open-source CUA SDK.
The project began inside dcc-mcp-core, where it reproduced the Computer Use
workflow used by Codex. CUA SDK's cross-platform support made that boundary
useful beyond one host, so it was extracted and extended as dcc-cua for any
agent or application to embed.
dcc-mcp-core remains one consumer, not a runtime dependency. The Host protocol
is product-neutral; application_label is only a bounded human-readable
safety-banner label. Its public protocol is owned by this repository and
provides:
- exact PID/window/title scope; agent requests cannot widen the target;
- a fresh observation ID is required for every mutation;
- bounded text, key, drag, and coordinate input;
- fail-closed sensitive-window policy;
- explicit stop/resume lifecycle and structured errors;
- a visible, vector-rendered CUA mouse-pointer cursor on Windows, Linux, and
the packaged macOS Host,
plus a Host-owned, localized
<agent> is controlling <app>safety banner with a session-specific hue and softly breathing target-window frame on Windows. Windows and Linux reuse CUA's native per-session cursor and badge; macOS re-enters the samedcc-cuaexecutable as a private SDK worker so AppKit remains on that worker's main thread. Headless macOS sessions still return CUA's structured readiness refusal. All supported indicators are click-through and excluded from agent captures. Windows physical Escape and the cross-platforminterrupt_allHost request advance the same Host-process stop generation for every active connection. The Windows Escape boundary uses a non-exclusive low-level hook only while a control banner is active, so another application's global hotkey cannot silently disable the stop control; the key is consumed instead of also being delivered to the controlled application. Agent-injected Escape is not an operator stop signal: it passes through to the granted target window and does not advance the shared stop generation.
Windows mixed-DPI acceptance can be collected without activating or inputting
into the target with python -B scripts/indicator-acceptance-probe.py --target-pid <pid> --target-hwnd <hwnd>. The probe emits JSONL and fails closed
unless the exact 45-DIP frame, 20-band fade, motion policy, monitor migration,
window styles, and target-scoped z-order contract are all observed.
The repository is a Cargo workspace with eleven product responsibilities plus the Hakari dependency-unification support crate:
dcc-cua-core: scoped Computer Use domain, safety policy, and CUA execution boundary;dcc-cua-e2e: opt-in controlled GUI tests against the upstream CUA Electron fixture and the public Host IPC contract;dcc-cua-browser: exact-window browser binding, tab snapshots, typed browser actions, and bounded file transfer;dcc-cua-client: reusable Core-side Host IPC client with request correlation and binary image attachments;dcc-cua-host: long-lived versioned IPC and request routing;dcc-cua-indicator: Host-process stop generation plus the Windows control banner/frame and physical Escape boundary; cursor/badge rendering stays in the CUA SDK, while the packaged macOS Host uses its self-hosted private-worker overlay;dcc-cua-platform-windows: exact PID/HWND Windows UI Automation worker for background semantic fallback when CUA's combined window-state path is unavailable;dcc-cua-protocol: shared Host wire limits and per-user local endpoint identity used by both the Host and reusable Client;dcc-cua-shm: cross-platform shared-memory image handoff;dcc-cua-semantic-profiles: validated application selectors, surfaces, targets, route hints, and fallback edges;dcc-cua-cli: the thin CLI process that composes the workspace crates.
Inside dcc-cua-core, source files follow domain responsibility rather
than numeric partitions: contracts.rs owns public requests/results and shared
limits, runtime.rs owns driver/session orchestration, window_target.rs owns
exact native-window identity, observation.rs owns observation construction,
and policy.rs owns trust-boundary validation, action translation, and SDK
error/result normalization.
Application-specific adapters stay above this workspace. Browser control uses CUA's typed CDP routes first, then a browser semantic/DOM adapter, exact-window OS accessibility, and finally explicitly approved exact-window pixels. It does not enter UIA before proving an available CDP route. Unreal/Fab flows belong in the Unreal or browser adapter and should combine typed Unreal APIs with scoped CUA. If the in-editor Fab download route is unavailable, the UE profile points to the Fab profile's Epic Games Launcher fallback. Fab account and purchase boundaries remain explicit; security and human-verification clicks additionally require a trusted-confirmation task grant.
The dcc-cua-semantic-profiles crate is the application-specific extension
point for deeper semantics. It ships validated profiles for ue, maya,
maya-2024, and fab without adding application branches to the generic Core or Host. Each
profile describes window/URL selectors, semantic surfaces and targets, the
preferred route, and dialog policy. The built-ins are the official defaults;
users and studios can supply a compatible JSON profile through the same CLI
execution path.
Profiles are declarative routing and vocabulary contracts. They do not launch an application, switch control routes, perform a fallback, or prove application state. Core and Host still own exact-window scope, fresh observations, grants, actions, and post-action verification.
Portable profile packages use profile-package.json schema 2. The manifest
declares typed artifacts rather than an untyped file list, requires exactly
one semantic_profile, and declares the minimum compatible CLI through
requires.dcc_cua. Skills, documentation, fixtures, context documents, and
companion source are optional artifact types. A package is installed only after
every declared artifact, version requirement, identity, path, and size limit is
validated.
Application startup knowledge uses generic identity-fenced documents, so the same contract can represent an Excel workbook/template, PowerPoint deck/theme, DCC plugin ABI, game data snapshot, or policy revision:
dcc-cua profile context --id excel `
--identity document=sha256:... --identity template=quarterly-v3 `
--selector workflow=financial-reviewIdentity and selector values are exact and case-sensitive. Every matching
document is returned; duplicate document IDs or an index/document fence
disagreement fail closed. The JSON schemas live under docs/schemas/.
| Field | Agent meaning |
|---|---|
profile_version |
SemVer of the Profile data. In a package it must equal profile-package.json.version. |
application |
Stable host family plus optional exact host-version tokens. maya-2024 therefore cannot match a Maya 2025 title. |
extends |
Optional single parent ID plus SemVer requirement. Runtime resolves and flattens inheritance before the Agent uses the Profile. It never inherits authorization or window scope. |
selectors |
Candidate application/window or URL identities. Selector objects are OR alternatives. Inside one object, the application constraint is ANDed with one match from the combined generic/localized title aliases. URL-only selectors never match native windows. |
surfaces[] |
A stable task area such as outliner, dialog, or launcher_download. Its route selects the owning executor. |
targets[] |
Stable intent vocabulary. names, BCP-47 keyed localized_names, and automation_ids narrow live matches; supported_actions is an allow-list. Optional key_bindings maps a supported semantic action to 1-4 verified keys. |
fallback |
A reference to another profile_id and surface_id. The agent must re-discover, bind, observe, and verify that route; no transition is automatic. |
settings |
Profile-wide route preference, optional default_locale for untagged aliases, dialog style, and destructive-confirmation policy. Surface routes take precedence for a concrete task. |
Route ownership is explicit:
| Route | Owning path |
|---|---|
accessibility |
The profile CLI can inspect and act when exactly one fresh live element matches. |
unreal_typed_api |
The Unreal adapter/Skill executes the typed operation and returns authoritative state. |
browser_dom |
The exact-bound browser adapter executes DOM work. Do not substitute the in-app Browser skill. |
os_native_dialog |
The platform-native dialog path binds and controls the exact dialog window. |
visual_fallback |
dcc-cua uses a fresh exact-window visual observation; desktop scope remains explicit and separate. A declared key_bindings action may execute after that same observation fence. |
Multilingual aliases are additive and locale-agnostic at runtime. Every alias is
eligible to match, so an agent does not need to guess the current UI locale
before discovery. Locale tags make coverage inspectable through
dcc-cua profiles and maintainable by profile authors. Matching trims and
collapses whitespace and applies Unicode lowercase conversion. Keep profile,
surface, target, role, action, and automation IDs stable; localize only visible
window-title fragments and element names. default_locale identifies untagged
aliases when known. Existing profiles that only use window_title_contains and
names remain valid.
Use this profile-aware agent loop:
- Run
dcc-cua profiles, inspect itssupported_locales, and print the candidate withdcc-cua profile --id ID. When the application/window is already known, usedcc-cua profile match --app APP --title TITLE; a unique version-specific match wins over the family Profile, while equally specific candidates are reported as ambiguous instead of being guessed. - Discover the real PID/window with
dcc-cua list --on-screen, then bind that exact identity. Confirm that its application/title or URL matches a selector. - Choose the task surface and query the stable target ID. Use localized names
only to match live UI. Reject actions absent from
supported_actions. - Dispatch through the surface route above.
profile --actionis supported only foraccessibility; other routes are intentionally declarations for their owning adapter. - If a target has
fallback, switch to the referenced profile/surface and repeat discovery, exact binding, and observation. For example,ue/fab/downloadfalls back tofab/launcher_downloadwhen the in-editor path is unavailable. - Take a fresh observation after every mutation and verify the requested state independently. Input delivery alone is not success.
Inspect the extension catalog without starting a DCC process:
dcc-cua profiles
dcc-cua profile --id maya
dcc-cua profile --id maya-2024
dcc-cua profile match --app maya.exe --title "Autodesk Maya 2024: scene.ma"
dcc-cua profile --profile-file C:\profiles\maya-studio.jsonAfter discovery, inspect or execute one accessibility target using the exact
identity returned by list:
dcc-cua list --app maya.exe --on-screen
dcc-cua profile --id maya --pid $pid --window-id $hwnd --surface home --query new_scene
dcc-cua profile --id maya --pid $pid --window-id $hwnd --surface home --query new_scene --action click --activateMaya's profile explicitly sets dialog_style to os_native and routes its
file dialog surface through os_native_dialog, so an adapter can request the
operating system's native dialog semantics instead of treating it as an
application-rendered panel.
The repository also ships standalone Agent Skills under skills/:
cua-cli: the standalone CLI control loop, verification, safety, and long-task recovery;cua-profile-authoring: official and user-authored semantic profile guidance.
They use the released dcc-cua CLI and are included in release archives, so
another agent can install a single Skill without coupling to the Rust workspace.
Multiple agents may keep independent exact PID/HWND sessions open for different
applications. Semantic, UIA, and browser operations remain parallel; actions
that consume the single OS keyboard/mouse stream use one fair Host-wide FIFO and
release it before post-action capture. Run one Host process per interactive OS
seat so the shared Escape broadcast and raw-input ordering have one owner.
Public session_id values are connection-scoped: Host mints a private CUA
runtime identity for every opened window or desktop session and rewrites it at
the IPC boundary. Two agents may therefore both use session-1 without sharing
cursor, browser refs, recording ownership, capture scope, or cleanup state.
Game automation is supported as an exact-window black-box test surface for menus, launch flows, HUD interaction, input replay, screenshots, and visual regression. For authoritative 3D state, performance, physics, or gameplay assertions, combine CUA input/vision with engine-native telemetry and test APIs such as Unreal Automation or Gauntlet; protected anti-cheat environments and exclusive full-screen capture are outside this Host's contract.
This project wraps the CUA SDK for agent-friendly, bounded operations. The
dcc-cua CLI owns its Host and update lifecycle and uses the SDK in-process;
users do not install or run a separate cua-driver executable or daemon. Use
this CLI/Host for its safety envelope, exact-window capability, fresh
observations, grants, friendly actions, and software-specific adapters.
Every Rust file is limited to 2000 lines. Unit tests live in a sibling
src/tests.rs module rather than production files, use rstest, and run with
cargo-nextest; the same layout gate runs before formatting in CI. A
Hakari-managed dcc-cua-workspace-hack unifies dependency features for the
four supported build targets while leaving target and host graphs separate for
the upstream MSVC Spectre dependency. Install both tools once:
vx cargo install cargo-nextest cargo-hakari --lockedvx cargo hakari generate --diff
vx cargo hakari manage-deps --dry-run
pwsh -NoProfile -File scripts/check-rust-layout.ps1
vx cargo fmt --all -- --check
vx cargo nextest run --workspace --all-targets --locked
vx cargo test --workspace --doc --lockedUse Cua-Bench only as an external development harness for deterministic tasks
with reset and outcome evaluators. Drive those tasks through the same
host-jsonl contract used in production, and report success, action count,
visual/semantic/post-action observation count, image pixels/encoded bytes,
errors, elapsed time, and wire bytes. Keep transport
microbenchmarks in Rust and do not add Cua-Bench, its Python environment, or VM
providers to the shipped runtime. A live game session without a reset/oracle is
showcase evidence, not a repeatable benchmark.
Pass --metrics-output artifacts/cua-bench/dcc-cua-metrics.json to the
development host-jsonl bridge. The bridge atomically refreshes the report
after every response, so a long-running task can be inspected before EOF.
run_status is running, succeeded, or failed; transport_success is null
until the bridge finishes. The v3 report separates attempted/succeeded/rejected
actions, visual/semantic/post-action observations, image pixels/encoded bytes,
live-observation start/clean-stop lifecycle, errors, elapsed time, and JSON payload bytes.
action_kinds and error_codes make repeated pointer motion and platform
refusals visible without reparsing the full JSONL trajectory. Cua-Bench remains
responsible for reset and outcome evaluation.
On Windows, vx.toml selects MSVC 14.44 with Spectre-mitigated libraries and
injects its Windows SDK environment into Cargo. Release archives contain one dcc-cua
executable plus assets, Skills, and both project and upstream license notices.
Each target also publishes a stable
dcc-cua-install-manifest-<target>.json containing the exact HTTPS archive URL
and SHA-256 digest for package managers such as dcc-mcp-cli. The built-in
updater requires the exact <archive>.sha256 sidecar and verifies it before
extracting or replacing the executable.
cargo run -p dcc-cua-cli -- list --app chrome.exe --title "New Tab" --on-screen
cargo run -p dcc-cua-cli -- wait-window --app UE5Editor.exe --title "PCG Fab" --on-screen
cargo run -p dcc-cua-cli -- apps
cargo run -p dcc-cua-cli -- tools
cargo run -p dcc-cua-cli -- call --tool check_permissions --json '{}'
cargo run -p dcc-cua-cli -- call --tool set_config --json-file payload.json
cargo run -p dcc-cua-cli -- manifest
cargo run -p dcc-cua-cli -- desktop-snapshot --output desktop.png
cargo run -p dcc-cua-cli -- screen-size
cargo run -p dcc-cua-cli -- cursor-position
cargo run -p dcc-cua-cli -- desktop-act --action-json '{"action":"click","x":100,"y":100}'
cargo run -p dcc-cua-cli -- act --app chrome.exe --action-json '{"action":"click","x":100,"y":100}' --output after.png
cargo run -p dcc-cua-cli -- launch --name Calculator
cargo run -p dcc-cua-cli -- doctor
cargo run -p dcc-cua-cli -- doctor --spawn target/debug/dcc-cua
cargo run -p dcc-cua-cli -- snapshot --app chrome.exe --output screenshot.png
cargo run -p dcc-cua-cli -- accessibility --app chrome.exe
cargo run -p dcc-cua-cli -- window-state --app chrome.exe
cargo run -p dcc-cua-cli -- activate --app chrome.exe
cargo run -p dcc-cua-cli -- set-window-frame --pid 4242 --window-id 123456 --x 80 --y 80 --width 1280 --height 720
cargo run -p dcc-cua-cli -- invoke-menu --app maya.exe --menu File --menu "New Scene"
cargo run -p dcc-cua-cli -- click --app chrome.exe --x 100 --y 100
cargo run -p dcc-cua-cli -- click --app chrome.exe --element-index 12
cargo run -p dcc-cua-cli -- toggle --app chrome.exe --element-index 14
cargo run -p dcc-cua-cli -- set-value --app chrome.exe --element-index 15 --value Published
cargo run -p dcc-cua-cli -- drag --app chrome.exe --from-x 100 --from-y 100 --to-x 300 --to-y 200 --duration-ms 750 --steps 32
cargo run -p dcc-cua-cli -- type --app chrome.exe --text "hello" --focused
cargo run -p dcc-cua-cli -- hotkey --app chrome.exe --key CTRL --key L
cargo run -p dcc-cua-cli -- scroll --app UE5Editor.exe --scroll-x 4 --by page --x 600 --y 900
cargo run -p dcc-cua-cli -- act --app chrome.exe --action-json '{"action":"click","x":100,"y":100}'
cargo run -p dcc-cua-cli -- verify --app chrome.exe --expect-json '[{"window":{"exists":true}}]'
cargo run -p dcc-cua-cli -- update --checkupdate downloads one exact platform archive, validates the replacement
executable, and replaces the CLI. The SDK runtime is statically linked into the
same versioned executable. Release discovery uses the GitHub REST API first and
falls back to the public releases/latest redirect when the API is rate limited
(HTTP 403); set GITHUB_TOKEN or GH_TOKEN to raise the unauthenticated API
quota of 60 requests per hour per IP address.
manifest is the stable machine-readable discovery entry for Core and other
independent callers. It reports the current platform, Host protocol, frame
limits, snapshot transports, capabilities, endpoint, recommended stdio/JSONL
launch arguments, and that no separate driver executable is required.
list, apps, tools, desktop-snapshot, screen-size, cursor-position, and
doctor are read-only. snapshot and act require one exact
target; if an application has multiple windows, pass --pid and
--window-id instead of relying on an app name.
doctor runs CUA's check_permissions and health_report concurrently with
driver/window discovery. It reports the upstream structured checks for native
accessibility, screen capture, platform support, and input readiness, and exits
non-zero when the authoritative health status is not ok. Its ready field
also becomes false when the current Windows session is disconnected, its input
desktop is not the interactive Default desktop, or the process cannot read
the current input surface, even if UIA and screen-capture permissions remain
available. A temporarily absent foreground window is reported as diagnostic
state but does not by itself imply that the desktop is locked. Exact-window
capture and showcase recording remain independently observable, while raw
input first requires a successful read-only cursor probe and then activates and
revalidates the granted PID/HWND before injection. The report includes the
native WTS, observation, and input-surface state; raw mouse/keyboard routes fail
before input with interactive_desktop_unavailable, while
exact-element Windows UIA operations can continue through their background
semantic path.
Use doctor --route visual when the intended contract is exact-window capture
plus bounded coordinate input on a custom-rendered DCC or game surface. The
report keeps the strict aggregate ready field and adds independent routes
for full, visual, and semantic; a degraded UIA provider therefore remains
visible without incorrectly rejecting a healthy WGC/Win32 visual route. On
Windows, a timed-out global UIA desktop enumeration is reported as a degraded
exact_window_uia_fallback semantic route when UIA permission remains present;
the fallback still requires an exact PID/HWND and a fresh fenced observation.
The default doctor behavior remains strict and backward compatible.
list accepts optional --app, --pid, --window-id, --title, and
--on-screen filters. --app is case-insensitive; --title is exact and
bounded, so Core can select a UE/Fab subwindow without receiving the entire
inventory over Host IPC. wait-window polls CUA's native window inventory for an app,
process ID, window handle, or exact title. It is capped at 30 seconds and is
intended for launch/switch orchestration before a target-bound action.
snapshot returns the screenshot plus a bounded semantic tree (default 512
elements and 16 levels). accessibility reads a larger semantic tree without
transferring screenshot pixels when the agent needs to locate a deeply nested
control. Prefer the returned element_token/element_index over guessed
pixels, then verify the post-action state. UIA element bounds are explicitly
tagged as virtual_desktop, while window pixel actions use non-negative
coordinates from the latest exact-window screenshot. Desktop actions use signed
virtual-desktop coordinates, including negative X/Y on Windows monitors left of
or above the primary display. window-state, activate,
set-window-frame, and invoke-menu operate on the same exact target scope.
Long-lived recording remains on the persistent Host session so its start/stop
lifecycle is not lost when a one-shot CLI process exits.
The friendly selector forms also include toggle, drag, set-text, and set-value.
Click, toggle, scroll, press, hotkey, type, and value actions can target the
latest semantic tree with --element-index or --element-token; coordinate
actions remain available for custom-rendered surfaces. Semantic type
uses CUA's canonical type_text element path; type --x X --y Y
uses CUA's pixel-focus-then-type path for Chromium/Electron and other
custom-rendered inputs; press and hotkey accept the same focus coordinates.
press --modifier M and drag's --modifier M map to CUA's native modifier
fields, while click and drag accept --button left|middle|right.
Scroll accepts one signed axis per action (--scroll-x or --scroll-y), an
optional --by line|page, and either a semantic element or exact window-local
coordinates. This preserves horizontal timeline/canvas scrolling instead of
silently converting it to a vertical wheel action.
One-shot window and desktop actions always attempt a fresh post-action
snapshot. --output FILE writes that post-action image, and the JSON result
includes post_snapshot. If capture fails after input was already delivered,
the command reports action_was_executed: true instead of returning a generic
mutation failure that could cause an unsafe retry.
Their banner and frame exist only for that command's session lifetime. Core and
other multi-step agents should keep one Host IPC session open so the same exact
PID/HWND retains its visible banner, breathing frame, cursor, and observation
fence across actions. The Windows UIA worker starts through a separate readiness
handshake. A due upstream-session refresh never crosses an action request: Core
refreshes before the next observation and requires a new observation fence
before input. A refresh or activation timeout leaves the local long-running
session alive and returns a typed no-blind-retry result. Only a timeout after an
action was actually dispatched is completion-unknown and invalidates that exact
local window session.
The shared Core window session owns this ControlBanner, so direct dcc-cua
window actions and Host IPC sessions use the same visible banner and target
frame. The Host's Hello client_name is shown as the agent name; the text
follows the operating-system language and the color is stable for that agent's
session while avoiding the default banner hue. Desktop-scope sessions have no
single PID/HWND to frame and therefore retain the localized CUA desktop marker
instead.
For common controls, click, double-click, right-click, move, scroll,
press, hotkey, and type build the same fenced CUA actions without manual
JSON. type requires --focused or an explicit --element-index/
--element-token; hotkey accepts repeated --key values.
apps uses CUA's cross-platform application inventory. launch accepts one
explicit selector (--name, --bundle-id, --aumid, --path, or
--launch-path) or at least one bounded http, https, or Epic Launcher URL,
supports repeated --url/--arg values, and applies the same
sensitive-application deny policy as the host.
Clipboard access is session-scoped and grant-gated: clipboard_read does not
return text unless the caller asks for it, and clipboard_write accepts exactly
one bounded text, image path, or regular-file path. Recording is also
grant-gated through recording_start, recording_stop, and recording_state.
live_observation_start prefetches the exact window's latest frame with a
requested ceiling of 1..30 FPS. Windows owns one persistent D3D11
device, capture session, frame pool, and reusable staging texture for the feed;
if that backend cannot initialize, the state identifies the one-shot WGC
fallback instead of silently claiming the fast path. macOS and Linux retain the
same latest-frame contract through bounded driver PNG capture/decode. Decision snapshots preserve
the full-window coordinate mapping while bounding their longest edge with
max_dimension (default 1568, accepted range 256..4096); showcase recording
keeps its independent video sizing. State reports the lifetime effective_fps,
EWMA recent_effective_fps, last_capture_duration_ms,
max_capture_duration_ms, and capture_mode. While active, snapshot consumes
only a newer frame, encodes that selected frame once, and skips UIA; use
accessibility_snapshot separately when semantic state is needed. Stop it with
live_observation_stop.
Showcase video rolls into independently decodable five-minute MP4 segments so
an interrupted long run cannot invalidate footage that was already finalized.
The first segment retains the compatible showcase.mp4 path; later segments
use ordered names such as showcase-0002.mp4. Only the active tail is written
as *.partial.mp4 and exposed as current_partial. Each completed segment
starts with an IDR access unit and carries its own SPS/PPS track configuration.
recording_stop finalizes the tail, clears current_partial, and atomically
publishes showcase.manifest.json with the ordered, non-overlapping segment
timeline. If the interactive desktop is temporarily unavailable, the live
producer and recording owner remain active but report paused and
video_paused; cached frames are not encoded again. Capture resumes in the same
stream only after a strictly newer frame, while a missing window or changed
PID/HWND owner remains terminal. A crash can therefore strand only the
explicitly partial tail, not the earlier readable segments.
Start one persistent host process instead of spawning a process per action:
cargo run -p dcc-cua-cli -- host --stdio
cargo run -p dcc-cua-cli -- host
cargo run -p dcc-cua-cli -- host-ensure
cargo run -p dcc-cua-cli -- ping --spawn target/debug/dcc-cua
cargo run -p dcc-cua-cli -- interrupt-all
cargo run -p dcc-cua-cli -- host-call --method list_apps --json '{}'
cargo run -p dcc-cua-cli -- host-batch --json '[{"method":"list_apps","params":{}},{"method":"screen_size","params":{}}]'
cargo run -p dcc-cua-cli -- host-call --spawn target/debug/dcc-cua --method list_apps --json '{}'
# Keep one Host connection open and process one JSON request per input line.
cargo run -p dcc-cua-cli -- host-jsonl --spawn target/debug/dcc-cua --output-dir artifacts
# Batch only stateless discovery lines within a short window.
cargo run -p dcc-cua-cli -- host-jsonl --parallel-discovery --spawn target/debug/dcc-cuadcc-cua-client is the direct embedding path for dcc-mcp-core. It opens
the per-session endpoint, performs hello, sends JSON requests, and returns
the following binary image frame without base64 decoding in the control path:
let mut host = dcc_cua_client::HostClient::connect_default("dcc-mcp-core").await?;
let response = host.request("list_windows", serde_json::json!({})).await?;
let stopped = host.interrupt_all().await?;HostClient::interrupt_all and dcc-cua interrupt-all [--endpoint PATH]
broadcast a cooperative safety stop to every connection in the selected Host
process. The calling connection is cleaned up before acknowledgement. Other
connections poll the shared stop generation while otherwise idle, then
proactively stop live observation, finalize recording, invalidate frames, and
retain interrupted window/desktop tombstones; those sessions return
user_interrupted on subsequent use. An already-running native SDK call remains
bounded by the Host action timeout because CUA exposes no portable preemption
primitive.
dcc-cua host-ensure [--endpoint PATH] is the idempotent supervisor entry
for Core and adapters. It first probes the local endpoint, starts this same
version of dcc-cua host only when absent, and waits for a negotiated ping.
An endpoint served by a different CLI version fails closed with restart
guidance instead of being reported as ready.
Windows also holds one named singleton per endpoint because named pipes alone
permit multiple server instances; Unix keeps the existing socket bind as its
singleton boundary. Independent Core bridges can therefore share one Host per
interactive OS session while retaining connection-scoped agent sessions.
When Core owns the Host lifecycle, use HostProcess::spawn to start the CLI
with host --stdio, reuse the same negotiated HostClient, and call
shutdown when the task ends. This keeps process supervision out of Core's
request code while preserving the same protocol as endpoint connections.
let mut host = dcc_cua_client::HostProcess::spawn(
"dcc-cua",
"dcc-mcp-core",
dcc_cua_client::SnapshotTransport::SharedMemory,
).await?;
let response = host.client_mut().request("list_apps", serde_json::json!({})).await?;
let _status = host.shutdown().await?;Supervisors can poll host.is_running() and call host.restart(...) after a
process exit. Restart is explicit and never replays requests; Core must reopen
sessions and obtain a fresh observation before sending another action.
HostClient::ping and dcc-cua ping provide a small protocol-level
liveness check without querying the native CUA backend or transferring its
tool inventory.
HostClient::doctor and dcc-cua doctor --endpoint/--spawn probe the
selected CUA runtime owned by that Host process. The structured report keeps
transport liveness separate from driver, window inventory, permission, and
native health readiness.
Long waits can use HostClient::request_with_cancel; it sends cancel on the
same connection and consumes both the cancellation acknowledgement and the
wait terminal response.
Read-only discovery and observation calls can use HostClient::request_batch
to write several requests before one flush; responses are returned in request
order. Core callers that need task/turn tracing can use
HostClient::request_batch_with_ids, which preserves caller-owned IDs through
the same pipelined write. The Host dispatches stateless discovery calls
(ping, list_apps, list_tools, list_windows, screen_size, and
cursor_position) concurrently; exact-window and desktop session state stays
serialized. The client matches responses by request_id, so completion order
does not change the caller's result order. Mutating methods stay on request
so side effects remain explicit. The handshake advertises this as
pipelined_read_requests and parallel_discovery_requests.
The host-batch CLI accepts {request_id?, method, params} objects and uses
one persistent Host connection; supplied IDs are echoed, while omitted IDs
receive a deterministic host-batch-N ID. If a response contains image
pixels, pass --output-dir DIR; metadata-only batches can omit it. host-call and
host-batch accept --spawn BINARY for a one-shot stdio-managed Host when a
supervisor does not already own an endpoint.
host-jsonl is the streaming CLI bridge for dcc-mcp-core and scripts. It keeps
one negotiated Host session open, reads one {request_id?, method, params}
object per line from stdin, and writes one response object per line to stdout.
When present, request_id is preserved end to end for Core task/turn tracing.
Binary image attachments are written to --output-dir; shared_memory keeps
image pixels out of the Host control pipe. The machine manifest publishes the
transport-neutral host-jsonl entry point so Core can prefer shared memory and
fall back to binary attachments when its native shared-memory reader is absent.
Consumers that need a standard MCP tool-result envelope can opt in with
--response-format mcp. Each JSONL response then contains content,
structuredContent, and isError; window, desktop, post-action, browser, and
native-tool image attachments are promoted to native MCP image content. The
default host response format remains unchanged. This flag projects Host
responses only—it does not turn the JSONL transport into an MCP JSON-RPC
server.
dcc-cua host-jsonl --response-format mcp --snapshot-transport shared_memory--parallel-discovery batches contiguous ping, list_apps, list_tools,
list_windows, screen_size, and cursor_position requests for up to 5 ms or
32 lines, preserves input order and request_id, and leaves stateful,
visual, browser, and mutating requests serialized.
The Host enforces the same per-connection ceiling with backpressure and reaps
completed discovery tasks while the connection stays open, so a long-running
Core bridge cannot retain one task allocation per request.
The Rust Client rejects larger single batches before writing to the transport;
host-jsonl --parallel-discovery automatically splits a longer stream into
bounded batches on the same connection.
The endpoint admits at most 32 simultaneous client connections and applies
transport backpressure before creating another connection task. The manifest
publishes both connection and per-connection discovery limits for supervisors.
Each agent thread should own one persistent Host connection and open its own
TaskGrant-bound window sessions on that connection. A connection may own up to
16 window, desktop, and launch sessions in total. Different connections may use
the same public session_id; their random window capabilities and observation
state remain private to the owning connection. Background-safe actions can make
progress independently, while physical desktop input is arbitrated by one
host-global FIFO so two agents cannot interleave keys or pointer mutations.
Disconnecting one agent stops only the sessions owned by that connection.
Supervisors can discover this contract through
host.session_concurrency and the multi_agent_sessions capability in
dcc-cua manifest.
Clients have 10 seconds from connection acceptance to complete hello;
negotiated Host connections remain long-lived without an idle deadline.
EOF, transport failures, and malformed frames all abort outstanding discovery
work and stop every private window, desktop, and launch session on that connection.
--metrics-output FILE atomically checkpoints development metrics after every
response and finalizes them at EOF or failure; it does not alter response JSONL
or the production Host protocol.
{"request_id":"core-task-42","method":"list_apps","params":{}}
{"request_id":"core-task-43","method":"list_windows","params":{"on_screen_only":true}}
For large or frequent images, use connect_default_with_transport(..., SnapshotTransport::SharedMemory) and open the returned descriptor with
dcc_cua_shm::SharedImageReader; window/desktop snapshots, verification
screenshots, and browser responses containing one image keep pixels out of the
control pipe. Native extension results and browser responses containing multiple images use one
bounded binary attachment frame with offset descriptors.
On Windows, the default endpoint is the per-session named pipe
\\.\pipe\dcc-cua-v1-session-<WindowsSessionId> with a protected DACL
that grants access only to LocalSystem and the current Windows logon SID. On Unix, the default
endpoint is $XDG_RUNTIME_DIR/dcc-cua-v1.sock when that directory is
owned by the current user with mode 0700; otherwise it falls back to
$TMPDIR/dcc-cua-<uid>/dcc-cua-v1.sock. The Host creates a missing
endpoint parent with mode 0700 and refuses relative paths or parents
that are not current-user 0700 directories. The protocol uses an unsigned
big-endian u32 length followed by one UTF-8 JSON request or response. A
client selects snapshot_transport as binary_frame (the default) or
shared_memory in hello; binary snapshots are followed by one additional
length-prefixed PNG frame, avoiding base64 pixel transfer and keeping the JSON
frame under 4 MiB. Requests may include a top-level request_id (1–128
characters); the host echoes it on the JSON response, including errors. The
handshake advertises the exact capabilities of this build.
dcc_cua_client::HostClient::capabilities() and
supports_capability(...) expose that negotiated list without requiring Core
to parse Host handshake JSON; callers can choose shared memory, batching, or
optional routes from the actual Host instead of assuming them.
Native tool results expose every returned image in attachments. The single
binary frame following the JSON response is the concatenation of those images;
each descriptor gives its offset, length, and mime_type.
The supported request surface is hello, ping, list_apps, list_tools, list_windows, wait_for_window, launch_app, open_session,
get_window_state, change_window_state (activate, restore_activate, or close), set_window_frame, invoke_menu, snapshot,
accessibility_snapshot, verify_state, call_tool, call_global_tool, get_session_state, cursor_tool, escalate_session, find, wait_for, browser_snapshot,
browser_prepare, browser_navigate, browser_click, browser_type, browser_pointer,
browser_set_input_files, browser_download, browser_dialog,
clipboard_read, clipboard_write, recording_start, recording_stop,
recording_state, live_observation_start, live_observation_state,
live_observation_stop,
desktop_snapshot, screen_size, cursor_position, open_desktop_session,
desktop_session_snapshot, execute_desktop_action, stop_desktop_session,
zoom,
get_input_state, poll_session_events, execute_action, resume_session, terminate_app, and
stop_session; cancel is available while wait_for is active and
cancel_window_wait while wait_for_window is active on the same connection.
get_input_state and poll_session_events expose one bounded, per-session
event stream with orthogonal current_state (interactive input) and
current_target_state (exact-window availability). Always continue polling
from the response-level latest_sequence; component sequence fields identify
only that component's last transition. The stream deduplicates unchanged
statuses without advancing the cursor while refreshing their sampled metadata,
reports overflow with resync_required, and emits
target_minimized/target_restored as well as input suspend/resume events.
foreground is sampled target metadata, not a separate transition event.
A minimized target pauses every action with automatic_input=false. For a
grant originally bound to an exact PID/HWND, an agent may explicitly request
change_window_state with operation: "restore_activate"; this restores only
that HWND, validates ownership and final foreground state, and still requires a
fresh observation. It never runs automatically or blind-retries. Interactive
desktop readiness is checked again immediately before each Windows mutation,
and all action/UIA/browser/shared observation caches are invalidated even when
the restore attempt only partially succeeds. Live observation, showcase, and
recording ownership remain intact.
execute_action accepts capture_after: true plus optional
post_snapshot_delay_ms (0..5000), post_snapshot_max_nodes, and
post_snapshot_max_depth. The Host then performs
the mutation and captures the next exact-window observation in one serialized
request, returns its screenshot and semantic tree as post_snapshot, and keeps
that observation current for the next action. The handshake advertises this as
action_post_snapshot and action_post_snapshot_delay. Use the delay for
custom-rendered applications that need a bounded settle period instead of
issuing a second snapshot. If only the post-action capture fails, the response
still reports the completed mutation and sets observation_required: true.
An action without capture_after also sets observation_required: true.
execute_desktop_action accepts the same capture_after: true flag and returns
the next full-display image and desktop state in post_snapshot; it has no
window accessibility-tree bounds.
Semantic actions use CUA element_index values from the latest
accessibility snapshot, and set_text/set_value/set_checked use CUA's
native semantic value path. Coordinate actions remain available for
custom-drawn surfaces. For applications that miss fast keystrokes, use
action: "type_chars" with delay_ms (0..200); it requires an
element_index/element_token, or the explicit type_chars_only: true when
the target field is already focused. This maps to CUA's cross-platform
type_text input path with character pacing and does not accept screen
coordinates.
list_windows supports optional app, pid, window_id, window_title, and
on_screen_only filters;
these are applied by the native backend before the response crosses IPC.
open_session grants may bind an exact window_title when Core does not yet
have the PID/HWND; the Host still requires the title to resolve to exactly one
native window before starting the CUA session.
open_session.params.activate_before performs only exact PID/HWND activation;
it does not restore a minimized target. The Host revalidates the same identity
at the Windows mutation boundary and validates the final foreground state. The
option defaults to false; title-only and process-only bootstrap activation
fail closed, and no general native-tool permission is granted. To recover a
minimized exact target, open without bootstrap activation and issue the explicit
grant-scoped restore_activate operation before taking a fresh observation.
If it becomes minimized after the session opens, use the typed target event
contract above. activate retains its existing semantics; only the explicit
restore_activate operation performs an exact restore before activation.
close posts a polite WM_CLOSE only to an exact Windows PID/HWND target and
requires allow_trusted_confirmation: true. It never terminates the process
and reports failure unless the HWND actually disappears.
wait_for_window accepts query with app, process_id, window_handle,
window_title, and on_screen_only; its timeout_ms is capped at 30 seconds.
When a request ID is supplied, cancel it on the same connection with
cancel_window_wait and {"wait_id":"<request_id>"}. The Rust Client's
wait_for_window_with_cancel helper sends that route automatically.
find filters the current accessibility tree by text, role, or element index
and returns a fresh accessibility_state_id. wait_for is bounded to 30 seconds and supports element_present,
text_contains, text_equals, and value_equals. launch_app requires a non-empty session_id, task_grant_id, application_label, and
allow_app_launch: true; terminate_app requires the separate
allow_app_terminate: true grant and force-closes only the exact session target;
neither permission inherits from an open DCC window
session. Clipboard operations require allow_clipboard_read or
allow_clipboard_write; recording operations require allow_recording: true;
live observation requires allow_live_observation: true.
Grant IDs are capped at 128 characters and application labels at 80; both reject
control characters and surrounding whitespace. The manifest exposes these
limits under host.grant_limits for non-DCC callers.
When CUA returns a newly launched PID, the Host keeps its private runtime
session alive and open_session with the same public session_id, task grant,
and application label promotes that ownership into the exact window session. This lets
CUA standard mode prove that terminate_app targets a process created by that
runtime; a different PID or grant is rejected. Keep these requests on one
persistent Host connection because launch ownership is connection-scoped.
Browser mutations additionally require allow_browser_input: true.
browser_prepare is destructive and separately requires
allow_browser_prepare: true; it never changes a personal browser profile
implicitly and forwards CUA's explicit setup refusal/approval contract.
For an isolated browser, mint the one-use approval through an operator-owned
upstream CUA installation, then pass its token to browser_prepare; DCC CUA
never mints a browser approval on behalf of an agent. Existing-profile attachment requires
a trusted Core authorization host created through
ComputerUseDriver::create_with_authorization_host; the default runtime and
Host process keep refusing it.
browser_snapshot first binds the exact native window, then snapshots a
specific CUA tab; browser_click, browser_type, and browser_pointer require
the latest browser snapshot_id, exact binding, and an explicit input route.
browser_navigate, browser_set_input_files, and browser_download invalidate
the tab snapshot. Upload uses allow_browser_input; download is a separate
destructive grant (allow_browser_download) and CUA's host approval evidence.
browser_dialog only resolves page-owned JavaScript dialogs and requires the
exact current dialog_id for accept/dismiss.
Attaching to a logged-in Chromium profile keeps CUA's R2 gate: launch the Host
with dcc-cua host --grant existing-profile and also set the session's
allow_browser_prepare grant. Without both approvals, attachment is refused.
allow_trusted_confirmation: true on an exact window or desktop task grant
only permits the Host to ask for confirmation; it never authorizes an action
by itself. Embeddings that support confirmation must start the library Host
with dcc_cua_host::run_with_confirmation_host and a constructor-owned
TrustedActionConfirmationHost. The callback is not reachable through Host
IPC. Each request binds the session, task grant, exact capability, current
observation/accessibility state, intent, and complete action into a SHA-256
digest. The Host accepts only an inline decision echoing that exact digest, so
a decision cannot be replayed after the evidence or action changes. Missing,
failed, or mismatched callbacks remain approval_required; explicit denial or
cancellation has its own typed error. Terminal/run-dialog, credential,
password-change, scope-escape, and safety-bypass intents remain hard-denied and
never reach the callback. The task-grant gate defaults to false and does not
follow from raw-input, browser-profile, or session-escalation access.
On Windows, non-pixel semantic access reuses one exact PID/HWND UIA worker per
session; CUA remains the cross-platform, browser, and visual backend. An
accessibility_snapshot creates a fresh non-pixel observation and returns
dcc-wuia: tokens; click, toggle, set-text, and set-value can consume those
tokens without a screenshot, raw-input grant, or explicit window activation.
The target application may still choose to activate itself when it opens a
visible menu or dialog.
If the upstream Windows session start itself times out, Host reports
upstream_session.state: "visual_only" and never re-enters that unresponsive
driver session. Exact local WGC/UIA observation remains available only after
the existing explicit escalation grant; semantic or upstream evidence stays
unavailable until a new session is opened.
For native windows whose UIA/AX provider is unavailable (for example a
game-engine editor or custom-rendered DCC surface), snapshot first attempts
the semantic window capture. After an explicit escalate_session approval,
the same exact-window session first uses CUA's native platform capture for that
validated HWND. Only when exact-window capture is unavailable may it crop a CUA
desktop frame, which requires the target to be foreground so another window
cannot be mistaken for it. The standalone Windows Host enters Per-Monitor V2
DPI awareness before creating CUA, and resized exact-window frames are mapped
back to native target coordinates. Exact Windows visual
captures also attach the bounded Windows UIA tree when available; otherwise
they are marked accessibility_available: false. Coordinate actions remain
bound to their exact PID/HWND.
One-shot CLI act and friendly action commands accept the same --activate
flag, so their pre-action observation and mutation remain in that foreground
session instead of racing a separate activation process.
desktop_snapshot is a full-display visual discovery surface; it does not
widen an existing window session or grant desktop-wide mutation. For an
explicit desktop input scope, use open_desktop_session, then take a fresh
desktop_session_snapshot and call execute_desktop_action; raw input grant
and the exact desktop capability are required.
Action responses preserve the CUA SDK's structured result, text, degraded
status, and image attachments. Host transports image bytes as the negotiated
binary attachment, so Core does not need to decode base64 on its control path.
While wait_for is running, the same connection accepts cancel with the
exact session grant and window capability; the host returns both a cancellation
acknowledgement and the wait's cancelled terminal response. Other requests stay
ordered and are rejected until that wait completes.
On Windows, activate uses the input-gated exact PID/HWND foreground primitive;
other platforms retain CUA's scoped bring_to_front operation. It never
restores a minimized target, and the returned state is independently
revalidated. An activation timeout is completion_unknown, requires a fresh
observation, and never authorizes a blind retry or tears down live observation,
showcase, or recording ownership.
set_window_frame uses an exact PID/HWND SetWindowPos path on Windows and
CUA's native cross-platform mutation elsewhere, followed by independent
geometry readback. Moving or resizing a window invalidates native and browser
observations, so callers must snapshot again before the next action.
invoke_menu forwards CUA's live native menu-path resolver, never guesses
pixels, and fails closed for missing or ambiguous levels. A successful native
delivery can remain unverifiable; take a fresh accessibility snapshot and
verify the application state before the next mutation. Host sessions require
the explicit allow_menu_invoke: true task grant because native menu commands
can be destructive; the one-shot CLI command itself is the explicit request.
zoom is a typed, read-only crop of the latest window snapshot. It requires
the matching observation_id, keeps the exact PID/HWND binding, limits the
requested width to 500 pixels, and returns the JPEG through the negotiated
binary or shared-memory image transport. This is useful for dense DCC/UE/Fab
panels where the full observation is resized.
Window actions accept CUA's element_token as an alternative to
element_index; when both are supplied the token wins. They also accept
delivery_mode: "background" | "foreground". The default is background,
which preserves the user's foreground and lets CUA select its accessibility or
synthetic-event route. Use foreground only after CUA reports that the
background route is unavailable.
Element indexes and tokens belong to the exact accessibility snapshot that created them. They are not interchangeable with indexes or tokens from a pixel snapshot, another backend, another window, or an earlier persistent session. The friendly semantic CLI commands take a fresh accessibility snapshot and rebind an index to its current token before delivery.
On Windows, a background UIA action can succeed even when Windows refuses to
restore the previous foreground window (or that window disappears during the
action). In that case the action result remains successful with
action_executed: true and reports the independent failure under
foreground_restore.success: false. Do not retry the input; take a fresh
observation and verify application state.
get_session_state reads CUA's live capture policy. escalate_session grants
pixel fallback only inside the existing exact-window scope and requires the
separate allow_session_escalation: true grant plus one of CUA's bounded
escalation reasons; it does not widen the session to desktop control.
The stable reasons are ax_tree_pixel_mismatch, background_delivery_failed,
foreground_ineffective, no_window_target, uia_timeout, and other.
Use --escalation-detail for the separate bounded audit note; manifest
publishes the same enum and meanings for machine discovery.
cursor_tool exposes move_cursor, set_agent_cursor_enabled,
set_agent_cursor_motion, set_agent_cursor_theme, and
get_agent_cursor_state; move_cursor is forced to scope: "window", and the
session id is always injected by Host, so the mouse-shaped marker cannot be
redirected to another session or move the real system pointer.
CUA owns the cursor state, scoped motion, and native cursor/badge renderer on
Windows and Linux. dcc-cua embeds and installs its purple 12-state CUA v2
theme as com.dcc-mcp.cursor in the standard CUA theme store. The packaged
macOS Host selects the same theme through its private worker. Application
identity remains the real executable icon in the dynamic control banner.
The safety banner remains a native overlay rather than a WebView. Static SVG art can be added as a cached theme layer later, while the app name and stop state remain runtime text; the current Win32 backend draws the small capsule directly and does not rerender an SVG every frame.
Extension tools from the live CUA inventory are available through call_tool
only after open_session grants allow_native_tool: true. The host injects
the exact session PID/HWND/session values from the live SDK schema and rejects
reserved arguments. CUA's canonical action-result vocabulary is always kept on
the dedicated routes, including platform-specific pointer actions. Click,
keyboard, browser, clipboard, recording, and
session-lifecycle tools stay on their dedicated grant-gated routes so the
extension surface cannot bypass observation or approval fences. This includes
CUA's legacy page compatibility tool; browser work must enter through the
exact-binding browser_snapshot route before any browser mutation.
The CLI call and host-call commands accept either --json JSON or
--json-file PATH; host-call reuses the persistent Host endpoint instead of
creating a new CUA driver for each request. host-call --output FILE consumes
both binary-frame images and negotiated shared-memory image descriptors.
--json-file - reads UTF-8 JSON from stdin, keeping large payloads off the
process command line. Host clients use call_global_tool for the grant-gated
global CUA tools check_permissions, health_report, get_accessibility_tree, get_config,
set_config, replay_trajectory, and install_ffmpeg; window tools continue
through call_tool with an exact session capability.
Example host requests:
{"method":"list_apps","params":{}}
{"method":"launch_app","params":{"session_id":"session-1","grant":{"task_grant_id":"task-1","application_label":"Unreal Editor","allow_app_launch":true},"launch":{"name":"Calculator"}}}
{"method":"call_tool","params":{"session_id":"session-1","task_grant_id":"task-1","window_capability":"cua-window-...","tool":"debug_window_info","arguments":{}}}
{"method":"zoom","params":{"session_id":"session-1","task_grant_id":"task-1","window_capability":"cua-window-...","request":{"observation_id":"session-1-obs-1","x1":120,"y1":80,"x2":420,"y2":220}}}
{"method":"call_global_tool","params":{"grant":{"task_grant_id":"task-1","application_label":"Desktop","allow_native_tool":true},"tool":"health_report","arguments":{}}}vx cargo hakari generate --diff
vx cargo hakari manage-deps --dry-run
vx cargo fmt --all -- --check
vx cargo check --workspace --all-targets --locked
vx cargo nextest run --workspace --all-targets --locked
vx cargo test --workspace --doc --locked
vx cargo nextest run --locked -p dcc-cua-e2e --features gui-e2e --no-run
pwsh -NoProfile -File scripts/run-gui-e2e.ps1 -Binary target/debug/dcc-cua.exeCI checks layout, formatting, workspace tests, the locked release build, and a
real release-binary E2E on Windows, Linux, and macOS. The E2E validates the
machine manifest, platform identity, shared-memory negotiation, a spawned Host
handshake, lightweight ping, pipelined/streaming request correlation, invalid
request recovery (including a UTF-8 BOM on the first JSONL line), and the
CUA application/tool inventories. On macOS the release Host also proves the
bundled private-worker route and its AppKit-owned session cursor. All three
platforms build CUA's official Electron fixture and verify the
real launch -> scoped PNG snapshot -> semantic find -> input -> state oracle ->
exact-window raw-input coordinate click -> independent state oracle ->
exact browser binding -> semantic browser snapshot -> click/type -> independent
state oracle -> cleanup path. Each lane also builds CUA's native WPF, GTK3, or
AppKit fixture and verifies an exact Window -> Arrange -> Left menu path by
reading fresh UIA, AT-SPI, or AX application state. Concurrent-session coverage
uses two independent endpoint clients controlling two Electron windows on
Linux/macOS and two non-foreground WPF windows on Windows; it also verifies
same-named public sessions remain runtime-isolated, Host-wide stop propagation,
and serialized concurrent raw input. The same CLI
E2E launches a real endpoint Host and
checks ping plus pipelined application/tool discovery over the platform transport
(Windows named pipe or Unix socket).
An additional lifecycle E2E uses Host IPC itself to launch an isolated native
fixture (Calculator as a fresh instance on macOS), promote the launch into the
same private runtime session, record a real mutation to action.json, stop the
recording, terminate only that proven PID, and verify its windows disappear.
The release workflow packages one dcc-cua executable, assets, Skills, and
both MIT license notices, then attaches the platform archives to the GitHub
release. CI exercises that self-contained SDK runtime and Host IPC on every
platform before GUI testing.
The release gate is intentionally closed while the product is still being
completed. Do not set the repository variable DCC_CUA_RELEASE_READY=true
until the full computer-control goal is accepted. The initial manifest starts
at 0.0.0, so the first release-please release will be 0.1.0; after that
release-please owns the manifest version and conventional-commit changelog.
The workflow uses the official cargo-workspace release-please plugin so all
workspace crates and Cargo.lock stay aligned. It does not publish crates;
publish = false remains intentional.
The CUA SDK revision is pinned in Cargo.toml and Cargo.lock. Native desktop
permissions and an interactive session are still required for real capture and
input on Windows, macOS, and Linux.
