pub enum Request {
Show 38 variants
ListSessions,
GetSession(SessionId),
GetWindow(WindowId),
GetPane(PaneId),
NewSession {
name: String,
shell: String,
source: Option<SessionSource>,
size_cells: Option<(u16, u16)>,
args: Vec<String>,
},
RenameSession {
id: SessionId,
new_name: String,
},
KillSession(SessionId),
NewWindow {
session: SessionId,
name: String,
shell: String,
args: Vec<String>,
},
KillWindow(WindowId),
SelectWindow(WindowId),
SplitPane {
origin: PaneId,
direction: Direction,
shell: String,
args: Vec<String>,
},
KillPane(PaneId),
SelectPane(PaneId),
ResizePane {
id: PaneId,
direction: Direction,
delta_cells: i16,
},
ApplyLayout {
window: WindowId,
kind: LayoutKind,
},
SendKeys {
id: PaneId,
bytes: Vec<u8>,
},
PaneSnapshot(PaneId),
Subscribe(PaneId),
PaneResizeAbsolute {
id: PaneId,
cols: u16,
rows: u16,
},
GetConfig,
ReloadConfig,
SetConfig(String),
SetSpawnEnv(SpawnEnv),
StartPaneRecording(PaneId),
StopPaneRecording(PaneId),
ExportPaneRecording(PaneId),
PaneRecordingStatus(PaneId),
PaneBlocksList {
pane: PaneId,
since_index: u64,
limit: u32,
},
PaneBlockAt {
pane: PaneId,
index: u64,
},
PaneBlocksStatus(PaneId),
PaneSubscriberCount(PaneId),
SetInputPolicy {
id: PaneId,
policy: InputPolicy,
},
SetFreio {
session: Option<SessionId>,
engaged: bool,
},
GetFreio,
SubscribeConfigChange,
Authenticate(String),
IdentifyClient(u64),
Hello {
client_version: String,
},
}Expand description
Every [MultiplexerControl] operation, encoded as a single
tagged enum so the daemon can match on the variant once and
dispatch.
Variants§
ListSessions
GetSession(SessionId)
GetWindow(WindowId)
GetPane(PaneId)
NewSession
Fields
source: Option<SessionSource>Optional provenance tag — defaults to None on pre-#6
wire bytes (serde’s default). When present, mado MCP /
CLI sets it to Some(Agent) / Some(Human) / Some(Named(...))
so tear list can group by source.
size_cells: Option<(u16, u16)>Optional initial pane size in cells. Defaults to None for backwards-compat (older clients omit this field; daemon falls back to 80×24). mado attaches at known geometry — passing Some((cols, rows)) here means the shell’s TIOCGWINSZ returns the right size on first query, no resize-flicker on attach.
args: Vec<String>Arguments passed to shell as argv[1..]. Defaults to
empty on pre-args wire bytes. Because there is no
protocol negotiation, a stale daemon decoding this
frame drops the key and spawns the bare program — the
failure is silent and looks like “my arguments were
ignored”, so restart the daemon after upgrading.
RenameSession
KillSession(SessionId)
NewWindow
Fields
KillWindow(WindowId)
SelectWindow(WindowId)
SplitPane
Fields
KillPane(PaneId)
SelectPane(PaneId)
ResizePane
ApplyLayout
SendKeys
PaneSnapshot(PaneId)
Subscribe(PaneId)
Promote this connection to a push-mode byte stream from the
named pane. The daemon responds with Response::Ok then a
continuous stream of Response::PaneBytes(...) frames as
the pane’s PTY produces output. The connection is consumed
— no further Requests are accepted on it. Use a fresh
connection for control-plane work.
PaneResizeAbsolute
Set the pane’s PTY to an absolute size. Fires SIGWINCH at the child shell. Used by GPU consumers (mado at Phase 3.1) when their window resizes.
GetConfig
Snapshot the daemon’s current TearConfig as YAML. Lets
mado (or any consumer) introspect the live config without
racing the notify-driven hot-reload + without parsing the
YAML file directly.
ReloadConfig
Force the daemon to re-read its config file from disk. The notify watcher normally picks file changes up within ms; this is the manual escape hatch for filesystems where inotify-equivalents are unreliable (some network mounts).
SetConfig(String)
Push a typed TearConfig (serialised as YAML) to the
daemon — replaces the daemon’s live config snapshot
in-place via the same LiveConfig::replace path the
notify watcher uses. Lets mado (or any client) impose a
config when it first attaches AND mutate the config
dynamically over the lifetime of a session (per the M5
destination — mado is the canonical author of the tear
config when it’s the front-end). Daemon-side config file
on disk is NOT touched; the next reload reverts.
SetSpawnEnv(SpawnEnv)
Push a typed SpawnEnv (the embedder’s
capability env + cwd override) to the daemon. The daemon applies
it to its InProcess so every SUBSEQUENT NewSession spawn’s
child PTY sees the embedder’s TERM/COLORTERM/TERMINFO/
TERM_PROGRAM (and a stamped PWD) AFTER the inherited +
fallback env — closing the gap where a daemon-spawned child only
saw the daemon’s own env, so a truecolor capability set never
projected. The embedded path already calls
InProcess::set_spawn_env directly; this is the daemon-transport
equivalent. Idempotent; the last push wins. Replies
Response::Ok.
StartPaneRecording(PaneId)
#4 — start daemon-native recording for pane. Subsequent
PTY chunks are captured into a per-pane ring buffer; the
buffer can later be exported as asciinema v2 .cast via
ExportPaneRecording.
StopPaneRecording(PaneId)
#4 — stop recording. The captured buffer is retained so a
follow-up ExportPaneRecording still works.
ExportPaneRecording(PaneId)
#4 — export the pane’s captured recording as asciinema
v2 .cast (JSON-lines string). Returns
Response::CastJson(string).
PaneRecordingStatus(PaneId)
#4 — (is_enabled, event_count) for the pane. Returns
Response::RecordingStatus { enabled, events }.
PaneBlocksList
Pane-as-block (warp-class UX): list captured OSC 133
blocks for a pane. since_index filters older blocks;
limit caps the response size.
PaneBlockAt
Pane-as-block: fetch one block by per-pane index.
PaneBlocksStatus(PaneId)
Pane-as-block: (total_completed, in_progress) summary
for the pane. Cheap; tear top polls this each refresh.
PaneSubscriberCount(PaneId)
Probe how many subscribers (byte-stream consumers) are
currently attached to a pane. Used by the migration
ergonomic — tear pane-info surfaces the count so an
operator knows whether they’re stepping into an
already-shared pane, and by the auto-detect path so a new
renderer can decide between “attach to existing” and
“start new session”.
SetInputPolicy
Set a pane’s input policy. InputPolicy::Locked rejects
every subsequent SendKeys for that pane with
WireError::Rejected; InputPolicy::Free re-opens it.
Useful for demo / observer sessions, agent-only panes
where human input would interleave, and the migration
handoff window.
SetFreio
Engage or release the operator’s brake — see crate::freio.
None for session means EVERY session: the one-gesture panic
ergonomics live here, in the verb, rather than in a daemon-global
flag that could drift out of sync with the per-session records it
is supposed to describe.
A bool, deliberately not a Freio. Freio::Engaged carries
at_unix, and a peer must not be able to supply it — the daemon
stamps the time. The same discipline that made SessionSource
derived rather than declared: if this variant carried a Freio,
a backdated brake would have a wire syntax.
GetFreio
Read the brake state of every session.
SubscribeConfigChange
Promote this connection to a config-change subscription.
The daemon responds with Response::Ok then emits one
Response::ConfigChanged(yaml) frame every time the live
config is replaced (by Request::SetConfig, by a
LiveConfig.reload(), or by the notify-driven watcher
catching a file change). Connection is consumed — no
further Requests are accepted on it. Lets every attached
renderer react to a theme/keybind change at the same
moment, broadcast-style: typed config hot-reload to every
connected client.
Authenticate(String)
#5 — authenticate this connection. Only used when the
daemon was started with auth_token_env set in its
TearConfig. Must be the first request on the connection;
every other request returns WireError::Rejected(...) until
authentication succeeds. Sending an Authenticate to a daemon
that does not require auth is silently accepted (forward-
compatible).
IdentifyClient(u64)
#2 — tag this connection with a 64-bit client identity. Used
by InputPolicy::Leader(id) to gate SendKeys: only the
connection whose IdentifyClient matches the pane’s leader id
may send keys; all other clients get WireError::Rejected.
Sending to a daemon with no Leader-policy pane is a silent
Ok. Idempotent — calling again overwrites the connection’s
identity. Default identity is None (anonymous).
Hello
Capability probe. Replies Response::Hello carrying the
daemon’s own version and every capability it implements.
This variant is the one the compatibility story hangs on,
so be precise about how an older peer sees it. A daemon
built before this variant existed cannot decode the frame —
serde reports unknown variant \Hello``. What happens next
depends on the daemon’s read loop:
- built before the
read_framefix: the loop returns the decode error and the connection closes. The client observes EOF and reads that as protocol 0. - built at or after it: the loop answers
Response::Err(Rejected("unknown request …"))and stays up. The client reads that as protocol 0 too.
Both land on the same verdict, so the client needs no version knowledge to interpret the outcome — which is the property that makes this probe safe to send blind.
Sent after Authenticate on an auth-required daemon,
because the auth gate rejects everything else first.