Skip to content

The TUI

The full-screen terminal UI for driving several named Claude Code sessions at once, over one fleet.

claude-coder tui opens an alt-screen interface. It drives the same real sessions as the CLI: every session runs Claude Code over your Claude subscription (see concepts). It is not a sandbox or a replay — turns, permissions, and costs are live.

Launch

claude-coder tui
Flag Effect
--cwd <dir> Working directory for new sessions. Defaults to the current directory.
--graceful On quit, close sessions in an orderly way (cleanly interrupt an in-flight turn) instead of an abrupt close.
--config <path> Use a specific profiles config file. Global option (applies to every command).

--config defaults to ./claude-coder.config.json or ~/.claude/claude-coder/profiles.json. See profiles for the file format and the built-in claude-code-expert profile.

Usage: claude-coder tui [--cwd <dir>] [--graceful]

Note

The TUI needs your subscription login. If claude is not authenticated, run claude and use /login first. An API-key credential is rejected — auth is always the subscription. See security.

Layout

A header, a sessions sidebar, a transcript pane, an input line, and a status line. Below ~45 columns it collapses to a single column (a session strip replaces the sidebar; the action strip overlays the last transcript row).

┌─────────────────────────────────────────────────────────────────┐
│ claude-coder · cap 2/2 live · 1 queued                          │  header
├───────────────────────┬─────────────────────────────────────────┤
│ SESSIONS              │ session1 · claude-code-expert · sdk · busy │  pane header
├───────────────────────┼─────────────────────────────────────────┤
│ ── LIVE ──            │ ⋯ +5 older lines                         │  top note
│  ▸● session1 claude-code-expert •2 │ assistant text...           │
│   ○ session2 claude-code-expert    │ ▸ tool call summary          │
│                       │ ◂ tool result                            │
│ ── QUEUED ──          │ ✓ turn complete · $0.02                  │
│  ⏳ pending-create     │                                          │
│                       │ ⋯ +3 new ↓                               │  bottom note
│ ── PERSISTED ──       │                                          │
│  ⇡ old-session        │                                          │
├───────────────────────┴─────────────────────────────────────────┤
│ ❯ type a turn...                                                 │  input
│ [n]ew  [↹]next  [e]input  [?]help  [q]uit · idle · $0.02         │  status
└─────────────────────────────────────────────────────────────────┘

The sidebar groups rows into LIVE, QUEUED, and PERSISTED sections (empty sections are hidden), with ── LIVE ── style section headers. Each row shows its glyph, name, and profile. The focused row is marked . State glyphs include busy, idle, starting, stalled, error, closed, awaiting a permission, profile on cooldown, and an SDK→PTY rerouted session. A •N badge on a non-focused row is its unread-event count. Queued creates show ; persisted (resumable) sessions show .

The header capacity reads cap <live>/<max> live · <queued> queued. <max> is the fleet's concurrency ceiling (default 2).

Keybindings

These are the bindings exactly as the help overlay (?) groups them.

Navigate

Keys Action
/ focus next session
⇧↹ / focus previous
19 focus session N

Sessions

Keys Action
n new session
r resume persisted
f fork persisted
c cancel queued create
R reload persisted
q quit (close all)

Turn

Keys Action
e edit / type a turn
enter send the turn
i interrupt busy turn

Permissions

Keys Action
a allow once
d deny
s allow session
19 pick a question option
enter confirm multi-select
⇧↹ previous question

View

Keys Action
PgUp / PgDn scroll transcript
Home / End top / bottom
? this help

Search

Keys Action
/ search transcript
n / N next / prev match

Ctrl-C always quits, in any mode. Navigation works on any row; enter (send), i (interrupt), and transcript scroll require a focused live session. Entering input mode with e is always available, but send then fails with a notice if there is no live focus.

Modal keys (not in the help overlay, since they only apply inside a mode):

Mode Keys
Typing a turn (input) esc clears the input line · focuses the next session · backspace deletes
Create modal esc cancels at either step (profile pick / name) · backspace edits the name
Search esc exits search

Multiple sessions

Press n to create a session: pick a profile (/, enter), then type a name (enter to confirm). The new session enters the LIVE section.

