Configuration
Every knob Thurbox reads, where it lives, and how it behaves. One file per audience/lifecycle: hand-edited registries are TOML, the machine-written keybindings are JSON, and concurrently-written runtime state lives in SQLite.
Dev builds
(version
0.0.0-dev
) use
thurbox-dev
in place of
thurbox
in every path below, plus a
thurbox-dev
tmux socket, so a development checkout never touches your real setup. All paths
respect
$XDG_CONFIG_HOME
/
$XDG_DATA_HOME
.
Files at a glance #
| File | Format | Edited by | Read | Purpose |
|---|---|---|---|---|
~/.config/thurbox/agents.toml |
TOML | you | live (mtime poll) | coding-agent CLI definitions |
~/.config/thurbox/hosts.toml |
TOML | you | startup | remote SSH hosts |
~/.config/thurbox/settings.toml |
TOML | you / Settings panel | live (mtime poll) | tuning knobs + feature flags |
~/.config/thurbox/themes.toml |
TOML | you | startup | custom theme palettes |
~/.config/thurbox/keybindings.json |
JSON | F1 editor (or you) | live (mtime poll) | key chord overrides |
~/.config/thurbox/extensions/<name>.toml |
TOML | extension install |
startup + tick | extension manifests (self-healed resources) |
~/.local/share/thurbox/thurbox.db |
SQLite | thurbox | live | sessions, automations, tasks, theme, editor command |
~/.local/share/thurbox/thurbox.log |
text | thurbox | — | logs (incl. config warnings) |
agents.toml
,
keybindings.json
, and
settings.toml
reload
live
: the TUI polls their mtime (~1/s) and applies edits with a confirmation toast —
no restart. For
settings.toml
the UI-panel feature flags apply immediately; the
[notifications]
knobs, the
automations/mouse/notifications/version_check/auto_update
feature flags, and the write-once scalars take effect on the next launch and the toast says so.
hosts.toml
and
themes.toml
need a restart.
Config problems are not silent : parse errors, unknown fields, invalid chords, and chord conflicts surface as a status-bar toast on startup (and in the log file). Unknown TOML keys are tolerated and reported by name, while syntax/type errors fall back to built-ins (agents), zero hosts, or defaults (settings). Check everything from the command line:
thurbox-cli config validate # strict parse of every file; exit 1 on problems
thurbox-cli config show # effective config + where each value came fromWhich file do I edit?
A task-to-file map so you don't have to scan every section to find the right knob. None of these files need to exist on a fresh install — every one is seeded (commented-out where applicable) on first run, and absent files fall back to built-in defaults.
| I want to… | Edit |
|---|---|
| Add a coding agent, pin a model, change resume/fork flags | agents.toml |
| Run sessions on a remote machine over SSH | hosts.toml |
| Turn a whole TUI feature on/off (tasks, mouse, notifications…) | settings.toml [features] |
| Tune scrollback, panel breakpoints, audit retention | settings.toml |
| Change when/how OS notifications fire | settings.toml [notifications] |
| Add or recolour a TUI theme | themes.toml |
| Rebind a key | keybindings.json (or the F1 editor) |
Set the Ctrl+O editor, pick a theme |
runtime — SQLite |
agents.toml #
Declares the launchable coding agents. Seeded with the built-ins (
claude
,
codex
,
antigravity
,
opencode
,
aider
,
copilot
,
vibe
,
pi
,
omp
) on first run; edit or add
[[agents]]
entries to support any CLI — no recompile. A malformed file falls back to the
built-ins and shows the error.
config_version = 1
default = "claude" # agent preselected in the picker / headless spawns
[[agents]]
name = "claude" # display + lookup name (unique)
command = "claude" # executable
args = [] # always passed; bake a model here if you want one
resume_args = ["--resume", "{id}"] # emitted when resuming
fork_args = ["--resume", "{id}", "--fork-session"]
new_session_args = ["--session-id", "{id}"] # emitted on a fresh spawn
resume_latest = false # true = id-less "resume last session in cwd"
{id}
is substituted with the thurbox-generated session UUID. Groups are emitted only when
their driving value exists; precedence is fork > resume > new-session.
For each built-in's recommended configuration and runtime behavior — resume/fork semantics, whether it pins a session id, and how it reports status — see Built-in agents.
hosts.toml #
Declares remote SSH hosts; each
[[hosts]]
entry registers a session backend named
ssh:<name>
. Seeded fully commented-out (fresh installs are local-only). A malformed file means
zero remote hosts and shows the error.
| Field | Required | Default | Purpose |
|---|---|---|---|
name |
yes | — | backend id ssh:<name>; what --host expects |
destination |
yes | — | ssh target (user@host or ~/.ssh/config alias) |
ssh_opts |
no | [] |
extra ssh flags, one token per element |
socket |
no | thurbox |
remote tmux -L socket |
session |
no | thurbox |
remote tmux session name |
worktrees_dir |
no | remote $HOME/.local/share/thurbox/worktrees |
absolute remote worktrees dir |
Auth comes entirely from your
~/.ssh/config
; thurbox never handles credentials. Host changes require a restart.
settings.toml #
Scalar tuning knobs plus the
[features]
switches, seeded fully commented-out (defaults apply when absent). Only knobs a user
plausibly wants are exposed; internals stay hardcoded. The file is
live-reloaded
via mtime poll: the UI-panel feature flags apply immediately, while the
[notifications]
knobs, the
automations/mouse/notifications/version_check/auto_update
feature flags, and the write-once scalars take effect on the next launch.
Settings panel.
You don't have to hand-edit the file: the TUI has a
Settings modal
opened with
Ctrl+,
(or
F6
) that views and edits all of
settings.toml
— the
[features]
toggles,
[notifications]
knobs, and scalars. It edits a working copy and applies
only on
Ctrl+S
(Esc discards); the panel writes back through the same file, preserving
its documentation comments.
| Key | Default | Purpose |
|---|---|---|
scrollback_lines |
1000 |
terminal scrollback kept per session |
two_panel_min_cols |
80 |
width below which only the terminal renders |
three_panel_min_cols |
120 |
width unlocking the optional third column |
audit_retention_days |
90 |
audit-log history kept (pruned on startup) |
A complete settings.toml showing every knob at its default — copy
this and uncomment what you want to change (the UI-panel feature flags apply live; the
[notifications] knobs, the
automations/mouse/notifications/version_check/auto_update
flags, and the write-once scalars take effect on the next launch):
config_version = 1
# Scalar tuning knobs (top level)
scrollback_lines = 1000 # terminal scrollback kept per session
two_panel_min_cols = 80 # width below which only the terminal renders
three_panel_min_cols = 120 # width unlocking the optional third column
audit_retention_days = 90 # audit-log history kept (pruned on startup)
[features]
tasks = true
automations = true
file_viewer = true
global_search = true
info_panel = true
shell_pane = true
code_review = true # native diff-review pane (F7)
mouse = true
notifications = true
soft_delete = true # Ctrl+D soft-deletes (Ctrl+Z undo); false = hard-delete
version_check = false # opt-in: makes a network call
auto_update = false # opt-in: downloads + replaces binaries
[notifications]
backend = "auto" # auto / dbus / windows / off
also_on_waiting = false # also fire on Busy → Waiting (no bell)
suppress_for_active = true # skip the session you're currently viewing
sound = true # play the OS default notification sound
min_interval_secs = 5 # per-session floor between notifications[features] — whole-feature switches
Turn major TUI features off entirely. All default to
true
except version_check and auto_update, which default to false
(both reach the network, so they are opt-in). The UI-panel feature flags
(tasks, file_viewer, info_panel,
global_search, shell_pane, code_review,
soft_delete) are live-reloaded — they take effect
immediately, no restart. The rest (automations, mouse,
notifications, version_check, auto_update) and the
write-once scalars wait for the next launch. A disabled feature's pane never renders, its keybinding shows a status
toast instead of acting, and its global-search scope returns no results. Data is never
touched, so re-enabling a flag is lossless.
| Key | Default | Controls |
|---|---|---|
tasks |
true |
tasks panel (F5/Ctrl+W) and task search results |
automations |
true |
automations pane, Ctrl+P, TUI schedule firing, heartbeat arming |
file_viewer |
true |
file viewer column (F3) and file search results |
global_search |
true |
global search strip (Ctrl+/) |
info_panel |
true |
info panel column (F2) |
shell_pane |
true |
per-session shell toggle (Ctrl+T) |
code_review |
true |
native code-review view (diff + comments, Ctrl+X) |
mouse |
true |
mouse capture: clicks, wheel, drag-select, hover, scrollbars |
notifications |
true |
OS desktop notifications when a session needs attention |
soft_delete |
true |
TUI Ctrl+D soft-deletes (with a Ctrl+Z undo window);
false makes it a hard delete behind a confirmation modal. Never affects
thurbox-cli session delete (soft unless --force).
|
version_check |
false |
GitHub update check: TUI header “update available” badge +
thurbox-cli version --check
|
auto_update |
false |
silent self-update: download + verify + replace the binaries on startup +
thurbox-cli update
|
automations = false
is the one flag with teeth beyond the UI: it also stops the TUI from firing due
schedules and arming the tmux heartbeat at startup (explicit
thurbox-cli automation
commands still work).
mouse = false
skips terminal mouse capture entirely, so the terminal keeps its native mouse behavior.
notifications = false
keeps the background dispatcher thread from ever starting (zero overhead) and silently
no-ops every transition; the session status display itself is unaffected.
version_check = true
enables the update check. On launch the TUI reads a cached result
(~/.local/share/thurbox/version-check.json) and, if it is older than 24 h,
fires a single best-effort background fetch of GitHub's latest release (via
curl/wget); a newer release shows a
↑ vX.Y.Z available
badge next to the version in the header. The fetch never blocks startup and failures are
silent. Dev builds (0.0.0-dev) never show the badge. The same flag enables
thurbox-cli version --check
(thurbox-cli version with no flag always prints the current version).
auto_update = true
goes a step further than version_check: instead of just showing a badge, the
TUI silently updates itself on startup. After the same 24 h cache
check, if a newer release exists it downloads that release's tarball + checksums from
GitHub Releases (curl/wget), verifies the SHA256
(sha256sum/shasum), extracts it (tar), and
atomically replaces the installed thurbox/thurbox-cli binaries
in place — mirroring scripts/install.sh. The download is verified
before any installed file is touched, so a failed download leaves the
current binaries untouched; the step runs before the TUI takes the terminal and is
best-effort. The replaced binary takes effect on the next launch, so the
TUI shows an “Updated to vX.Y.Z — restart to apply” status line.
thurbox-cli update
performs the same update on demand (--force bypasses the up-to-date and
dev-build guards); dev builds (0.0.0-dev) never auto-update.
version_check and auto_update are independent — enable
either or both.
[notifications] — OS notification settings
Surfaces an OS notification when a session crosses into a state that needs the user's
attention (the agent rang the terminal bell or emitted an OSC 9 / OSC 777
message — usually because it's waiting on an answer or has finished a task). Linux
dispatches via dbus and supports
click-to-focus: clicking the banner writes a focus request that the
running TUI reads on its next tick and switches to that session. macOS shows the banner
but ignores clicks (the modern UNUserNotificationCenter API requires a
signed app bundle, which thurbox is not). The notification body is the agent's last OSC
message when present, otherwise Waiting for input.
Only fires while the TUI is open
— the agent terminal parser is what sees the bell, and it doesn't run when thurbox
isn't. Gated by the notifications feature flag above.
| Key | Default | Purpose |
|---|---|---|
backend |
auto |
delivery backend (auto / dbus / windows /
off): auto picks dbus on a Linux desktop, the WSL
Windows-toast fallback, or the macOS native banner; off drops every
notification (a soft switch distinct from the feature flag)
|
also_on_waiting |
false |
also fire on Busy → Waiting (no explicit bell from the agent) |
suppress_for_active |
true |
skip the notification for the session you're currently viewing |
sound |
true |
play the OS default notification sound |
min_interval_secs |
5 |
per-session floor between two notifications (dedup) |
The default-on Attention trigger is the right knob for any agent that
respects the terminal bell / OSC 9 / OSC 777 conventions (Claude Code out of
the box, for example). For agents that only go quiet without ringing a bell, set
also_on_waiting = true — note this fires once each time the agent goes
idle after activity, so it can be chatty.
themes.toml #
User-defined themes, offered in the
Ctrl+Y
picker alongside the nine built-in presets and persisted by
name
like any preset. Each
[[themes]]
entry starts from a built-in
base
and overrides only the colours it names:
[[themes]]
name = "my-mocha" # stable id; must not shadow a built-in
display_name = "My Mocha" # picker label (default: name)
base = "catppuccin-mocha" # starting palette (default: default)
accent = "#fab387"
app_bg = "reset" # keep the terminal's native background
Colours accept anything ratatui parses:
#rrggbb
, ANSI names (
red
,
lightcyan
), indexed (
14
), or
reset
. Bad colours and built-in name collisions degrade to startup warnings.
keybindings.json #
Maps Action names to one or more chord strings:
{ "QuitApp": ["ctrl+a"], "OpenThemePicker": ["ctrl+y", "f4"] }- The preferred editing path is the F1 panel (live capture, conflict stealing, immediate persistence). Hand-edits are read at startup and live via mtime poll.
-
Chord syntax:
[ctrl+][alt+][shift+][cmd+]<key>where<key>is a letter,f1–f12, or a named key (enter,esc,tab, arrows,home,end,pageup,pagedown,backspace,delete,insert). Case-insensitive.cmd(aliasessuper,command,win) is the macOS Command key, delivered only by kitty-keyboard-protocol terminals. - Unknown action names, invalid chords, and the same chord bound to two actions in overlapping contexts are reported at startup (the file still loads; bad entries fall back to defaults).
See the Keybindings page for the full default chord table.
Extensions #
Each opt-in extension is described by a single
extension.toml
manifest.
thurbox-cli extension install
writes the home-resolved copy to
~/.config/thurbox/extensions/<name>.toml
(thurbox never seeds this dir). The manifest has an
install
spec and a
runtime
spec; see the
Extensions
page for the full manifest format, lifecycle commands, and versioning.
thurbox-cli extension install flow # fetch + lay files + agents + activate
thurbox-cli extension list # installed + active/healthy + version/stale
thurbox-cli extension update --all # re-fetch every installed extension
thurbox-cli extension activate <name> # (re)create resources + mark active
thurbox-cli extension deactivate <name> # tear down + stop self-heal
thurbox-cli extension status [<name>] # per-resource presence + version/staleSQLite-backed settings #
Live in the
metadata
table and apply immediately (no restart):
| Key | Set via | Purpose |
|---|---|---|
active_theme |
Ctrl+Y / F4 picker |
TUI palette (nine built-ins) |
editor_command |
thurbox-cli editor set "<cmd>" |
what Ctrl+O runs |
active_extensions |
extension activate/deactivate |
JSON array of active extensions to self-heal |
These are in the DB rather than a file because they are written concurrently by
multiple thurbox processes (TUI, CLI, MCP) and picked up live via
PRAGMA data_version
polling.
Environment variables #
| Variable | Used for |
|---|---|
XDG_CONFIG_HOME, XDG_DATA_HOME |
config/data roots |
VISUAL, then EDITOR |
Ctrl+O editor when editor_command is unset |
SHELL |
the Ctrl+T companion shell pane (fallback /bin/sh) |
RUST_LOG |
log filter for thurbox.log |
Editor resolution order: DB
editor_command
→
$VISUAL
→
$EDITOR
→ error toast.
Versioning #
The SQLite schema migrates automatically (
schema_version
in
metadata
). The TOML files carry a
config_version = 1
marker so a future format change can migrate them too; current files are version 1 and
the field is optional.