Kubi Docs
Kubi API

Run shell commands. Short ones answer inline, long ones return an id to poll.


Run a command

POST
https://api.trykubi.com/v1
/screens/{screen_id}/exec
Bearer (API key)

Needs the exec permission. Answers within 28 s.

Starts a command on the screen. If it ends within wait_s (default 25) the reply is 200 with exit code and output (max_bytes and tail shape it). Otherwise 202 with the exec id: poll getExec. timeout_s: 0 runs with no limit (dev servers, bots). The command keeps running if the connection drops; resend with the same Idempotency-Key and you get the same exec, never a second run.

Run a command › path Parameters

screen_id
​string · maxLength: 24 · pattern: ^scr_[0-9a-z]{20}$ · required

Screen id (scr_...).

Run a command › Headers

Idempotency-Key
​string · minLength: 8 · maxLength: 255 · pattern: ^[ -~]+$

Any unique string, ideally a UUIDv7; the SDK and MCP always send one. A retry with the same key and body gets the stored answer instead of running twice (kept 24 h for screens and power, 10 minutes for actions and commands). Stored once execution began: 2xx, 500 and 504. Never stored when outcome is not_applied (400, 401, 403, 404, 409, 415, 422, 429), so the same key can be retried after a conflict or a rate limit. Replays of runActions keep per-action results and shot metadata only, capture a fresh screenshot and carry Idempotent-Replayed: true. Same key, different body: 422 IDEMPOTENCY_KEY_REUSED. Same key still running: 409 IDEMPOTENCY_KEY_IN_USE.

Kubi-Run
​string · maxLength: 100 · pattern: ^[ -~]{1,100}$

Optional label that groups calls into one run in the screen's history. It is only a label and never locks the screen. The SDK fills it from KUBI_RUN, else Claude Code's CLAUDE_CODE_SESSION_ID, else one id per client it creates.

Run a command › Request Body

command
​string · maxLength: 10000

Shell command, run with bash -lc as the desktop user. Send this or argv.

argv
​string[] · minItems: 1 · maxItems: 200

Program and arguments, no shell. Send this or command.

cwd
​string · maxLength: 1024
Default: /home/user
​object · maxProps: 50
stdin
​string · maxLength: 65536

Written to stdin, then closed.

timeout_s
​integer · int32 · min: 0 · max: 86400

0: no limit (dev servers, bots). At the limit we send TERM, then KILL after 10 s; status timed_out. Runs on after the call returns.

Default: 3600
wait_s
​integer · int32 · min: 0 · max: 25

Answer inline if done within this; else 202 and an id to poll.

Default: 25
max_bytes
​integer · int32 · min: 1 · max: 1048576

Bytes of output per stream in this reply.

Default: 65536
tail
​boolean

true: the last max_bytes after the offset (errors and exit lines). false: the first.

Default: false

Run a command › Responses

Finished within wait_s.

id
​string · maxLength: 23 · pattern: ^ex_[0-9a-z]{20}$ · required
screen_id
​string · maxLength: 24 · pattern: ^scr_[0-9a-z]{20}$ · required
​required

lost: the screen restarted mid-run; the exit status is unknown. Never rerun blindly.

started_at
​string · date-time · maxLength: 40 · required
stdout
​string · maxLength: 1048576 · required

Output from stdout_from, up to max_bytes (head or tail). UTF-8, invalid bytes replaced.

stderr
​string · maxLength: 1048576 · required
stdout_bytes
​integer · int64 · min: 0 · max: 1099511627776 · required

Total bytes written so far. Use as the next stdout_from.

stderr_bytes
​integer · int64 · min: 0 · max: 1099511627776 · required
incarnation
​integer · int32 · min: 0 · max: 2147483647 · required
​
​
​
​
output_dropped
​boolean

Older output fell out of the 1 MiB per-stream buffer.


Get a command's status and output

GET
https://api.trykubi.com/v1
/screens/{screen_id}/exec/{exec_id}
Bearer (API key)

Needs the exec permission. Answers within 28 s.

Status, exit code and output from byte offsets. With wait_s, until=exit (default) holds the reply until the command ends; until=output answers as soon as it prints (for live log views). Output keeps the last 1 MiB per stream for 24 h after exit.

Get a command's status and output › path Parameters

screen_id
​string · maxLength: 24 · pattern: ^scr_[0-9a-z]{20}$ · required

Screen id (scr_...).

exec_id
​string · maxLength: 23 · pattern: ^ex_[0-9a-z]{20}$ · required

Exec id (ex_...) from startExec.

Get a command's status and output › query Parameters

wait_s
​integer · int32 · min: 0 · max: 25

Long poll: hold the reply up to this many seconds until something changes. 0 answers at once. Capped at 25 so every call ends within 30 s.

