Skip to content

Sessions and persistence ​

A session is a row in Sessions mode. The rows from every host you are connected to appear in one list, grouped by host; the machine in front of you is just another host.

Hosts, sessions, REPLs ​

  • A host is a machine running the backend daemon, sotd.

  • A session is one project directory on one host. The backend calls it a workspace, and the words mean the same thing: one session is one row in Sessions mode and one entry in the session strip along the bottom edge. Shift+Arrow moves between sessions.

  • Each session has its own agent pane (Claude Code, Codex or a plain shell), its own Julia REPL, and its own kernel, the Julia process that serves Modules mode and file previews. The REPL and kernel start the first time something needs them, in the project's Project.toml environment, running the julia that SOT_JULIA_BIN names, else juliaup's default channel, else a julia on PATH.

Two sessions never share a Julia Main: each REPL is its own process. Inside one session, you (from the REPL drawer), the session's agent and any helper agents it starts all run code in that session's one REPL. It runs one evaluation at a time and does not queue: a request that arrives while another is running comes back as busy and nothing runs. The julia-repl skill tells agents to use separate julia processes for parallel runs.

Capsules: what a session survives ​

Each session's agent runs in a capsule: a small supervisor process (sot-capsule) that owns the agent's terminal and keeps its latest screen on disk, so a restarted capsule shows the old screen above a restart line. The frontend attaches to the capsule to draw the pane; the daemon starts capsules and lists them, but does not hold them up.

What goes awayWhat happens to the session
the network, or the laptop lidnothing — the frontend reconnects on its own when the network is back; F5 retries at once
the last window on this computer (closed, crashed or killed)it ends, with the backend; the next window starts with none. Ctrl+Q asks first and can keep them running
one of two windows on this computernothing — sessions end with the last window
a window relaunch (update)nothing, if the new window opens within a minute
a window on another computernothing — the next window reattaches
the daemon (restart, upgrade)the capsule keeps running and the restarted daemon re-adopts it

When a session's agent restarts, or a session is reopened after it ended, the agent starts a fresh conversation, which first reads the session's handoff file (dev/output/handoff-<handle>.md in the project, when it has one). An earlier conversation comes back only when asked: /resume inside Claude Code, ccb --continue / ccx --continue from a terminal, or a reauth (/reauth), which continues the same conversation on the new account.

On Linux each capsule supervisor runs in its own transient systemd --user scope, outside the daemon's unit, which is what lets it survive a daemon restart. On a host with no reachable user systemd manager it runs in a degraded mode that shares the daemon's lifetime, and the daemon log says why.

Where the state lives ​

The daemon's state root is ${XDG_STATE_HOME:-~/.local/state}/sot: the capsule folders and the daemon's own sotd.log. It must be a local, durable filesystem — the daemon refuses to start a capsule on a network or volatile filesystem rather than risk the screen file and the capsule's lock. On Linux, the installer checks this root. When it fails qualification, a managed daemon unit with no nonempty XDG_STATE_HOME gets /scratch/<user>/sot-state/sot when that local folder is usable. The installer writes a systemd drop-in pointing there and restarts the daemon. Each computer sharing the home uses its own local disk. An explicit export or a personal drop-in is kept; an unqualified root ends ONE STEP LEFT, with the folder and the reason in the final checklist. The unit sources ~/.bashrc, whose export wins over the drop-in. Other Unix installs check the root and name the export to fix when it fails (see Troubleshooting).

Closing a session from the session list ends its capsule and removes its folder under workspaces/, with the saved screen. The conversation itself lives with the agent, so it stays resumable with /resume in the same project folder. The default row only ends its run and keeps its folder, and a session ended by closing the window keeps its folder for now. When the daemon starts, it removes the leftovers of closed sessions, and a folder that no registry names, if nothing runs in it and nothing in it was written for 24 hours; it skips that second part when it cannot read every registry that start. Each removal is one line in sotd.log.

Switching and restarts ​

Switching the active session is a frontend state change: it never restarts a REPL or kernel, so each session's Julia state is where you left it, and two sessions can run different versions of the same package side by side.

The kernels and REPLs are children of the daemon, so a daemon restart restarts them. The agents survive it; Julia state does not.

Reconnecting ​

Every connect sends the client's session id and the last revision it saw; the daemon replays the missed events from a bounded ring, or sends a fresh snapshot if the client is too far behind. That is why a reconnect puts you back exactly where you were. Protocol details are in Design: backend and sessions.

An agentic development environment for Julia. Released under the AGPL-3.0-or-later, with a commercial license on request.