Skip to content

Terminal UI

Eshan Roy edited this page Jun 16, 2026 · 3 revisions

Terminal UI

M31 Autonomous's (M31A) terminal interface is built with Bubble Tea, following the Elm architecture with a single-threaded Update() loop. The TUI provides 29 distinct screens, 40+ reusable components, and 5+ themes.

Architecture

cmd/m31a/main.go
    │
    ▼
tea.NewProgram(AppState)
    ├── Init()     → startup commands
    ├── Update()   → message routing, state transitions
    └── View()     → screen rendering

Source: internal/tui/app.go

App State

Source: internal/tui/app_state.go

AppState is the root Bubble Tea model containing:

Field Type Purpose
screen Screen enum Active screen identifier
config *config.Config Runtime configuration
registry *provider.Registry LLM provider registry
dispatcher *tools.Dispatcher Tool dispatcher
sessionManager *session.Manager Session lifecycle
workflowEngine *workflow.Engine Workflow orchestration
replModel *ReplModel REPL screen model
sidebarModel *SidebarModel Sidebar panel
themeManager *theme.Manager Theme management
Various screen models Model selector, settings, plan, diff, etc.

Screens

Screen Source Description
ScreenREPL repl_model.go Main chat interface
ScreenFirstRun firstrun_model.go Initial API key setup
ScreenModelSelector modelselector_model.go Fuzzy model search
ScreenSettings settings_model.go Config editor with tabs
ScreenConfig config_model.go Full config.toml editor
ScreenPlan plan_model.go Plan viewer and refiner
ScreenExecute execute_model.go Task execution view
ScreenVerify verify_model.go Verification results
ScreenShip ship_model.go Ship phase view
ScreenDiff diff_model.go Git diff viewer
ScreenRollback rollback_model.go Commit rollback browser
ScreenResume resume_model.go Session resume picker
ScreenDashboard dashboard_model.go Workflow dashboard
ScreenMetrics metrics_model.go Session analytics
ScreenLedger ledger_model.go Learning ledger
ScreenFileExplorer fileexplorer_model.go File tree browser
ScreenChatHistory chathistory_model.go Message history browser
ScreenBisect bisect_model.go Model response comparison
ScreenDiscuss discuss_model.go Discuss Q&A interface
ScreenHelp help_model.go Keybinding help
ScreenThemePicker themepicker_model.go Theme selection
ScreenToolDetail tooldetail_model.go Tool detail view
ScreenSessionDetail sessiondetail_model.go Session detail view
ScreenConfirmQuit confirmquit_model.go Quit confirmation
ScreenNotification notification_model.go Notification center
ScreenGhostPicker ghostpicker_model.go Ghost write file picker
ScreenGhostOutput ghostoutput_model.go Ghost write output
ScreenSubagents subagents_model.go Subagent manager
ScreenPhaseModelPicker phasemodelpicker.go Per-phase model assignment

Components

Source: internal/tui/components/

40+ reusable UI components:

Component Purpose
badge.go Status badges with color coding
bash_renderer.go Syntax-highlighted bash command output
breadcrumb.go Navigation breadcrumbs
card.go Content cards with borders
codeblock.go Code blocks with syntax highlighting
confirm.go Confirmation dialogs
datatable.go Tabular data display
divider.go Visual dividers
dropdown.go Dropdown menus
file_renderers.go File content renderers
filetree.go File tree with expand/collapse
filterchips.go Filter chip selectors
logo.go Application logo rendering
message.go Chat message rendering (markdown)
metriccard.go Metric display cards
notification_list.go Notification list with auto-expiry
permission.go Permission modal
progress.go Progress bars
question.go Question/option picker
search.go Search input
sparkline.go Sparkline charts
special_renderers.go Special content renderers
spinner.go Loading spinners (multiple styles)
splitpane.go Split pane layout
starfield.go Animated starfield background
statrow.go Statistics row display
syntax.go Syntax highlighting (Chroma-based)
tabbar.go Tab bar navigation
taskgraph.go Task dependency graph visualization
thinking.go Thinking/reasoning block display
timeline.go Event timeline
toolcard.go Tool execution cards
toolrenderers.go Tool-specific renderers
truncate.go Text truncation helpers
workflow_phasebar.go Workflow phase progress bar

Theme System

Source: internal/tui/theme/

File Purpose
theme.go Theme struct with all color/style definitions
registry.go Theme registry with named themes
colors.go Color palette definitions
borders.go Border style definitions
shadow.go Shadow effect rendering
tabs.go Tab styling
unicode.go Unicode character constants

Theme Modes

Mode Description
ModeDark Dark theme (default)
ModeLight Light theme
ModeAuto Auto-detect from terminal

Built with Lip Gloss for declarative styling.

Layout System

Source: internal/tui/layout/

File Purpose
responsive.go Responsive breakpoints and sizing
page.go Page layout helper
minscreen.go Minimum screen size handling

Streaming Infrastructure

Source: internal/tui/streaming/

File Purpose
agent_loop.go Agent loop streaming with tool execution
streaming.go Core streaming response rendering

The streaming system:

  1. Receives StreamChunk from the provider
  2. Renders text deltas incrementally
  3. Accumulates tool_call chunks
  4. Updates thinking duration display
  5. Handles usage tracking

REPL Model

The REPL is the primary interaction surface. It supports:

Source: internal/tui/repl.go and related files

Feature Source
Message history repl_model.go
Streaming display repl_stream.go
Thinking blocks repl_thinking.go
Mouse support repl_mouse.go
Scrollbar repl_scrollbar.go
Quick actions repl_quickactions.go
Welcome screen repl_welcome.go
Footer repl_footer.go
Clipboard repl_clipboard.go
State management repl_state.go
Slash commands repl_commands.go

Command Palette

Source: internal/tui/cmdpalette.go, internal/tui/commandpalette_model.go

Press Ctrl+P to open. All registered slash commands appear with fuzzy search.

Workflow Integration

The TUI drives the workflow engine via RunPhaseCmd():

User types "/workflow"
    │
    ▼
AppState.initWorkflowEngine()
    │
    ▼
RunPhaseCmd(PhaseInitialize)  →  engine.RunPhase() in goroutine
    │
    ▼
PhaseResultMsg arrives via Bubble Tea message
    │
    ▼
AppState transitions to next phase
    │
    ▼
RunPhaseCmd(PhaseDiscuss) → ... → RunPhaseCmd(PhaseShip)

Messages from the engine reach the TUI through a channelEmitter that writes to a buffered channel, drained by drainEmitterCmd().

Clone this wiki locally