Skip to main content

TUI

flux tui is the full-screen terminal chat UI — the same agent loop, the same safety envelope, and the same session store as flux run, driven interactively. It renders a streaming transcript, tool cards, plan trees, and an in-UI approval sheet, and it keeps the composer live while a turn is running so you can write the next message (or steer the current one) without waiting.

flux tui # start in the current workspace
flux tui -m opus # pick a model for the session
flux tui --yes # auto-approve every admitted tool call (no approval sheet)
flux tui -c # continue the most recent session
flux tui --remote https://worker.example:8790 # approve here; effects land there
flux tui --attach https://agent.internal:8787 # the whole agent lives there; watch and steer it
flux tui --fleet # attach to the Fleet rooted in the current directory
flux tui --fleet=../roadmap # attach to an explicit Fleet root
--remote and --attach are opposite

--remote (and --host) keep the agent here and land its effects there, so you still approve on this machine and the session is stored in your local event store. --attach moves the whole agent — planning, model calls, tools, approvals and the session — to a served host, and this terminal becomes a window onto it. flux refuses the two together. See attaching the TUI to a served agent for what an attached surface can do, which affordances the protocol does not carry, and — importantly — which session artifacts live on which machine.

flux tui takes the same turn-control flags as flux run — see CLI for -m, --effort, --max-tokens, --turn-budget, --loop, --skill, and the rest, and CLI for the flags that apply to every command.

In remote mode the header continuously shows the endpoint and canonical remote workspace. It is not a startup notice that scrolls away. The directory where the TUI started remains the local control plane; flux does not synchronize it with the remote tree.

When a budget is declared, the header also carries a live budget segment — budget Σ1.6k/4.0k tok, budget 3/10 calls, budget 12.0s/1.0m — showing spend against the declared figure and updating as spend accrues. It shows the dimension closest to its ceiling, marks a crossed target over target and a crossed hard ceiling limit, and shows nothing at all when no budget is declared. The figures come from the enforcing ledger, not from a second tally kept by the UI — see time and token budgets.

The header also names the loop the agent runs — loop adaptive@1 8f3c…, the resolved profile, revision and abbreviated source digest, never a filename. F3 opens the loop selector: it rescans the workspace's .flux/loops directory on every open (so a loop authored while the TUI runs appears without a restart) and always offers the shipped adaptive@1 preset. Type to filter, Enter selects, Esc closes. Selecting raises a short overlay showing the loop's description and its outer structure, and the choice takes effect on the next start. A session that has already run a turn has admitted its loop: the selector then refuses and names the new-session/re-admission path instead of switching a running agent.

Describing a loop authors one: /loop <what it should do> generates the *.flux file under .flux/loops, and the selector reopens with the new loop under the cursor, ready to select. The generated program passes the same load-time validation a hand-written loop passes before it is offered — an invalid generation is refused with its error rather than saved, and an existing loop file is never overwritten. Authoring is not an admission: it does not change the loop a running agent already runs, and it does not authorize the profile for a Fleet task kind.

Board and Fleet operations

Ordinary flux tui remains a standalone chat and says so in the header. Fleet attachment is always explicit: --fleet means the current directory and --fleet=ROOT names another root. The attached form validates .flux/fleet.toml, opens the reserved main coordinator's isolated session store, and resumes the exact session recorded in durable Fleet state. It never substitutes the newest unrelated chat session.

Start the supervisor before sending coordinator requirements:

flux fleet start --output json
flux tui --fleet

The attached header continuously says Fleet main, connected or stopped, the Fleet revision, and F2. A stopped or failed main remains inspectable but refuses conversation input until it is started and the view is refreshed. At 104 columns and wider, a right-hand attention rail summarizes the active wave, worker capacity, open decisions, blocked work, and failures. Narrow terminals keep the full chat width and use the header plus the full-screen operations view.

Press F2, or run /fleet or /board, to open that view. Tab/Shift-Tab or 15 select Overview, Board, Workers, Decisions, and Stats; arrows and PgUp/PgDn move the selection; Enter opens detail; r refreshes; Esc, q, or F2 closes it. Worker detail correlates the durable assignment, session, worktree, handoff, review, rework, activity, and error evidence. Missing fields say unavailable. Capacity distinguishes configured, desired, active, draining, and registered; desired/draining likewise remain unavailable until the Fleet's durable state records them.

