Sessions & Daemon Mode
Persistent terminal sessions with detach and reattach
TUIOS supports persistent sessions through a daemon process, similar to tmux or screen. Sessions continue running in the background even when you disconnect, allowing you to reattach later with all windows and terminal content preserved.
Platform Support: Daemon mode is available on Linux, macOS, and Windows (Windows 10 build 17063+ with Unix socket support).
Quick Start
# Create a new session
tuios new mysession
# Work in TUIOS, then detach
# Press Ctrl+B d
# Later, list sessions
tuios ls
# Reattach to continue
tuios attach mysessionCreating Sessions
Use tuios new to create a new persistent session:
# Auto-generated session name
tuios new
# Named session
tuios new work
# With options
tuios new dev --theme dracula --show-keysHeadless Sessions
--detach (short -d) creates a session without attaching to it. The session gets an initial window and is immediately usable by send-keys, run-command, capture-pane, and the control protocol. This is the entry point for scripting and for driving TUIOS from a program.
tuios new build --detach
tuios send-keys -s build --literal --raw "make all"
tuios send-keys -s build EnterA detached session is created at a fixed 80x24. It resizes when a client attaches, but until then anything you capture is 80 columns wide regardless of your terminal.
The root appearance flags (--theme, --show-keys, --border-style, and the rest) are ignored by --detach. They are read when a client attaches, and a headless session has no client. Passing them is not an error, so they fail silently.
Session Naming
- Session names can contain letters, numbers, hyphens, and underscores
- If no name is provided, a unique name is auto-generated
- Session names must be unique
Listing Sessions
View all sessions with tuios ls:
tuios lsOutput:
╭───────────────┬─────────┬──────────┬───────────────┬─────────────────╮ │ NAME │ WINDOWS │ STATUS │ CREATED │ LAST ACTIVE │ ├───────────────┼─────────┼──────────┼───────────────┼─────────────────┤ │ work │ 3 │ detached │ 2 hours ago │ 5 mins ago │ │ dev │ 2 │ attached │ 1 day ago │ just now │ ╰───────────────┴─────────┴──────────┴───────────────┴─────────────────╯
Attaching to Sessions
Reattach to a session with tuios attach:
# Attach to specific session
tuios attach work
# Attach to the most recently active session
tuios attach
# Attach and create if session doesn't exist
tuios attach work -cAttaching to a session you detached from resumes it exactly where you left off: the same windows, positions, and terminal content, because the PTYs never stopped running.
This is different from what survives a daemon restart. See Session Resurrection for what comes back after the daemon exits, and what does not.
Detaching from Sessions
Detach from a session without closing it:
| Method | Key |
|---|---|
| Prefix command | Ctrl+B d |
| From window mode | d (detach) |
After detaching, the session continues running in the background.
Session Switcher (In-App)
In addition to the CLI commands above, TUIOS v0.7.0 includes an in-app Session Switcher that lets you browse and switch between sessions without leaving the TUI.
Opening the Session Switcher
- Press Ctrl+B then S from any mode
How It Works
The session switcher displays a list of all daemon sessions with their name, window count, and status. You can:
- Arrow keys or j/k to navigate the list
- Type to filter the list by name
- Enter to attach to the selected session (detaches from the current one). If your query matches no existing session, Enter creates a session with that name instead.
- Ctrl+D to kill the selected session, confirmed with y or cancelled with n
- Esc to close the switcher without changing sessions
This is especially useful when you have multiple projects running as separate sessions and want to hop between them quickly, without dropping to the shell to run tuios attach.
The session switcher works alongside the CLI commands. Use Ctrl+B S for quick in-app switching, and tuios ls / tuios attach for scripting and external access.
Managing Sessions
Kill a Session
Remove a specific session:
tuios kill-session workThis permanently closes all windows in the session. Any unsaved work will be lost.
Stop the Daemon
Stop the TUIOS daemon and all sessions:
tuios kill-serverHow It Works
- Daemon Process: When you create your first session, TUIOS starts a background daemon that manages all sessions
- Socket Communication: TUI clients communicate with the daemon over a Unix socket
- PTY Persistence: Terminal PTYs are owned by the daemon, not the client, so they survive disconnection
- State Sync: Window positions, workspace layout, and terminal content sync continuously
Session Resurrection
Detaching and reattaching preserves everything, because the daemon keeps running and the PTYs never stop. Resurrection is the weaker guarantee that applies when the daemon itself exits: a reboot, a crash, or tuios kill-server.
The daemon writes each session's structure to disk every 30 seconds, and again synchronously when it shuts down cleanly. On its next cold start it restores those sessions automatically, before it accepts any connections.
What comes back
Window structure, and only window structure:
- Window geometry, titles, and custom names
- Workspace assignment, minimize state, and which window had focus
- The BSP tree for each workspace, the layout mode, tiling scheme, and master ratio
- The working directory each window was in
- Session options
What does not come back
Resurrection restores the shape of your session, not its contents. It is crash recovery, not a snapshot.
- Processes are gone. Every window gets a fresh
$SHELL. A build, avim, or an SSH connection that was running is not restarted, and TUIOS does not try to re-run it. - Screen contents and scrollback are gone. They live only in daemon memory and are never written to disk. Each restored window starts with an empty emulator.
- Up to 30 seconds of structural change can be lost if the daemon is killed rather than shut down. A window created 5 seconds before a
SIGKILLwill not be there. - Restored shells inherit the daemon's environment, not the environment of the terminal you attach from. If your
$SHELLor your exported variables changed since the daemon started, the restored windows do not see it. - Working directory capture is Linux only. It reads
/proc/<pid>/cwd. On macOS and Windows, restored windows open in the shell's default directory instead.
A restored window announces itself so you are not misled into thinking your work survived. It prints a dimmed -- tuios: session restored, fresh shell in <cwd> -- banner, dropping the in <cwd> part when the working directory could not be captured, and sets TUIOS_RESTORED=1 in the environment so your shell profile can react to it.
Controlling resurrection
# Restore saved sessions on demand
tuios resurrect
# Start a daemon without restoring anything
tuios daemon --no-restoreState lives in $XDG_STATE_HOME/tuios/sessions/<name>.json, written with owner-only permissions.
Killing a session with tuios kill-session deletes its state file, so a killed session is deliberately not resurrectable. This is the difference between killing a session and losing a daemon.
Multi-Client Support
Multiple clients can connect to the same session simultaneously. All clients see synchronized state in real-time.
How It Works
When you attach multiple terminals to the same session:
- All clients share the same windows and workspaces
- Actions from one client are reflected on all others
- The effective terminal size is the minimum of all connected clients
Notifications
TUIOS displays notifications for multi-client events:
| Event | Notification |
|---|---|
| Client joins | "Client joined (N connected)" |
| Client leaves | "Client left (N connected)" |
| Window created | "Window created (N total)" |
| Window closed | "Window closed (N remaining)" |
| Workspace switch | "Switched to workspace N" |
Example: Pair Programming
# Terminal 1: Create session
tuios new pairing
# Terminal 2: Attach to same session
tuios attach pairing
# Both terminals now show the same TUIOS instance
# Actions in either terminal are reflected in bothMulti-client mode uses thread-safe channels to prevent race conditions when synchronizing state between clients.
Session Lifecycle
Daemon Location
The daemon socket is located at:
- Linux:
$XDG_RUNTIME_DIR/tuios/tuios.sockor/tmp/tuios-$UID/tuios.sock - macOS:
/tmp/tuios-$UID/tuios.sock - Windows:
%LOCALAPPDATA%\tuios\tuios.sock
Remote Control
One of the most powerful features of daemon sessions is the ability to control them from external scripts and tools. TUIOS provides CLI commands to send keystrokes, execute commands, and query state.
Send Keystrokes
Send input to a running session:
# Enter terminal mode
tuios send-keys i
# Send key combo
tuios send-keys "ctrl+b q"
# Send to specific session
tuios send-keys -s mysession Escape
# Send literal text to terminal (use --raw to prevent space splitting)
tuios send-keys --literal --raw "echo hello"Run Commands
Execute TUIOS commands remotely:
# Create a new window
tuios run-command NewWindow "my-terminal"
# Get JSON output with window ID
tuios run-command --json NewWindow "dev"
# Switch workspace
tuios run-command SwitchWorkspace 2
# Toggle tiling
tuios run-command ToggleTiling
# Target specific session
tuios run-command -s mysession NewWindow "dev"Query State
Inspect session state for scripting:
# List all windows
tuios list-windows --json
# Get focused window info
tuios get-window --json
# Get session state
tuios session-info --json
# Capture a pane's contents
tuios capture-pane -w mywindow --scrollbackrun-command --json flattens its result data to the top level of the JSON object, so a window ID is at .window_id, not .data.window_id. Window objects from list-windows use window_id as their identifier field; there is no .id.
Beyond the CLI
The CLI commands above are convenient for shell scripts, but they open a connection per invocation and report failures as exit codes. For anything more involved, the daemon speaks a JSON control protocol on the same socket: structured errors, blocking waits with wait-for instead of poll loops, and a subscribable event stream.
# Discover the whole protocol without reading the docs
tuios list-verbsExample: Development Layout Script
#!/bin/bash
# Create a development environment
# Create windows and capture IDs
EDITOR=$(tuios run-command --json NewWindow "editor" | jq -r '.window_id')
TERM=$(tuios run-command --json NewWindow "terminal" | jq -r '.window_id')
LOGS=$(tuios run-command --json NewWindow "logs" | jq -r '.window_id')
# Enable tiling
tuios run-command ToggleTiling
# Start applications
tuios send-keys --literal --raw "nvim ." && tuios send-keys Enter
tuios run-command FocusWindow "$TERM"
tuios run-command FocusWindow "$LOGS"
tuios send-keys --literal --raw "tail -f app.log" && tuios send-keys EnterExample: Window Selector with fzf
#!/bin/bash
WINDOW=$(tuios list-windows --json | \
jq -r '.windows[] | "\(.display_name)\t\(.window_id)"' | \
fzf --with-nth=1 | cut -f2)
[ -n "$WINDOW" ] && tuios run-command FocusWindow "$WINDOW"For the complete list of remote control commands, see the CLI Reference.
Best Practices
Naming Conventions
Use descriptive session names:
tuios new project-frontend
tuios new project-backend
tuios new personalWorkspace Organization
Combine sessions with workspaces:
- Use sessions for different projects or contexts
- Use workspaces within a session for related tasks
Clean Up
Regularly remove unused sessions:
tuios ls # Review sessions
tuios kill-session old-projectTroubleshooting
"Daemon not running"
If you see this error, the daemon may have crashed. Clean up the stale socket and start again:
tuios kill-server # Clean up any stale socket
tuios new mysession # Start a new daemonThis does not give you a clean slate. kill-server saves every session on the way out, and the next daemon restores them all on start. If you want a daemon with no sessions, start it explicitly:
tuios kill-server
tuios daemon --no-restore"Session not found"
The session may have been killed or the name is incorrect:
tuios ls # Check available sessions
tuios attach <name> # Use exact nameStale Sessions
If a session becomes unresponsive:
tuios kill-session stuck-session
tuios new fresh-session