Sessions
A CMDOP session is a unit of the execution-state continuity layer: a single-homed, stored, resumable object that lives in the database rather than on a connection, so it survives client disconnects and re-attaches from any device. Two flavours exist — terminal sessions (one PTY, 30 s grace) and persistent sessions (many commands, 1 MiB output buffer, 30 min idle TTL). The relay routes by ID, not IP.
A CMDOP session is a stored, resumable object. It is not tied to a network connection — it lives in the database, survives client disconnects, and can be re-attached from any device. There are two flavours, and they are easy to confuse.
Sessions are objects, not connections
Where SSH binds a session lifetime to one TCP socket, CMDOP decouples them. The session is a database row plus runtime state on the agent; clients (Desktop, CLI, mobile, SDK) attach and detach over the relay. Multiple clients can attach to the same session concurrently — see Multi-Client.
Traditional SSH:
Connection ═══════ Session
└─ connection closes → session dies
CMDOP:
Connection ────┐
Connection ────┼──▶ Session (persistent object)
Connection ────┘
└─ connections come and go, session persistsTwo kinds of sessions
| Kind | Surface | Lifetime | Identity | Idle behaviour |
|---|---|---|---|---|
| Terminal session | cmdop connect, Desktop machines tab | One PTY, one client at a time as operator | Server UUID issued on open | 30 s grace on disconnect, then closes |
| Persistent session | connect_session agent tool, board task runners | Many commands within one channel | host-uuid:slotN (daemon-issued) or machine_<uuid>_<hex> (Desktop machine-scoped) | 30 min idle TTL by default; per-session override |
Same word, different objects. Use Remote Sessions for the persistent flavour.
Lifecycle states
The persistent session walks a small state machine:
Terminal sessions have a similar but simpler shape — see the grace-period section below.
Identity
Two ID formats appear in logs and APIs:
host-uuid:slotN— daemon-issued for persistent sessions (e.g.prod-1:slot3).machine_<uuid>_<hex>— minted by the Desktop frontend when a chat is scoped to a specific machine; the target machine ID it encodes is carried through to the session.
Both are addressable from any client; the relay routes by ID, not by IP.
The output buffer (persistent sessions only)
Persistent sessions buffer output in a per-session rolling window (default 1 MiB). The contract:
- New output is appended; once the window is full, the oldest bytes are dropped and the buffer is flagged as truncated.
- A reader asks for everything since a given offset and gets back the bytes, a cursor to resume from, and a truncated flag. A truncated answer signals that the requested offset fell outside the current window and some bytes were lost.
See Remote Sessions for the read pattern.
Idle behaviour and the reaper
The session manager runs a background reaper that closes sessions idle longer than the TTL (30 min by default). Per-session override via the idle-TTL setting at open time:
- Idle TTL of 0 — disables auto-close (use for builds, deploys, log tails).
- A small value — quick health probes that should free up slots fast.
If a session is idle 30+ minutes, the manager closes it. To keep a long task alive, set the idle TTL to 0 on open.
Grace period (terminal sessions)
When a terminal session’s client disconnects (laptop closes, network blip), the agent does not tear the PTY down immediately. The session enters a 30-second grace window:
- Process keeps running on the agent host.
- Output is buffered for replay.
- If the client (or any other fleet member) reconnects within 30 s, the stream resumes seamlessly.
- If 30 s elapses with no reconnect, the session closes.
This means flaky networks don’t kill long commands. A reconnect from a different device (phone, another laptop) attaches to the same session.
Where each kind is used
| Kind | Typical use |
|---|---|
| Terminal session | cmdop connect, Desktop machines tab interactive shell |
| Persistent session | connect_session agent tool; board task runners that must issue many commands |
Cross-link: Remote Sessions for the persistent-session surface; Multi-Client for the operator/observer model on terminal sessions.
Reconnecting from another device
# laptop, opens a session
cmdop connect prod-1
# (laptop closes, session continues)
# phone or another machine — list active sessions in fleet
cmdop session list
# inspect a session's metadata by ID
cmdop session attach <session-id>
# reattach interactively to the live terminal
cmdop connect prod-1Reconnect from any device — sessions are not bound to the originating client. Interactive reattach (a live terminal) is done with cmdop connect; cmdop session attach currently reports the session’s metadata and marks it attached, with interactive takeover planned but not yet implemented.
Opening a persistent session with idle TTL disabled
{
"tool": "connect_session",
"args": {
"hostname": "prod-1",
"operation": "open",
"idle_ttl_ms": 0
}
}An idle TTL of 0 disables the reaper for that session — the agent must close it explicitly.
Limits
- One operator per terminal session at a time (others attach as observers).
- 64 persistent sessions per daemon process (default).
- 1 MiB output buffer per persistent session.
- 30 s terminal grace, 30 min persistent-session idle TTL — both overridable.
Related
Background reading: The Session as a Computational Primitive — the category essay on why the session, not the connection, is the durable object.