vmux
Appsvmux Daemon

Session Commands

List sessions, create sessions out of band, and dump full session state as JSON.

The session-level CLI is intentionally small. Most of what you do in tmux with tmux new-session, tmux list-sessions, and tmux switch-client happens here through three commands plus vmux attach.

CommandPurpose
vmux lsList active sessions, one per line, name<TAB>uuid<TAB>colsxrows.
vmux session create [-s NAME]Create a session without attaching. Returns the new session's UUID.
vmux state [-s NAME-OR-UUID]Dump a structured JSON snapshot of one session's tabs, panes, runtime states, and split tree.

There is no kill-session or rename-session subcommand. Sessions die when their last pane exits — see Killing a session below for the practical equivalent.

vmux ls

vmux [global-flags] ls

List all active (non-ended) sessions. Output is plain text, one session per line, three tab-separated fields, suitable for piping into awk, cut, or fzf:

NAME    UUID                                    SIZE
default 4F9C8A3B-1D2E-4F0A-9B8C-1D2E3F0A4B5C    80x24
work    7B6D5C4E-2F3A-4B1C-8D9E-0F1A2B3C4D5E    140x42

There are no flags for ls — the protocol always returns every active session for this client's daemon.

To get just session names:

vmux ls | cut -f1

To pick one with fzf:

vmux attach -s "$(vmux ls | fzf | cut -f1)"

Empty output

When no sessions exist yet, vmux ls exits 0 with no output. The daemon does not auto-create the default session until something actually attaches; ls is read-only.

vmux session create

vmux [global-flags] session create [-s NAME]

Create a new session without attaching. Useful when scripting: spin up the session, populate it with pane create and pane launch, then attach interactively at the end.

FlagDefaultEffect
-s NAME, --session NAME, --name NAMEserver's defaultSessionName (config) or defaultSession name. Must be unique across active sessions.

On success, the new session's UUID is written to stdout:

$ vmux session create -s ci-shells
B19B7C0E-4F5A-4B6C-9D0E-1F2A3B4C5D6E

Capture it for later commands:

SESSION=$(vmux session create -s ci-shells)
TAB=$(vmux state -s ci-shells | jq -r '.tabs[0].tabID')
PANE=$(vmux pane create --session "$SESSION" --tab "$TAB" --role shell)

The session is created with the daemon's configured initial size (default 80×24) and one tab containing one pane. Resize happens automatically on first vmux attach from a real terminal.

If a session with that name already exists, vmux session create fails with vmux: protocolError("…") on stderr and exit code 1.

vmux state

vmux [global-flags] state [-s NAME-OR-UUID]

Dump a full structured snapshot of one session. Output is JSON, pretty-printed and key-sorted, encoded with ISO-8601 dates. This is the same data the visionOS app uses to draw its scene; the CLI just hands it to you raw.

FlagDefaultEffect
-s NAME-OR-UUID, --session NAME-OR-UUIDthe daemon's default sessionEither the session name or its UUID string. The CLI parses the value as a UUID first; if it parses, the request is sent by ID — otherwise by name.

Example

vmux state -s work | jq '.tabs[0].panes[] | {id: .paneID, role, runtimeState, title}'
{
  "id": "8E7D6C5B-…",
  "role": "shell",
  "runtimeState": { "kind": "idleShell" },
  "title": "zsh"
}
{
  "id": "1A2B3C4D-…",
  "role": "teammate",
  "runtimeState": { "kind": "running" },
  "title": "claude code"
}

Schema highlights

  • sessionID, name, cols, rows — top-level session info.
  • tabs[] — each has tabID, title, activePaneID, rootPaneID, a splitTree describing the layout, and a panes[] array.
  • panes[].runtimeState — one of:
    • { "kind": "idleShell" }
    • { "kind": "starting" }
    • { "kind": "running" }
    • { "kind": "exited", "exitCode": 0 }
    • { "kind": "failed", "message": "…" }
  • panes[].roleshell, teammate, system, or unknown.
  • panes[].teammate — optional metadata when a pane was launched as an agent process: taskID, taskTitle, agentName, source, launchTimestamp.
  • splitTree is a recursive tagged union: each node is either { "kind":"pane", "id": UUID } or { "kind":"split", "axis":"horizontal"|"vertical", "ratio": Double, "first": …, "second": … }.

The exact shape is driven by the daemon's wire types, not by the CLI, so it is the source of truth for any external tool reading vmux state.

Killing a session

There is no vmux kill-session. To end a session, end every pane in it. The daemon ends the session automatically once the last pane exits.

The blunt way:

# enumerate every pane in a session and force-close each
vmux state -s work \
  | jq -r '.tabs[].panes[].paneID' \
  | xargs -n1 -I{} vmux pane close {} --force

The friendly way:

vmux attach -s work
# inside the session, type `exit` in each shell pane until everything is gone

If you want a session to be unkillable from inside (think a long-running build) and still be tear-down-able from outside, the --force flag on pane close will SIGKILL the underlying process group.

Renaming a session

Not supported by the CLI today. Names are fixed at session creation. The internal protocol carries a session UUID alongside the name, so most automation should reference sessions by UUID — captured from session create or state — rather than by name.

If you really need a different name, create a new session and migrate the panes' contents manually.

See also