IPC¶
shed-desktop exposes a control socket so the app can be driven and observed
programmatically — by shedctl, by the functional test harness, or by hand. This is a
first-class feature: it is how changes are verified without a human clicking.
Transport¶
- A Unix-domain socket at
~/Library/Caches/ShedDesktop/shed-desktop.sock(mode0600). - Newline-delimited JSON, one object per line, 16 MiB frame cap.
- Request:
{"id": "<int64-as-string>", "op": "...", "params": {...}} - Response:
{"id": "...", "ok": true, "result": {...}}or{"id": "...", "ok": false, "error": {"code": "...", "message": "..."}}
Request structs reject unknown fields. Errors use stable codes: unknown-op,
invalid-param, unknown-field, not-found, internal, not-enabled.
Core ops¶
| op | params | result |
|---|---|---|
identify |
— | socket_path, pid, app_label, app_id, ui_version, protocol_version, test_mode, mock_base_url? |
ui.state |
— | pane, hosts[], sheds[], host_agent_connected, last_error? |
ui.navigate |
pane (sheds|approvals|agents|activity|system) |
pane |
ui.set_ssh_approval |
method?, scope?, ttl? |
{} (applies SSH approval prefs + resets live SSH grants) |
ui.show_window |
— | {} |
ui.hide_window |
— | {} (closes the dashboard → menu-bar-only accessory) |
ui.window_state |
— | visible (bool), activation_policy (regular|accessory) |
ui.open_preferences |
— | {} |
ui.open_menu |
open (bool) |
open |
host.list |
— | hosts[] |
sheds.list |
host? |
sheds[] |
sheds.refresh |
— | {} (forces an immediate poll) |
system.df |
— | usage[] (per-host GET /api/system/df: totals + image/shed/orphan disk entries) |
app.window_metrics |
— | window_width, window_height, sidebar_width, visible_pane |
app.screenshot |
surface (window|menu), scale (1|2) |
png (base64), width, height, scale, surface |
The screenshot renders the target window's content view to a PNG in-process — no screen
capture permission, works even when the window is occluded or off-screen. Capturing the
menu requires it to be open first (ui.open_menu {open:true}).
Lifecycle, create + terminal¶
| op | params | result |
|---|---|---|
shed.start / shed.stop / shed.reset / shed.delete |
host?, name |
{} (refreshes first) |
create.start |
host?, name, repo?, local_dir?, image?, backend?, cpus?, memory_mb?, no_provision? |
create_id |
create.status |
create_id |
CreateProgress (poll until complete/error) |
terminal.preview |
host?, shed, session? |
the ssh TerminalCommand (spawns nothing) |
terminal.open |
host?, shed, session? |
launches the terminal (disabled in test mode) |
Remote control¶
| op | params | result |
|---|---|---|
rc.classify |
kind, pane |
state, url? (pure pane classifier) |
rc.list |
host?, shed? |
sessions[] |
rc.launch |
host?, shed, kind?, display_name?, workdir? |
the launched RcSession |
rc.kill |
host?, shed, slug |
{} |
rc.inject_test |
shed, slug, kind?, state?, managed?, display_name?, created_by?, … |
{} — test mode only; injects a session (e.g. a legacy row) into the table |
Each RcSession carries the RC Session Convention v1 metadata:
managed, and (when managed) rc_id, created_by, created_at, target_label.
A legacy/unmanaged rc-* session decodes with managed: false and no metadata.
Approval ops¶
These drive the credential-approval gate (see Credential approvals).
| op | params | result |
|---|---|---|
approvals.list |
— | approvals[] (each carries server?, namespace, op, shed, detail, expires_at, gate, default_scope, default_ttl) |
approval.decide |
id, decision (approve|deny), scope? (per-request|per-session|per-shed), ttl? (e.g. 1h), persist? |
{} |
activity.list |
limit? (default 200) |
entries[] (audit feed) |
activity.log_path |
— | path (the append-only audit log) |
policy.list |
— | rules[] (effective: default + per-namespace + per-shed) |
policy.set |
rules[] |
{} (test mode only) |
notifications.list |
— | notifications[] (test mode: what the gate posted) |
notification.invoke |
id, action (approve|deny) |
{} (test mode: drive a notification action) |
notification.open |
— | {} (test mode: drive a banner-body tap → opens the Approvals pane) |
approval.decide with persist:true saves a per-(server,shed) rule (always-allow
when decision:approve, always-deny when decision:deny). For an approve, scope
controls the grant: per-request (once), or per-session/per-shed add an in-memory
grant lasting ttl (e.g. 1h). scope/ttl/persist are reported to the host agent
so its durable audit records how the decision was made.
Test mode¶
When launched with SHED_DESKTOP_TEST_MODE=1, identify reports test_mode: true and the
mock_base_url the app's HTTP clients were redirected to, so the harness can confirm a run
is hermetic before asserting anything. Fault-injection ops (like policy.set) are gated
behind this flag.