Features
Sessions #
Heads up: The session list display is not yet perfect and will keep improving — what it can show is heavily dependent on the signals each agent CLI exposes.
Ctrl+N
: pick a repo, name it, choose an agent.
Run multiple coding-agent CLIs side-by-side, each in its own tmux pane. A session runs one agent (Claude Code, Codex, Gemini CLI, opencode, aider, Vibe, or your own), each with its own default config. Sessions persist across crashes, restarts, and even multiple concurrent Thurbox instances — tmux keeps them alive in the background.
-
Create a session with
Ctrl+N: repo picker → session name → agent picker. The agent picker is skipped when only one agent is defined. -
Restart a session with
Ctrl+Rto preserve conversation history when the agent supports resume (e.g. Claude's--resume). - Each session displays elapsed time ("Waiting 45s", "Idle 2m")
-
Open URLs in terminal output with
Ctrl+Click -
Select text with mouse drag, copy with
Ctrl+C, paste withCtrl+V. With no selection,Ctrl+Csends SIGINT to the active session. -
Toggle a shell pane alongside the agent session with
Ctrl+T -
Recover sessions externally at any time with
tmux -L thurbox attach
Agent Definitions #
The set of available agents is data, not code. On first run Thurbox seeds
~/.config/thurbox/agents.toml
with built-ins (claude, codex, gemini, opencode, aider, vibe). Edit the file to tweak an
agent or add a new one — no recompile required.
-
Each
[[agents]]entry has acommand,args(always passed — bake in flags like a model here if you want), and argument-template groups (resume_args,fork_args,new_session_args). -
A group is appended only when its driving value is present, with
{id}substituted. Selection precedence is fork > resume > new-session id. - A session is fully described by its repos and agent. There is no per-session model selection, permissions, prompt, tool, or skill configuration — those belong to the agent CLI itself, which runs with its own default config.
Automations #
Note: Automations are stable and good enough for daily use today, but the feature may still evolve.
Named, scheduled agent runs. An automation fires on a schedule and either
sends
a prompt to a running session or
spawns
a fresh session (optionally on a new git worktree) and prompts it. Press
Ctrl+P
for the full list, or use the always-present Automations pane beneath the session list.
-
Schedules are one-shot (a relative delay) or recurring cron, with friendly
hourly/daily/weekdays/weeklypresets and an optional timezone. The editor needs no cron knowledge: the trigger is a selector, the time is set with steppers, and a live preview shows the next fire. -
The Automations pane joins the
Ctrl+H/Ctrl+Lfocus cycle; once focused,Ctrl+Ncreates andj/k/Space/r/e/dselect / toggle / run / edit / delete. - Automations fire even when the TUI is closed — a detached tmux heartbeat keeper runs them every minute (and keeps the tmux server alive), with opt-in systemd/launchd units for reboot-proof firing. Concurrent firers are de-duplicated by an atomic claim, so nothing double-fires.
-
Everything is persisted in SQLite (
automations+automation_runshistory) and scriptable headlessly viathurbox-cli automation create/list/edit/run/runs/tick.
Tasks #
Heads up: Tasks are a new feature — expect the UX and UI to keep evolving in upcoming releases.
Ctrl+W
.
A built-in todo list whose items can be connected to a coding agent with the same Send/Spawn model as automations: Send pastes the task title into an existing session, Spawn creates a fresh session (optionally on a new worktree) seeded with the title, and an unconnected task is a plain local todo. Triggering a task runs its action and advances it to in progress .
-
Tasks render in a toggleable right-side column (
Ctrl+W/F5) that behaves like the file viewer and joins theCtrl+H/Ctrl+Lfocus cycle. Once focused,ncreates,e/Enteropens an in-pane editor (no popup),Spacecycles status (☐ todo · ◐ in progress · ☑ done),rruns the action, andddeletes. -
Persisted in SQLite and scriptable headlessly via
thurbox-cli task(aliastodo):create/list/show/edit/remove/run. External issue-tracker sync (Jira, GitHub Issues) is scaffolded for a later release.
Git Worktrees #
Optionally spawn sessions inside git worktrees for branch isolation.
-
When creating a session (
Ctrl+N), choose "Worktree" mode to select a base branch and name a new branch - Thurbox creates the worktree and launches the agent inside it
-
Press
Ctrl+Sto sync all worktree sessions withorigin/main - On rebase conflicts, Thurbox automatically sends a resolution prompt to the agent
- Closing a session automatically removes the worktree
- Worktree sessions show the branch name in the terminal title and session list
Worktree storage
Worktrees are created at
<repo>/.git/thurbox-worktrees/<sanitized-branch>
, where
/
in branch names is replaced by
-
.
Remote SSH Sessions #
Run an agent on a remote machine over SSH while the TUI stays local. The agent process, its tmux window, and any git worktrees all live on the remote host.
-
Declare hosts in
~/.config/thurbox/hosts.toml(seeded commented-out, so a fresh install has none); each entry registers a selectable backend namedssh:<name> -
The new-session flow (
Ctrl+N) shows a host picker first; remote sessions are marked with a☁glyph in the session list -
Thurbox shells out to your system
ssh, so authentication, keys, and connection multiplexing come from~/.ssh/config— thurbox never handles credentials - Remote sessions get the same persistence, multi-instance sharing, and restore-on-startup as local ones
- The remote host needs tmux ≥ 3.2 and git
# ~/.config/thurbox/hosts.toml
[[hosts]]
name = "devbox" # backend "ssh:devbox"; what --host expects
destination = "me@devbox" # ssh target or a ~/.ssh/config alias
ssh_opts = ["-o", "ControlMaster=auto", "-o", "ControlPersist=10m"]
# socket / session — optional remote tmux -L / session-name overrides
# worktrees_dir — optional absolute remote worktrees dir
Spawn remotely from the CLI with
thurbox-cli session create --host devbox …
.
Worktree Sync #
Ctrl+S
synchronizes all worktree sessions with their upstream default branch.
- Sessions are grouped by repository to avoid git lock contention. Different repos sync in parallel.
-
Per-worktree: stash uncommitted changes, fetch, rebase
origin/main, stash pop. -
Stale
.git/index.lockfiles from crashed git processes are automatically cleaned up before syncing. - Runs on background threads — the TUI remains fully responsive.
- Results shown per-session: synced, conflict (sent to Claude for resolution), or error.
Session Forking #
Press
Ctrl+F
to fork the active session. This creates a new session that resumes from the same
conversation history, allowing you to explore alternative approaches without losing the
original session's context.
Global Search #
Ctrl+A
, searching every scope at once.
Press
Ctrl+A
to open a non-modal search strip that searches
every scope at once
— sessions, tasks, automations, and the active session's file tree. It is the one
search: the old per-pane
/
filters were folded into it.
- Sessions match on name, agent, and worktree branch and on live terminal-buffer content; tasks match on title, automations on name, and files on path.
- Matches highlight live in the panels themselves — matching rows are accented, the rest dimmed — with per-scope match counts and a grouped result list.
-
↑/↓move the selection (previewing the owning panel),Enterjumps to the result and focuses its pane, andEscrestores exactly what you had before searching.
Responsive UI #
Three layout tiers adapt to your terminal width:
| Width | Layout |
|---|---|
| < 80 cols | Terminal only |
| >= 80 cols | Session sidebar + terminal |
| >= 120 cols | Sidebar + terminal + info panel |
-
Scrollback with
Shift+arrows/PageUp/PageDown/ mouse wheel - Non-modal error messages in the status bar
- Vim-inspired keybindings throughout
- Tri-state focus system (Focused, Active, Inactive) with visual border feedback
Ctrl+B
) — session details plus live CPU/RAM and agent metrics.
Ctrl+E
) — browse the worktree tree with fuzzy search.
Themes #
Eight built-in palettes (four dark, four light) switch live with
Ctrl+Y
and persist across restarts.
Ctrl+Y
).
Session Persistence #
Sessions run inside a dedicated tmux server (
tmux -L thurbox
) and survive crashes, restarts, and multiple concurrent instances.
How it works
- Sessions spawn as tmux windows. The tmux pane keeps running regardless of Thurbox's lifecycle.
-
On shutdown (
Ctrl+Q), session metadata is saved to SQLite. Thurbox detaches without killing sessions. - On restart, Thurbox discovers existing sessions from tmux, matches them to persisted metadata, and adopts them with terminal content intact.
-
External recovery is always possible via
tmux -L thurbox attach.
Close vs Quit
| Action | Behavior |
|---|---|
Ctrl+Q
(Quit)
|
Detaches all sessions, saves metadata. Sessions resume on next launch. |
Ctrl+D
(Close)
|
Permanently kills the tmux pane. Worktree (if any) is removed immediately. |
Headless CLI #
The
thurbox-cli
binary drives the same sessions, automations, and editor settings without the TUI
— ideal for scripting. It shares the TUI's SQLite database and
tmux -L thurbox
server, so changes made by either show up live in the other. Every command prints JSON;
pass the global
--pretty
flag for indented output.
$ thurbox-cli session list
$ thurbox-cli session create --name reviewer --repo-path /path/to/repo --agent codex
$ thurbox-cli session send <uuid> "run the test suite"
$ thurbox-cli session capture <uuid> --lines 500
-
session
—
list,get,create(synchronous — the tmux window is live on return; supports--worktree-branch/--base-branch),send,capture,restart,delete,restore. -
automation
(alias
auto) —create/list/show/edit/remove/run/runs, plustick(the headless entry point that fires all due automations — what the tmux heartbeat keeper and any systemd/cron timer call). -
editor
—
get/setthe commandCtrl+Oruns (the worktree path is appended as the final argument).
How session delete is handled
session delete <uuid>
is a
soft-delete
by default: it only marks the database row deleted. The tmux window, git worktrees, and
any pending scheduled commands are left untouched — the running TUI cleans those
up on its next sync, and the session stays recoverable with
session restore <uuid>
(the TUI's
Ctrl+U
/
Ctrl+Z
undo). Restore revives the metadata; the TUI re-spawns a fresh window for it.
Pass
--force
to tear down the session's runtime resources in the same call — for headless
cleanup when no TUI is running to observe the deletion. A forced delete also:
- kills the tmux window,
- removes the session's git worktrees (the underlying repos are left intact),
- removes the multi-repo symlink workspace, if any (only the symlinks — never the linked repos), and
- disables any send automations that target the session.
Teardown is
best-effort
: individual tmux/worktree failures are recorded in the JSON report (
killed_window
,
removed_worktrees
,
worktree_errors
,
disabled_automations
) but never abort the delete. The DB row is always soft-deleted last, so even a forced
delete stays restorable — it just re-spawns from a clean slate.