Skip to Content
ConceptsSessions

Sessions

TL;DR

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 sessionmgr sessions (many commands, 1 MiB ring 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 persists

Two kinds of sessions

KindSurfaceLifetimeIdentityIdle behaviour
Terminal sessioncmdop connect, Desktop machines tabOne PTY, one client at a time as operatorServer UUID issued on open30 s grace on disconnect, then closes
Persistent (sessionmgr)connect_session agent tool, board task runnersMany commands within one channelhost-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:

Source of truth: internal/connect/sessionmgr/types.go:18–78.

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 sessionmgr sessions (e.g. prod-1:slot3).
  • machine_<uuid>_<hex> — minted by the Desktop frontend when a chat is machine-scoped, then decoded by the chat service (TargetMachineID flows through chat.Optional). See report 05 §2.8 and the per-machine chat path.

Both are addressable from any client; the relay routes by ID, not by IP.

The ring buffer (sessionmgr only)

Persistent sessions buffer output in a per-session ring (default 1 MiB). The contract:

  • Write(b) — appends, drops oldest on overflow, sets truncated=true.
  • Since(offset) → (data, nextCursor, truncated) — returns bytes since offset. A truncated=true answer signals that the requested offset fell outside the current window and bytes were lost.

Source: internal/connect/sessionmgr/ringbuf.go:14–84. See Remote Sessions for the read pattern.

Idle behaviour and the reaper

The sessionmgr runs a reaper goroutine that closes sessions idle longer than the TTL (30 min by default). Per-session override via IdleTTL on Open:

  • IdleTTL=0 — disable auto-close (use for builds, deploys, log tails).
  • 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 IdleTTL=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:

  1. Process keeps running on the agent host.
  2. Output is buffered for replay.
  3. If the client (or any other fleet member) reconnects within 30 s, the stream resumes seamlessly.
  4. 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

KindTypical use
Terminal sessioncmdop connect, Desktop machines tab interactive shell
Persistent (sessionmgr)connect_session agent tool; board task runners that must issue many commands

Cross-link: Remote Sessions for the sessionmgr 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-1

Reconnect 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.

sessionmgr open with IdleTTL=0

{ "tool": "connect_session", "args": { "hostname": "prod-1", "operation": "open", "idle_ttl_ms": 0 } }

IdleTTL=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 sessionmgr sessions per daemon process (default).
  • 1 MiB ring buffer per persistent session.
  • 30 s terminal grace, 30 min sessionmgr idle TTL — both overridable.

Background reading: The Session as a Computational Primitive — the category essay on why the session, not the connection, is the durable object.

TAGS: sessions, sessionmgr, ring-buffer, idle-ttl, grace-period DEPENDS_ON: [agents, remote-sessions, multi-client]

Last updated on