Default: 0
until
​string · enum · maxLength: 6

What ends a long poll: exit (default) or output.

Enum values:
exit
output
Default: exit
stdout_from
​integer · int64 · min: 0 · max: 1099511627776

Byte offset in stdout to read from (the last reply's stdout_bytes).

Default: 0
stderr_from
​integer · int64 · min: 0 · max: 1099511627776

Byte offset in stderr to read from (the last reply's stderr_bytes).

Default: 0
max_bytes
​integer · int32 · min: 1 · max: 1048576

Bytes of output per stream in this reply.

Default: 65536
tail
​boolean

true: the last max_bytes after the offset. false: the first.

Default: false

Get a command's status and output › Headers

Kubi-Run
​string · maxLength: 100 · pattern: ^[ -~]{1,100}$

Optional label that groups calls into one run in the screen's history. It is only a label and never locks the screen. The SDK fills it from KUBI_RUN, else Claude Code's CLAUDE_CODE_SESSION_ID, else one id per client it creates.

Get a command's status and output › Responses

Success.

id
​string · maxLength: 23 · pattern: ^ex_[0-9a-z]{20}$ · required
screen_id
​string · maxLength: 24 · pattern: ^scr_[0-9a-z]{20}$ · required
​required

lost: the screen restarted mid-run; the exit status is unknown. Never rerun blindly.

started_at
​string · date-time · maxLength: 40 · required
stdout
​string · maxLength: 1048576 · required

Output from stdout_from, up to max_bytes (head or tail). UTF-8, invalid bytes replaced.

stderr
​string · maxLength: 1048576 · required
stdout_bytes
​integer · int64 · min: 0 · max: 1099511627776 · required

Total bytes written so far. Use as the next stdout_from.

stderr_bytes
​integer · int64 · min: 0 · max: 1099511627776 · required
incarnation
​integer · int32 · min: 0 · max: 2147483647 · required
​
​
​
​
output_dropped
​boolean

Older output fell out of the 1 MiB per-stream buffer.


Stop a command

POST
https://api.trykubi.com/v1
/screens/{screen_id}/exec/{exec_id}/kill
Bearer (API key)

Needs the exec permission. Answers within 12 s.

Sends a signal to the command's process group. TERM then KILL after 10 s.

Stop a command › path Parameters

screen_id
​string · maxLength: 24 · pattern: ^scr_[0-9a-z]{20}$ · required

Screen id (scr_...).

exec_id
​string · maxLength: 23 · pattern: ^ex_[0-9a-z]{20}$ · required

Exec id (ex_...) from startExec.

Stop a command › Headers

Idempotency-Key
​string · minLength: 8 · maxLength: 255 · pattern: ^[ -~]+$

Any unique string, ideally a UUIDv7; the SDK and MCP always send one. A retry with the same key and body gets the stored answer instead of running twice (kept 24 h for screens and power, 10 minutes for actions and commands). Stored once execution began: 2xx, 500 and 504. Never stored when outcome is not_applied (400, 401, 403, 404, 409, 415, 422, 429), so the same key can be retried after a conflict or a rate limit. Replays of runActions keep per-action results and shot metadata only, capture a fresh screenshot and carry Idempotent-Replayed: true. Same key, different body: 422 IDEMPOTENCY_KEY_REUSED. Same key still running: 409 IDEMPOTENCY_KEY_IN_USE.

Kubi-Run
​string · maxLength: 100 · pattern: ^[ -~]{1,100}$

Optional label that groups calls into one run in the screen's history. It is only a label and never locks the screen. The SDK fills it from KUBI_RUN, else Claude Code's CLAUDE_CODE_SESSION_ID, else one id per client it creates.

Stop a command › Request Body optional

signal
​string · enum · maxLength: 4
Enum values:
TERM
INT
KILL
Default: TERM

Stop a command › Responses

Success.

id
​string · maxLength: 23 · pattern: ^ex_[0-9a-z]{20}$ · required
screen_id
​string · maxLength: 24 · pattern: ^scr_[0-9a-z]{20}$ · required
​required

lost: the screen restarted mid-run; the exit status is unknown. Never rerun blindly.

started_at
​string · date-time · maxLength: 40 · required
stdout
​string · maxLength: 1048576 · required

Output from stdout_from, up to max_bytes (head or tail). UTF-8, invalid bytes replaced.

stderr
​string · maxLength: 1048576 · required
stdout_bytes
​integer · int64 · min: 0 · max: 1099511627776 · required

Total bytes written so far. Use as the next stdout_from.

stderr_bytes
​integer · int64 · min: 0 · max: 1099511627776 · required
incarnation
​integer · int32 · min: 0 · max: 2147483647 · required
​
​
​
​
output_dropped
​boolean

Older output fell out of the 1 MiB per-stream buffer.