The Board view renders each item as a collapsed bordered box carrying only its id, title, status, and priority, grouped by status and ordered by ascending priority inside a group — the same order flux board next returns for ready work. A box whose item the Fleet has in flight is additionally marked ◆ <wave>; that marker comes from Fleet state (a live worker's assignment or active-wave membership), never from the Board's own status. Only the boxes the viewport shows are built, so a board of a thousand-plus items pages to the selection instead of rendering every box. The view also includes ready, active, blocked, and completed stories, dependencies, linked planning documents, decision lifecycles, and the exact flux.board-stats/v1 ratios/history used by flux board stats. Lists and text are bounded before rendering; a refresh error keeps the last good snapshot and marks it stale instead of inventing an empty Fleet.

Conversation input is durably acknowledged as accepted, delivered, then completed or failed. Those recent acknowledgements reconstruct after restart together with the main transcript. Viewing operations is read-only. The only Board mutation in the view is choosing an option on an open decision: open its detail, select with Left/Right, press Enter to review the confirmation, then Enter again to apply. The TUI cannot push, release, deploy, apply a Fleet candidate, or clean worktrees.

Press F1 at any time for the in-app keybinding and slash-command list. That overlay is generated from the same tables the UI dispatches on, so it can never drift from the running binary.

Keybindings

Everything not listed below edits the composer — text, Backspace, arrows, word navigation, Home/End, Ctrl-U undo — and stays live while a turn runs.

KeyWhat it does
EnterSend. While a turn is running, queue the message instead (see Queue and steering).
Ctrl-J · Alt-Enter · Shift-EnterInsert a newline instead of sending.
/ Recall previous input — only at the composer's first/last row, so they still move the cursor inside a multi-line message.
Ctrl-RReverse history search. Type to match; Ctrl-R again steps to an older hit; Enter keeps the recalled text in the composer without sending; Esc restores the draft you started from.
Ctrl-FTranscript search. Opens in typing mode; Enter leaves typing mode, then n / N step forward/backward through matches. Ctrl-F reopens typing; Esc closes.
PgUp / PgDnScroll the transcript by a page. PgDn re-attaches follow mode when it reaches the bottom.
Mouse wheelScroll the transcript three lines at a time.
Ctrl-EndJump to the latest activity and re-attach follow mode.
Ctrl-G / Ctrl-Shift-GJump to the next / previous failed tool card.
Ctrl-EExpand/collapse tool and thinking details on all cards at once.
Shift-↑ / Shift-↓Move the transcript entry focus. With an entry focused: Enter expands/collapses that one card, y copies the entry to the system clipboard, Esc clears the focus.
Ctrl-TToggle mouse capture. With capture off, your terminal's native select-and-copy works again; wheel scrolling stops, PgUp/PgDn keep working, and the footer shows mouse off (Ctrl-T).
Ctrl-CContext-sensitive: interrupt a running turn · clear a non-empty composer · arm quit when idle and blank (see Leaving).
Ctrl-DQuit — only when the session is idle and the composer is empty.
F1Open the help overlay (F1, Esc, q, or Enter closes it).
F2Open/close the attached Board + Fleet operations view. No effect in standalone chat.
F3Open the loop selector: the live set of *.flux loops plus the built-in preset. Type to filter, Enter switches the agent's loop for its next start and shows the loop's structure and description, Esc closes.
EscDismiss the active popup, cancel a queue edit, or clear a half-typed slash command.

Terminal support for the newline keys

Ctrl-J always inserts a newline — it is a plain control character every terminal sends. Alt-Enter and Shift-Enter only work in terminals that actually report the modifier on Enter. If your terminal sends a bare Enter for both, the message is sent instead; use Ctrl-J.

Pasting

Bracketed paste is enabled for the session, so a multi-line paste arrives as one block and is inserted into the composer verbatim — newlines inside the pasted text never submit the message.

The composer

The composer is a full multi-line editor and stays interactive while a turn runs. Two popups can take over the keys while they have candidates:

Slash menu. Typing a bare / prefix opens a fuzzy-ranked command menu — prefix beats substring beats subsequence, so /thm finds /theme. / select, Tab completes the name into the composer (adding a trailing space when the command takes an argument), Enter selects and runs it, Esc clears the composer.

@ path completion. An @-prefixed token opens a workspace file picker. / select, Tab or Enter inserts the path, Esc dismisses it for that token. The inventory is a bounded, ignore-aware walk built lazily on first use and cached for the session: it skips hidden entries, target/, and node_modules/, does not follow symlinked directories, and stops at 20,000 files.

Queue and steering

Pressing Enter while a turn is running does not interrupt it. The message goes onto a steering queue shared with the engine, and one of two things happens:

  • The adaptive loop drains the queue before the next consultation in its provider-native exploration stage and folds the text into the running turn as attributed steering — no cancelled operations, no disturbed approval prompt. The transcript records ↪ steering delivered: ….
  • If the turn finishes first, the next queued message starts as its own turn.

Consumption is the commit point: once the engine has drained an item you can no longer edit or retract it.

/queue opens the queue manager over the transcript:

KeyEffect
/ Select a queued message
Alt-↑ / Alt-↓Reorder the selected message
Delete or BackspaceRetract the selected message
EnterLoad it back into the composer to edit (Enter re-queues, Esc cancels the edit)
EscClose the manager

Approvals

When the agent proposes an effectful action batch, the approval sheet takes the keyboard. Only explicit keys act — every other keystroke is deliberately swallowed, so a stray press can never silently deny a batch.

KeyChoice
yAllow this call
aAllow always — records an allow rule, persisted when the TUI exits
n or EscDeny
dDeny with a reason — type it, Enter sends the denial carrying the reason, Esc returns to the sheet with the approval still pending
/ Scroll the sheet's subject list

flux tui --yes skips the sheet for admitted calls and auto-approves them within the active policy, app, and agent ceilings. See Safety and approvals for what prompts and why.

Slash commands

These are the TUI's built-ins. A command file discovered from .flux/commands, .claude/commands, ~/.flux/commands, or ~/.claude/commands is listed alongside them in the menu and in F1 — see Command files.

CommandEffect
/helpOpen the keybinding and command overlay (same as F1)
/usageOverlay: tokens, cache hit rate, and cost for the turn and the session
/insights [direction]Show durable facts for this session, then narrate them once; optional text focuses the summary without changing the facts
/model [spec]Show the active model, or switch mid-session (/model opus)
/effort [low|medium|high|xhigh|max|off]Show or set reasoning effort; takes effect from the next turn
/theme [name]List the palettes and the current one, or switch (see Themes)
/loop [description]Open the loop selector, or author a new *.flux loop from a description and offer it immediately
/toolsList the operations registered for this session
/shellToggle the optional bash op group from the next turn
/evidenceShow the session's durable evidence trail
/sessionShow the active session id and model
/sessionsOpen the session picker (--prune instead removes empty sessions)
/resume <id>Resume a session by id
/new · /clearStart a fresh session
/compactCompact older conversation history now
/queueManage queued follow-ups (see Queue and steering)
/fleet · /boardOpen the operations view when this TUI was launched with --fleet
/quit · /exitClear queued follow-ups, cancel a running turn, then leave once cancellation finishes

While a turn is running, only the read-only commands (/help, /tools, /evidence, /session, /sessions, /queue, /theme, bare /effort) and /quit run — anything that mutates the session asks you to interrupt the current action first.

/insights is an idle-only, cancellable report action because it makes one provider call. Its fact block comes from the session log, the optional direction only focuses the prose, and the generated summary is displayed without becoming conversation history.

/sessions opens a picker rather than printing a list: type to filter, / to select, Enter to switch, Esc to close. Switching is refused while a turn is running.

Themes

/theme with no argument lists the palettes and shows the active one. The shipped set is:

dark · light · dracula · nord · high-contrast · mono

Truecolor terminals get a finer-grained tuning of each palette automatically. NO_COLOR forces the mono palette regardless of the name you pick.

/theme <name> applies the palette immediately and persists it to ~/.flux/config.toml. It is the theme key documented in the configuration reference — set it there to choose a default without running the command.

The animated intro is skipped under NO_COLOR, when FLUX_NO_SPLASH is truthy, or in a terminal too small to draw it.

Leaving

Ctrl-C means different things depending on what is happening:

  • A turn is running — cancel it. The composer stays live, so you can keep typing.
  • Idle, composer has text — clear the composer.
  • Idle, composer emptyarm quit. The footer shows Ctrl-C again to quit; a second Ctrl-C within two seconds exits. Any other key disarms it, so a single reflexive press never drops you out of the session.

How long cancelling takes

Cancellation is cooperative, so it is acknowledged immediately but is not instantaneous. Any sub-agent the turn had in flight switches to a cancelling row in the fleet pane the moment the request lands — a state of its own, neither running nor a finished outcome — so you can tell the request was received rather than watching a spinner.

The wait has a ceiling: the provider call already open, plus a 10-second cleanup grace. A model request cannot be interrupted mid-flight, so a child that is waiting on a large-context answer keeps that request open until the provider replies; only then does the grace window start, and a child that still has not stopped by the end of it is reported as failing to stop. Independently, a sub-agent carries a 10-minute wall-clock deadline by default, which fires the same cancellation path, so a child can never run unbounded even if the cancel never reaches it.

Ctrl-D exits directly, but only from an idle session with an empty composer. /quit and /exit have one meaning in every state: clear queued follow-ups, cancel a running turn, and leave once cancellation finishes.

Recorded conversation and accepted-plan progress are durable. The current composer draft and queued-but-unconsumed follow-ups are not: they live only in the TUI process and are discarded when you leave. flux tui -c, /resume <id>, or the /sessions picker restores the recorded session. If that session was killed after accepting a plan, the next entry attempts to finish the durable turn before running new input; an effect interrupted before its cassette record can run again. See Crash recovery for the boundary.

  • CLI — subcommands, global flags, and the turn controls flux tui shares with flux run.
  • The agent loop — what the transcript's stages, plans, and batches actually are.
  • Safety and approvals — the envelope behind the approval sheet.
  • Configuration — the theme key and the rest of the settings.
  • Providers and models — how /model and -m resolve a spec.
  • Troubleshooting — credentials, sandbox, and session-state problems.