-
-
Notifications
You must be signed in to change notification settings - Fork 0
Terminal UI
M31A's 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.
cmd/m31a/main.go
│
▼
tea.NewProgram(AppState)
├── Init() → startup commands
├── Update() → message routing, state transitions
└── View() → screen rendering
Source: internal/tui/app.go
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. |
| 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 |
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 |
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 |
| Mode | Description |
|---|---|
ModeDark |
Dark theme (default) |
ModeLight |
Light theme |
ModeAuto |
Auto-detect from terminal |
Built with Lip Gloss for declarative styling.
Source: internal/tui/layout/
| File | Purpose |
|---|---|
responsive.go |
Responsive breakpoints and sizing |
page.go |
Page layout helper |
minscreen.go |
Minimum screen size handling |
Source: internal/tui/streaming/
| File | Purpose |
|---|---|
agent_loop.go |
Agent loop streaming with tool execution |
streaming.go |
Core streaming response rendering |
The streaming system:
- Receives
StreamChunkfrom the provider - Renders text deltas incrementally
- Accumulates tool_call chunks
- Updates thinking duration display
- Handles usage tracking
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 |
Source: internal/tui/cmdpalette.go, internal/tui/commandpalette_model.go
Press Ctrl+P to open. All registered slash commands appear with fuzzy search.
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().