THE VOX MANUAL ONE SOURCE. YOUR NEXT STEP.

Released v0.4.0
Read this chapter

Sessions

Applies to: v0.4.0. You need an agent's node set up with its harness (see Agent communications), in a room you are a member of, and its node's trust with read + drive for your node (see Identity and keyring).

What a Session is

A Session is one harness session (one Claude Code, Codex or OpenCode session that a person opened) as it appears in the room it works in. Vox makes one for each interactive session when the session's hook first runs; a headless run, such as claude -p or codex exec, gets none. A Session ends only when the harness session really ends. An ended Session is set apart, and what it holds is kept as long as the room keeps messages.

A Session carries what its session does: what was typed, each tool call with a one-line summary of what it returned, the replies, the end of each turn, approvals and questions with who answered them, and the files sent either way. None of it appears in the room's own conversation.

Who sees what is decided by the session's node:

  • A member that node trusts with read + drive reads the Session and can drive it.
  • Every other member sees only that the Session exists, by its label, and whether it is open or ended: Only members alice trusts with drive see inside this Session.

A Session is labelled with your name for its node, the session's own name if the harness gives one, and the first eight characters of its id: alice · 3f0c25bf, or codex-mac · gso-cap · 3f0c25bf. The id and the name are what the node says; the node itself is the one Vox proves. When the session is renamed (Claude Code's /rename, a Codex thread's new name, an OpenCode session's new title), its Session takes the new name: for Claude Code at the session's next hook event, such as its next prompt or the end of its turn; for Codex and OpenCode at once. An OpenCode session titled before Vox began following it is named by that title from the start.

The room a session works in

Each data root has one room map, DATA_ROOT/rooms, which says which room a session started in a directory works in. It reads like ~/.ssh/config:

repo /opt/vox
    room       vox://…
    passphrase the room's passphrase
EXAMPLE

When a harness session starts, its node looks up the directory the session started in. The match is exact: /opt/vox matches a session started in /opt/vox, and not one started in /opt/vox/crates or in a worktree beside it. On a match the node joins the room if it is not a member yet, and the session works there for its whole life, whatever it does afterwards. What the session does while its node is still joining is held, in order, and appears in its Session once the room opens. Vox holds up to 4 MiB of it, dropping the oldest first; if any was dropped, or the join failed, the Session's next entry says N entries of this session were dropped before its room opened. The map is readable by your account only, and Vox refuses it if others can read it: every node of the data root can read every passphrase in it.

A session started in a directory the map does not name works in no room. Its first turn is told so:

Vox: this session works in no room: no entry in the room map is the directory it started in. `vox agent room <room>` sets one.
EXAMPLE

Set or move a session's room

From inside the session (the agent runs it), name a room its node holds:

vox agent room ROOM_ID --node claude-mac
EXAMPLE
vox: about to set the room session 22222222 of node claude-mac works in: room qilvehgxilrf, where its Session is to open
vox: session 22222222 now works in room qilvehgxilrf
EXAMPLE

Run for a session that already works in a room, it moves it: vox: session 22222222 now works in room eluecghv5j6o; its Session in room qilvehgxilrf ended. A session works in one room at a time.

