Configuration
Configuration
Preferences are stored in ~/.config/ccmux/ccmux.json and can be managed with:
ccmux config set <key> <value>ccmux config get <key>ccmux config list| Key | Values | Default | Description |
|---|---|---|---|
iconStyle |
dot, emoji, nerdfont, none |
dot |
Status icon style |
theme |
catppuccin-*, tokyo-night*, dracula, gruvbox-*, nord, rose-pine* |
catppuccin-mocha |
TUI color theme (resolved at launch; see Theme) |
showPreview |
true, false |
false |
Show preview panel on launch |
previewWidth |
20–80 |
40 |
Preview panel width (percentage) |
command |
any non-blank string | claude |
CLI command used for session restart |
groupBy |
project, cwd, session, window, none |
project |
How sessions are grouped in the TUI |
promptDisplay |
inline, row2, off |
inline |
Prompt display: inline on row 1, its own row, or hidden |
backgroundAgents |
true, false |
true |
Show Claude background agents as rows (daemon restart required) |
additionalClaudeConfigDirs |
array of paths | [] |
Additional Claude config dirs to watch (daemon restart required; see Multiple Claude Config Dirs) |
searchPaneContent |
true, false |
true |
Include captured pane content in TUI search |
searchPaneLines |
10–500 |
100 |
Lines of pane content scanned in TUI search |
searchTranscript |
true, false |
true |
Search live Claude/Codex transcripts (full history + assistant text) via the daemon |
persistent |
true, false |
false |
Keep picker open after switching sessions (dashboard mode) |
reviewHandback |
confirm, auto, fill |
confirm |
After a hunk review, confirm delivery, send immediately, or fill the agent composer without submitting |
tmuxSocket |
socket path (/...) or label |
unset | tmux server to track (daemon restart required; see Non-default tmux Server) |
sidebar.width |
10–80 |
30 |
Sidebar pane width in columns |
sidebar.position |
left, right |
left |
Which side of the window to place the sidebar |
For how these search knobs interact, see Search Mode.
Column Configuration
Each session item has up to two rows (row1, row2), and each row has a left and right side. Each side is a comma-separated list of field entries. An entry is either <field> (use the field’s default mode) or <field>:<mode> (override the mode).
ccmux config set columns.row1.left "index,status:icon,project"ccmux config set columns.row1.right "agent:short,pane,time"ccmux config set columns.row2.left "summary"ccmux config set columns.row2.right "branch"Pass an empty string to clear a side: ccmux config set columns.row2.left "".
| Field | Modes | Default mode | Description |
|---|---|---|---|
index |
— | — | Row number (1–9) |
status |
icon/short/full |
icon |
Status badge style |
project |
dirname/full |
dirname |
Project path (basename or full); a worktree renders as <repo>/<worktree> in both modes |
agent |
short/full |
full |
Agent name (2-char code or full label) |
version |
— | — | Agent version |
pane |
— | — | Tmux pane target (session:window.pane) |
time |
— | — | Relative time since last input |
prompt |
— | — | Last user prompt (truncated) |
cwd |
— | — | Working directory |
branch |
— | — | Git branch, suffixed + in a worktree |
pr |
short/full |
full |
Open PRs for the branch (#25/PR #25) |
summary |
— | — | The agent’s own summary of the session, falling back to the last prompt (truncated) |
summary is the default subtitle cell, and shows what the agent says it is doing. Claude Code, Copilot, Cursor, OpenCode and oh-my-pi each keep a generated summary in their tmux pane title; the column reads that through a per-agent rule that drops the status glyph, the spinner frame and the app name, so what lands on the row is the summary alone. Every other agent writes its cwd, its own state or a static app name there, and for those the cell falls back to the last prompt. A pane title equal to the machine’s own hostname is never shown either: that is the seed tmux gives a pane whose agent never set a title. Never both on one line.
prompt is unchanged and still shows the raw last prompt. To keep it as the subtitle, name it in the column config:
ccmux config set columns.row2.left promptccmux config set sidebar.columns.row2.left promptBoth cells flex to fill their row, so they share one budget — put at most one of them on a row.
The project cell reads path:branch, and a session running in a git worktree marks it twice: the branch gains a trailing + (also on the standalone branch column), and the path is replaced by <repo>/<worktree> — ccmux/parking rather than the worktrees/parking the directory happens to spell, so worktrees of different repos stay distinguishable. Both survive the dirname mode, since they are identity rather than path context; when the cell is too narrow for both, the repo yields before the worktree’s own name does.
Wrapped prompt block
promptLines renders the last prompt as a wrapped block of up to N lines, below the row’s other lines — the same text the one-line prompt column shows, given room to actually be read.
ccmux config set promptLines 3 # picker and sidebarccmux config set sidebar.promptLines 4 # sidebar only0 (the default) disables it; the cap is 10. Turning it on removes the prompt cell from both rows rather than printing the same text twice, and promptDisplay: "off" (the p key) still hides it. The summary cell yields the same way, but per session: a row whose agent wrote a real summary keeps it on the identity line with the block below, which is the one way to see both at once, while a row whose cell would fall back to the prompt drops it. While a search is active the block yields to the one-line prompt cell, so the match highlights and the [pane]/[transcript]/[cwd] source tag stay visible (plus [summary], which appears only when a summary-only match has nowhere to show itself, the prompt opt-out layout); a rail too narrow for a readable wrap keeps the cell for the same reason. A session with no prompt gets no extra lines. The preview pane already shows the selected row’s full last prompt, so the block earns its keep mostly in the sidebar. The block is wrapped and measured before layout, so a row’s reported height and its drawn lines are always the same number — the scroll and row-menu geometry stay exact at any height.
Defaults: row1.left is index, status, project (status badge widens icon→short→full as the terminal grows). row1.right cascades by breakpoint: just pane below xs, then agent:short, pane at xs, agent:short, pane, time at sm, and agent:full, version, pane, time at md+. The summary and pr cells are configured on row2, but promptDisplay (default inline, cycled live by p) controls how they render: inline flattens them onto row1 so each session stays a single line, row2 gives the subtitle its own line with pr at the right edge, and off hides both. Sessions with no prompt stay single-line in inline mode; in row2 mode the second line still appears when another row-2 field (such as an open PR) has data.
Sidebar defaults differ to fit the narrow rail: row1 is status, project with pr:short, agent:short on the right (PR stays visible even with the prompt hidden), and row2 is summary / time (a lone time never earns the row; it rides along when some other field has data). The 30-col rail has no room to inline, so the sidebar always uses the two-row layout (inline behaves like row2). Override these under the sidebar.columns key in ~/.config/ccmux/ccmux.json (e.g. "sidebar": { "columns": { "row2": { "left": ["pane"] } } } to bring the pane target back).
The CLI’s comma-separated form sets one mode per entry. To vary the layout by terminal width (responsive cascade), edit ~/.config/ccmux/ccmux.json directly and use the default/xs/sm/md/lg keys on either a row side (whole array) or an entry’s mode.
Breakpoints
Named breakpoints control when responsive column layouts activate. A breakpoint value applies from that terminal width upward until a larger breakpoint overrides it.
| Name | Default width |
|---|---|
xs |
40 |
sm |
60 |
md |
80 |
lg |
100 |
ccmux config set breakpoints.sm 55ccmux config set breakpoints.lg 120Theme
The TUI ships 14 built-in palettes across six families, resolved once at launch (no in-TUI toggle).
ccmux config themes # list built-ins, mark the active oneccmux config set theme tokyo-night # switch theme| Theme | Background |
|---|---|
catppuccin-mocha |
dark (default) |
catppuccin-macchiato |
dark |
catppuccin-frappe |
dark |
catppuccin-latte |
light |
tokyo-night |
dark |
tokyo-night-storm |
dark |
tokyo-night-day |
light |
dracula |
dark |
gruvbox-dark |
dark |
gruvbox-light |
light |
nord |
dark |
rose-pine |
dark |
rose-pine-moon |
dark |
rose-pine-dawn |
light |
For per-key tweaks, set theme to an object in ~/.config/ccmux/ccmux.json: a built-in base plus colors (the 14 semantic keys) and/or ansi (the 16 terminal colors used to render the preview), deep-merged over the base.
{ "theme": { "base": "catppuccin-mocha", "colors": { "red": "#ff5555" }, "ansi": { "brightBlack": "#585b70" } }}An unknown base name falls back to the default theme; an invalid hex value or unknown override key is dropped and the base value is kept. Each emits a warning. Run ccmux config themes to inspect any problems with the current config.
Multiple Claude Config Dirs
Claude Code writes session transcripts to $CLAUDE_CONFIG_DIR/projects (default ~/.claude/projects), so sessions from a second account (e.g. a personal login launched with CLAUDE_CONFIG_DIR=~/.claude-personal) land in a tree ccmux doesn’t watch by default. List those dirs in additionalClaudeConfigDirs and a single daemon watches every <dir>/projects tree:
ccmux config set additionalClaudeConfigDirs '["~/.claude-personal"]'ccmux setup --agent claude # installs hooks into every configured dirccmux daemon restart~/.claude is always watched; entries are additional config dirs (~ paths supported), and a set CLAUDE_CONFIG_DIR environment variable is picked up automatically. Sessions are keyed by their globally unique session ID, so the same project opened under two accounts coexists without collision.