At capacity. When live sessions already fill the concurrency ceiling, the create modal shows a banner:

2/2 live — will QUEUE

Confirming appends an optimistic row to the QUEUED section. The create blocks on the fleet's FIFO admission waiter. When a slot frees, the waiter resolves and the row graduates to LIVE. Press c on the queued row to cancel it before it admits. The queued row is a prediction; it is never removed early, and it clears only on a terminal result (admitted, cancelled, or failed).

Switch. / and ⇧↹/ walk the unified list (LIVE, then QUEUED, then PERSISTED, wrapping). 19 jumps to a row by position. A non-focused row accumulates a •N unread badge as fleet events arrive; focusing it clears the badge.

Resume / fork. In the PERSISTED section, r resumes the focused session and f forks it (opens the name editor, then creates a copy). Both graduate to LIVE on success. R reloads the persisted roster. See profiles and CLI for the underlying resume/fork semantics.

Interrupting a turn

Focus a busy session and press i. This is gated on the row being busy or stalled; on any other state it is a no-op with a notice. The interrupt is real — it cancels the in-flight turn over the fleet. There is no optimistic flip; the new state arrives as a normal fleet event.

Transcript scroll

The pane follows the tail by default. To read back:

Keys Effect
PgUp / PgDn one page older / newer
Home / End jump to top / bottom (resume following)

A top note ⋯ +N older lines appears when content exists above the window. A bottom note ⋯ +N new ↓ appears when you have scrolled up and new lines have landed below — End returns to the tail. While scrolled, appended lines keep the same content in view rather than scrolling it away.

/ opens search over the session's transcript (live focus required) — the whole retained ring, not just the on-screen window. Type to filter, enter to commit, then n/N to cycle matches (with wrap); n/N scroll the pane to reveal a match that is off-screen. The bottom note shows 🔎 c/T (current / total) while searching. esc exits search.

Help overlay

Press ? (in list or permission mode) to open the help overlay — the grouped keybinding reference above. Any key closes it without firing the underlying command. Ctrl-C still quits.

Answering AskUserQuestion

When Claude Code calls AskUserQuestion, the prompt renders as an action strip and the TUI switches to permission mode. Plain tool-permission prompts render the same way with [a]llow [d]eny [s]ession.

Single-select. Options are numbered. Press the matching 19 to pick and resolve immediately. a picks the first option; d skips (deny).

❓ session1: Which framework?   1. React  2. Vue  3. Svelte  [a]first [d]skip

Multi-select. Each option shows a checkbox. 19 toggles a box; enter confirms the whole set. d skips.

❓ session1: Pick all that apply   [x] 1. lint  [ ] 2. test  [x] 3. build  [↵]confirm [d]skip

Multiple questions. A [q N/M] counter precedes the question. Single-select answers advance to the next question on pick; multi-select advances on enter. ⇧↹ goes back to the previous question, keeping recorded answers. The last question reads [↵]confirm (multi-select) or [a]first (single); earlier ones read [1-9]next or [↵]next. d skips all remaining.

❓ session1: [q 1/2] Pick all that apply   [ ] 1. a  [x] 2. b  [↵]next [d]skip

Warning

A pending permission or question blocks that session's turn until you answer or skip. The status line shows the pending count.

Quit and terminal restore

Press q (or Ctrl-C) to quit. The TUI restores the terminal first — leaves the alt-screen, shows the cursor, unhooks input — then denies any open permission, aborts queued creates, and closes all sessions. The restore runs before anything else and on every exit path, including a crash, so the terminal is always left sane.

With --graceful, the final close is orderly — an in-flight turn is cleanly interrupted (it settles as interrupted) before the session tears down. It does not wait for the turn to complete. The default (no flag) is transport-specific: SDK-backed sessions close directly without that interrupt step, while PTY-backed sessions already close in an orderly way (they send /exit and await a clean exit before terminating). Either way the terminal is always restored first.

See also

  • CLI — the same sessions from the command line (repl, resume, fork).
  • Profiles — defining the profiles you pick in the create modal.
  • Library and the local API gateway — driving the fleet programmatically.
  • Troubleshooting — auth, version band, and terminal issues.