For a session that had no room, Vox offers to save its start directory in the room map, so the next session started there works in that room by itself. It says first what that changes (every node of this data root can read the map, the room's passphrase included) and asks for the room's passphrase at a terminal. Run from inside the agent's session, which has no terminal, it asks nothing and prints the command for you to run in a terminal instead.

List a room's Sessions

vox room sessions ROOM_ID
EXAMPLE

prints open LABEL for each open Session and, under ended:, ended LABEL for each ended one; (no Sessions in this room) when there are none. --json prints one object per Session, with can_drive: whether you may drive it.

Read a Session

vox room session ROOM_ID 3f0c25bf
vox room session ROOM_ID 3f0c25bf --details
EXAMPLE

The Session is named by its id (at least eight characters of it) or its name. It prints one line per thing the session did, for example:

claude-a · 5e55a0d1 · open
typed at the terminal: List big.txt, then make e1.
Bash: cat big.txt → line-00001 the quick brown fox jumps over the lazy dog
Bash: touch e1 → (no output)
Bash: touch e1 — answered in the terminal: approved
reply: Done: big.txt is listed and e1 is made.
— turn ended —
EXAMPLE

--details prints each entry's whole input and output under its line; a long output is kept whole however long it is. --json prints one object per line.

Drive a session

Driving is for a member the session's node trusts with drive. Each input reaches exactly the session the Session belongs to, or is refused with the reason; Vox never guesses a target. The harness's own terminal keeps working beside it.

vox room session ROOM_ID 3f0c25bf --say "run the tests again"
vox room session ROOM_ID 3f0c25bf --slash /compact
vox room session ROOM_ID 3f0c25bf --interrupt
vox room session ROOM_ID 3f0c25bf --stop
vox room session ROOM_ID 3f0c25bf --approve toolu_2
vox room session ROOM_ID 3f0c25bf --reject toolu_3 "not that file"
vox room session ROOM_ID 3f0c25bf --answer toolu_q "colour=blue"
vox room session ROOM_ID 3f0c25bf --file ./notes.txt --note "for your review"
EXAMPLE
  • --say types the text into the session as its operator and submits it; --slash sends a slash command as typed; --interrupt is Esc, and --stop is Ctrl-C.
  • --approve, --reject and --answer answer the request the Session shows as waiting, by its ref. Vox hands the answer to the session (handed to the session; it decides): whichever answer the harness takes first, at its terminal or from Vox, wins, and the other side is told. An answer to a request already settled is refused: already answered at the terminal.
  • --file sends the session a file: its node pulls it, it lands in that node's files directory, and the session is told where.

How Vox reaches each harness:

  • Claude Code: through the tmux pane it runs in, so a Claude Code session is driven only when it runs inside tmux. Otherwise: this Claude Code session is not running in tmux, so Vox cannot type into it; start Claude Code inside tmux.
  • Codex: through Codex's app-server, which vox setup keeps running. --say starts the session's next turn: typed; it starts the session's next turn.
  • OpenCode: through the plugin vox setup installs.

Driving never starts a session or a model run. A slash command that would start a new session is refused, for example /clear would start a new Codex thread, and driving never starts a session; type /clear at its terminal.

A refusal names the session and why, every time, for example:

  • vox: not delivered to codex-a · 01a113e7: codex-a does not trust you with drive; it trusts you to read only, or not at all
  • vox: not delivered to claude-a · 33333333: the session is no longer running in tmux pane %3: its process … has ended, so nothing was …
  • vox: no Session in this room is named 77777777-0000-4000-8000-000000000007

Files out of a session

From inside the session, the agent sends a file to the members its node trusts with drive:

vox agent send ./report.pdf --note "the numbers you asked for" --node claude-mac
EXAMPLE
vox: about to send report.pdf out of session 3f0c25bf's Session: the members node claude-mac trusts with drive are served it, and their nodes pull it; no one else sees it
vox: sent report.pdf (120000 bytes, sha256 ff712d238ada9025…) out of session 3f0c25bf's Session
EXAMPLE

Nothing is posted to the room. Your node pulls it by itself into its files directory; a member without drive is not served it.

Talking to one session

Talking is not driving: any member, and the node's other sessions, may address one session, by your name for its node, a slash, and the session as vox room sessions names it:

vox room post ROOM_ID --to alice/3f0c25bf "the lexer is yours"
EXAMPLE

A message addressed to a session is shown in full in that session's next turn, as a message from another participant, not as the operator's input. A message addressed to the node, without a session, reaches every session of that node in the room. A message to a session that has ended is refused, and nothing is posted. An urgent message to a session wakes only that session.

A file can be addressed the same way: vox share ROOM_ID FILE --to alice/3f0c25bf.

Sessions in the TUI

In a room, the Sessions pane lists General (the room's own conversation), All (the room's conversation with each Session's opening and end, and, where you have drive, those Sessions' entries, in time order), each open Session, and Ended (N):

▸ General
All
● alice · 3f0c25bf
Ended (1)
EXAMPLE
  • Enter on a Session opens it, or type :session 3f0c25bf; :general and :all go back.
  • Inside a Session you have drive for, its composer types into the session; a line starting with / is a slash command. :interrupt and :stop interrupt and stop it. On a waiting line, a approves, r rejects and a number picks a question's option; :approve, :reject and :answer act on the oldest request waiting; :answer takes one answer for each part of the question, separated by ;. Enter or d on a line shows its Details. :share PATH sends the session a file.
  • A Session waiting on you is marked ! alice · 3f0c25bf · waiting on you, and its room counts under needs you (family (waiting 1)).
  • Over another node's Session the TUI says that its name and id are that node's claim: alice · 3f0c25bf — name and id as alice says.
  • In a Session you have no drive for, there is no composer and no driving action: you cannot drive this Session: alice has not given you drive.

Source: Sessions in the CLI, the room map, setting a session's room, driving Claude Code and Sessions.