Skip to main content

Fullscreen TUI

The fullscreen TUI is a terminal takeover UI built with crossterm. It uses an alternate screen, raw mode, mouse capture, and fixed layout regions.

Layout

RegionRowsResponsibility
Header9 rowsBrand bar, active model, pinned status panel, command bar.
TranscriptFlexibleUser prompts, system progress, trace summaries, assistant responses, metadata.
Input area4 rowsPrompt line, context meter, project/chat/activity status.

The shell scrollback is not used during fullscreen mode. The transcript owns its own scroll offset.

Panels

The pinned panel is a compact status dashboard at the top of the screen.

PanelShows
DashboardProject, model inventory summary, agent roles, last query, UI mode.
ProjectActive project, state, /project commands, file-tagging hint, project config path.
ModelsActive provider/model, inventory status, provider chips, setup commands, config path.
AgentsArchitect, Context Loom, Explorer, Coder, approval boundary.
ContextContext Loom, context window, memory commands, pack preview, index refresh.
SessionsCurrent session, store path, recent sessions.
TimelineLatest structured agent path.
CheckRuntime readiness, active provider, workspace, config.
ConfigProvider/model/config/key hints.
HelpCommand map, scrolling, cancellation, launch forms.

The command bar exposes quick panel commands:

/dashboard /project /models /agents /context /sessions /timeline /check /config /help

Input Editor

The input editor is single-line and stable across terminal widths.

KeyBehavior
EnterSubmit the line.
Left / RightMove cursor.
Home / EndMove to start/end.
Backspace / DeleteEdit characters.
Up / DownNavigate input history.
TabInsert two spaces.
@Open the project file picker when a project is active.

Input history is stored in memory for the current TUI process and capped by INPUT_HISTORY_CAPACITY.

File Tag Picker

Typing @ opens a searchable modal backed by cli/src/terminal_ui/project.rs.

The picker:

  1. Scans the active project for taggable text files.
  2. Skips hidden and ignored directories such as .git, .venv, node_modules, target, dist, and build.
  3. Skips common binary suffixes.
  4. Lets the user type to filter results.
  5. Inserts either @path or @"path with spaces" into the prompt.

The Python core later resolves those tags with safe_path() and loads bounded read-only context.

Scrolling

InputBehavior
Mouse wheel up/downScroll chat by a small fixed amount.
PageUp / PageDownScroll by visible page size.
Ctrl-HomeJump far up.
Ctrl-EndReturn to live bottom.

When scrolled away from the bottom, the TUI renders a CHAT SCROLLED marker and keeps the live task progress from unexpectedly moving the user's viewport.

Modals

Focused modal modules keep the TUI maintainable:

FileModal or flow
modal.rsShared modal primitives, text input, searchable picker.
project.rsProject folder prompt and file picker.
model_picker.rsProvider/model picker and masked API key prompt.
approval.rsRuntime approval prompt for ProtoLink actions.
diff_view.rsDiff review modal for proposed file changes.

Context Meter

The bottom input area contains a context usage meter. It consumes normalized ProtoLink RunEvent payloads, especially model context events, and records:

FieldMeaning
used_tokensEstimated or measured tokens used.
window_tokensConfigured or detected context window when known.
used_percentPressure against the window.
estimatedWhether token count is estimated.
agent_nameAgent that emitted the sample.
modelModel name associated with the sample.

The meter keeps the latest sample and a high-water peak.

Task Loop

When a user submits a task:

  1. The TUI verifies an active project.
  2. A project session id is selected unless /context off is active.
  3. A temp progress JSONL file is created.
  4. Python is called through call_process_prompt_with_progress.
  5. The TUI tails progress events every 120 ms.
  6. Approval requests are displayed as modals.
  7. Esc or Ctrl-C writes a cancellation request.
  8. The final JSON response is parsed into CoreResponse.
  9. The response is appended to the transcript and recorded in sessions.json.

The one-shot runner in main.rs uses the same ProgressFile bridge but prints panels to stdout instead of rendering alternate-screen UI.