Spacesd client and processes

SpacesdClient: the cua-spacesd client, running processes in a sandbox, and sandboxes without cua-spacesd.

sandbox.spacesd(), space.spacesd() (or cua.spacesd(url, token) for any spacesd) returns a SpacesdClient. It picks native gRPC or gRPC-Web, sends the token and chunks transfers. Processes are below; files and the computer and media have their own pages.

Python programs usually use the high-level API instead: cua_sandbox interfaces.

cua-spacesd is optional: images without it still boot and serve their declared services, and sandbox.spacesd() raises SpacesdNotAvailable. capabilities() reports what this spacesd supports (has_feature(name) checks one feature). call_json(method, json) reaches every cua.env.v1 RPC of the protocol, including those without a typed method.

From a Space#

Methods of Space.

Space.spacesd#

The cua-spacesd client over the connection this Space authenticated.

def spacesd(self) -> SpacesdClient

Returns SpacesdClient · Raises CuaError

SpacesdClient#

Client for one cua-spacesd.

Returned by Cua.spacesd, Relay.connect, Sandbox.spacesd, Space.spacesd.

MethodDescription
call_jsonCalls any unary cua.env.v1 RPC with a proto3-JSON request and returns the proto3-JSON response.
call_json_streamCalls a server-streaming cua.env.v1 RPC and collects at most max_messages responses (or until the stream ends or timeout_ms elapses).
capabilitiesGetCapabilities (cached).
diagnoseRuns the image self-test (SystemService.Diagnose, the checks of cua-spacesd doctor) and returns the report as JSON (schema version 1, libs/cua/proto/diagnose-report.schema.json).
forward_tcpForwards a TCP port on this machine to guest port through cua-spacesd's tunnel: works for any Space this client reaches (on this machine, one of your machines or the cloud).
has_featureWhether the guest supports feature.
healthHealth as proto3 JSON.
httpSends one plain-HTTP request to the spacesd port with this client's endpoint and credentials (through a gateway when the endpoint is behind one).
open_downloadStreams path in chunks: one read that resumes where a dropped stream stopped and checks each segment's SHA-256, delivered through a small buffer (memory stays bounded whatever the file size).
routeWhich way calls go now, in one line: local <host:port> (a Space on this machine), direct <address>, relay <relay URL> (the relay's HTTPS path), mesh direct <ip:port> rtt <ms> ms (end to end over the mesh, straight to the machine: a LAN neighbour), mesh relayed or cloud.
agentsCoding agents in this guest.
attachAttaches to a running process by pid or tag.
clickLeft click.
cursor_positionPointer position.
displaysDisplays as proto3 JSON ([Display]).
double_clickDouble click.
downloadDownloads path into memory.
download_fileDownloads path to a local file.
dragDrags with the left button.
get_clipboardClipboard text.
hotkeyPresses a chord (["ctrl", "c"]).
keyboard_jsonFull ComputerService.Keyboard from proto3 JSON.
list_dirListDir (depth 1 = direct children), as user.
list_processesGuest processes as proto3 JSON ([ProcessInfo]).
make_dirMakeDir (with parents), as user: the new directories are owned by that user.
move_pathMove: renames source to destination, as user.
move_toMoves the pointer.
open_mediaOpens a media session and starts delivering encoded video frames and control events to frames.
open_media_with_audioSpacesdClient.open_media that also delivers audio packets to audio (set options.audio to negotiate audio tracks).
pointer_jsonFull ComputerService.Pointer from proto3 JSON.
pressPresses one key (enter, KEY_ESCAPE, a, ...).
removeRemove, as user.
right_clickRight click.
runRuns a command to completion.
screenshotCaptures a display.
scrollScrolls by line deltas.
set_clipboardSets clipboard text; returns the clipboard generation.
shRuns line with /bin/sh -c to completion.
spawnStarts a command and returns its handle.
statStat.
type_textTypes text.
uploadUploads bytes to path (chunked, resumable, SHA-256 verified).
upload_fileUploads a local file to path.
AccessorReturnsDescription
endpoint()StringEndpoint URL.
json_methods()Vec<String>Methods reachable through call_json / call_json_stream.
transport()Stringgrpc or grpc-web.

SpacesdClient.call_json#

Calls any unary cua.env.v1 RPC with a proto3-JSON request and returns the proto3-JSON response. method is the full path (/cua.env.v1.WindowsService/ListWindows) or Service/Method. Covers windows, accessibility, driver tools, teleport, tunnels and every other RPC without a typed method.

user makes a file request (FilesystemService Stat, ListDir, MakeDir, Move, Remove, CreateWatcher, CreateSignedUrl, BeginUpload) act as that guest user: it sets the request's run_as (in header for BeginUpload) and checks that the guest agent supports acting as another user. Any other method refuses it, and so does a request that already names a different run_as.

async def call_json(self, method: str, request_json: str, user: Optional[str] = None) -> str
ParameterTypeDefault
methodStringrequired
request_jsonStringrequired
userOption<String>None

Returns String · Async · Raises CuaError

SpacesdClient.call_json_stream#

Calls a server-streaming cua.env.v1 RPC and collects at most max_messages responses (or until the stream ends or timeout_ms elapses).

user acts as that guest user for WatchDir and ReadFile, as for call_json.

async def call_json_stream(self, method: str, request_json: str, max_messages: int, timeout_ms: int, user: Optional[str] = None) -> List[str]
ParameterTypeDefault
methodStringrequired
request_jsonStringrequired
max_messagesu32required
timeout_msu32required
userOption<String>None

Returns Vec<String> · Async · Raises CuaError

SpacesdClient.capabilities#

GetCapabilities (cached).

async def capabilities(self) -> SpacesdCapabilities

Returns SpacesdCapabilities · Async · Raises CuaError

SpacesdClient.diagnose#

Runs the image self-test (SystemService.Diagnose, the checks of cua-spacesd doctor) and returns the report as JSON (schema version 1, libs/cua/proto/diagnose-report.schema.json). options_json is a proto3-JSON DiagnoseOptions ("{}" for the defaults: every check, read-only). Falls back to DiagnoseOnce when the stream is cut.

async def diagnose(self, options_json: str) -> str
ParameterTypeDefault
options_jsonStringrequired

Returns String · Async · Raises CuaError

SpacesdClient.forward_tcp#

Forwards a TCP port on this machine to guest port through cua-spacesd's tunnel: works for any Space this client reaches (on this machine, one of your machines or the cloud). bind is the local address to listen on (default 127.0.0.1:0, a free loopback port; 0.0.0.0:0 serves the LAN).

async def forward_tcp(self, port: int, bind: Optional[str]) -> SpacesdForward
ParameterTypeDefault
portu16required
bindOption<String>required

Returns SpacesdForward · Async · Raises CuaError

SpacesdClient.has_feature#

Whether the guest supports feature.

async def has_feature(self, feature: str) -> bool
ParameterTypeDefault
featureStringrequired

Returns bool · Async · Raises CuaError

SpacesdClient.health#

Health as proto3 JSON.

async def health(self) -> str

Returns String · Async · Raises CuaError

SpacesdClient.http#

Sends one plain-HTTP request to the spacesd port with this client's endpoint and credentials (through a gateway when the endpoint is behind one). Used for streamable-HTTP MCP at /mcp, for example by typed cua-driver clients. Not retried.

async def http(self, request: SpacesdHttpRequest) -> SpacesdHttpResponse
ParameterTypeDefault
requestSpacesdHttpRequestrequired

Returns SpacesdHttpResponse · Async · Raises CuaError

SpacesdClient.open_download#

Streams path in chunks: one read that resumes where a dropped stream stopped and checks each segment's SHA-256, delivered through a small buffer (memory stays bounded whatever the file size). Read it with SpacesdDownload.next_chunk; dropping it, or cancel, stops the transfer.

async def open_download(self, path: str, chunk_size: Optional[int] = None, user: Optional[str] = None) -> SpacesdDownload
ParameterTypeDefault
pathStringrequired
chunk_sizeOption<u32>None
userOption<String>None

Returns SpacesdDownload · Async · Raises CuaError

SpacesdClient.route#

Which way calls go now, in one line: local <host:port> (a Space on this machine), direct <address>, relay <relay URL> (the relay's HTTPS path), mesh direct <ip:port> rtt <ms> ms (end to end over the mesh, straight to the machine: a LAN neighbour), mesh relayed or cloud. A Space one of your own machines provides prefers the direct path and falls back to the relay by itself (CUA_MESH=off turns that off). A client made otherwise reports where its spacesd runs (local, cloud, direct) and the endpoint it dials.

async def route(self) -> str

Returns String · Async · Raises CuaError

SpacesdCapabilities record#

SystemService.GetCapabilities, summarized. json has everything.

Returned by SpacesdClient.capabilities.

FieldTypeDefaultDescription
versionStringspacesd version.
protocol_version / protocolVersionu32cua.env.v1 protocol version.
protocol_revision / protocolRevisionu32Additive contract revision.
os_family / osFamilyStringOS family (linux, macos, windows).
os_name / osNameStringOS name.
os_version / osVersionStringOS version.
archStringCPU architecture.
hostnameStringGuest hostname.
initializedboolSystemService.Init has run.
featuresVec<SpacesdFeature>Feature flags.
jsonStringThe full response as proto3 JSON.

SpacesdFeature record#

One capability flag.

FieldTypeDefaultDescription
nameStringFeature name (for example a11y, stream.h264, audio.desktop).
supportedboolSupported in this guest.
limitationOption<String>Limitation when degraded or unsupported.
attributesHashMap<String, String>Extra attributes.

SpacesdHttpRequest record#

A plain-HTTP request to the spacesd port (for example MCP at /mcp).

FieldTypeDefaultDescription
methodStringMethod, for example POST.
pathStringAbsolute path under the endpoint, for example /mcp. Never a URL.
headersVec<SpacesdHttpHeader>[]Extra headers. Credentials (authorization and the env headers) are the client's and cannot be set here.
bodyVec<u8>Request body (empty for none).
timeout_ms / timeoutMsOption<u32>NoneWhole-request timeout; 30 s when unset.
max_response_bytes / maxResponseBytesOption<u64>NoneResponse body cap; 16 MiB when unset.

SpacesdHttpResponse record#

The spacesd's HTTP answer.

Returned by SpacesdClient.http.

FieldTypeDefaultDescription
statusu16Status code.
headersVec<SpacesdHttpHeader>Response headers, in order.
bodyVec<u8>Response body.

SpacesdHttpHeader record#

One HTTP header (duplicates are kept in order).

FieldTypeDefaultDescription
nameStringHeader name.
valueStringHeader value.

SpacesdDownload#

A download in progress (SpacesdClient.open_download).

Returned by SpacesdClient.open_download.

MethodDescription
next_chunkThe next chunk, or None once the whole file arrived.
AccessorReturnsDescription
cancel()Stops the transfer.

SpacesdDownload.next_chunk#

The next chunk, or None once the whole file arrived.

async def next_chunk(self) -> Optional[bytes]

Returns Option<Vec<u8>> · Async · Raises CuaError

SpacesdForward#

A loopback (or bind) TCP port that reaches a guest port through cua-spacesd's tunnel (SpacesdClient.forward_tcp). Stopped by stop or when dropped.

Returned by SpacesdClient.forward_tcp.

MethodDescription
stopStops listening and revokes the driver-side forward (also done when it is dropped).
AccessorReturnsDescription
guest_port()u16Guest port.
local_addr()Stringhost:port accepting connections.

SpacesdForward.stop#

Stops listening and revokes the driver-side forward (also done when it is dropped).

async def stop(self) -> None

Async · Raises CuaError

Without cua-spacesd#

Any OCI image is a full Space on the container and microVM kinds: when the image carries no cua-spacesd (alpine:3.20, node:20), Cua puts a static one into it and runs it beside the image's own command, so exec, files and ports work. Pass spacesd=False to run the image as it is. The sandboxes without cua-spacesd are those: the macOS 15 image (macOS 26 runs cua-spacesd) and a VM of an image that ships no Cua disk (use kind container or microvm, or cua build FROM a Cua image), so sandbox.spacesd() fails for them. A local Lume sandbox is still reachable: commands over lume ssh, screenshots and the display over the VM's VNC endpoint. cua sb exec, cua sb screenshot and cua sb view use the same calls. Other sandboxes fail with Unsupported.

Python programs usually use the high-level API instead: cua_sandbox shell and screen.

Agentless methods#

Methods of Sandbox.

Sandbox.lacks_spacesd#

Whether this sandbox has no cua-spacesd: it declares no env service, or its image says it does not carry one. spacesd() fails for these; guest_sh, guest_screenshot and guest_display reach a local Lume sandbox without it.

def lacks_spacesd(self) -> bool

Returns bool

Sandbox.guest_sh#

Runs line with /bin/sh -c in the guest without cua-spacesd, to completion (default timeout 120 s). Local macOS Lume sandboxes only: over lume ssh, stdout and stderr kept apart, no stdin. Others fail with Unsupported.

async def guest_sh(self, line: str, timeout_ms: Optional[int] = None) -> ProcessOutput
ParameterTypeDefault
lineStringrequired
timeout_msOption<u32>None

Returns ProcessOutput · Async · Raises CuaError (Unsupported)

Sandbox.guest_screenshot#

Captures the guest framebuffer as PNG without cua-spacesd. Local Lume sandboxes only: over the VM's VNC endpoint.

async def guest_screenshot(self) -> Screenshot

Returns Screenshot · Async · Raises CuaError

Sandbox.guest_display#

The guest display without cua-spacesd: the VM's VNC endpoint and a host command that opens it (lume attach). Local Lume sandboxes only.

async def guest_display(self) -> GuestDisplay

Returns GuestDisplay · Async · Raises CuaError

GuestDisplay#

The guest display of a sandbox without cua-spacesd (Sandbox.guest_display). An object, not a record, so no binding's default string form (repr, str, description, toString, Debug) can show the VNC password: url() is masked, and only the explicit url_with_password() returns it.

Returned by Sandbox.guest_display.

AccessorReturnsDescription
open_command()Vec<String>A host command that opens a viewer on it (lume attach <vm>); empty when there is none. It handles the password itself.
url()StringThe display URL (vnc://HOST:PORT) with any password masked as ****. Safe to print and log.
url_with_password()StringSENSITIVE: the display URL with the VNC password (vnc://:PASSWORD@HOST:PORT), for handing to a VNC client. Never print or log it.
via()StringHow the display is reached (vnc).