bardo-terminal
What It Is
bardo-terminal is the workspace’s interactive Rust TUI binary. It owns terminal setup and teardown, a 60 fps render loop, the 30-screen catalog, responsive layout, shared application state, live system metrics, and the crate-local widget layer that the later screens compose.
The current implementation follows the terminal architecture described in prd2/18-interfaces/01-cli.md sections TUI (Interactive Mode), Architecture, Entry points, and The 15-screen system, plus prd2/18-interfaces/03-tui.md sections 3. Crate architecture, 4. Render loop, and 5. The 15-screen system, and prd2/20-styx/05-tui-experience.md sections 1. Architecture, 4. The Screen System (11 Views), and 5. Custom Widgets.
Those PRD sections sometimes count screens or views at a coarser grain (for example fifteen grouped destinations or eleven product views). Window grouping follows prd2/18-interfaces/21-screen-catalog.md (six top-level windows). The exact tab order and count are whatever ScreenId::all() returns in this binary (currently 30 entries, including PROTOCOL / Views for mock protocol panels). Treat older PRD figures as grouping language when they disagree with the live registry.
Features
- Raw-mode and alternate-screen lifecycle management with panic-hook recovery
- 60 fps frame loop with bounded input polling and frame skipping on overruns
- 30-screen catalog with stable
TabandShift+Tabcycling inScreenId::all()order - PROTOCOL / Views — four mock DeFi panels (pool, lending, vault, bridge); see bardo-terminal protocol views
- Shared
AppStatewith layout breakpoint, atmosphere animation, progress tracking, placeholder vitality, and live system metrics - Home dashboard with creature silhouette, pipeline progress, per-task timing, connection status, and system resource panels
- Responsive sidebar/content split driven by terminal width
- ROSEDUST palette tokens and CRT-style box-drawing glyphs
- Reusable widgets for sparklines, gauges, feeds, tabs, progress bars, timelines, and help overlays
- Typed navigation layer with keybinding config loading, command palette, modal stack, and optional vim mode
Getting Started
Run the terminal:
cargo run -p bardo-terminal
Run the crate tests:
cargo test -p bardo-terminal
Useful live controls:
qquitsTabmoves to the next screen inScreenId::all()Shift+Tabmoves to the previous screen/opens the command palette?toggles the help overlay- Resizing the terminal recomputes
LayoutBreakpoint
Enable tracing with the standard Rust logging environment:
RUST_LOG=info cargo run -p bardo-terminal
Configuration
The binary still relies primarily on runtime environment and terminal capabilities, but the navigation layer now also looks for ~/.bardo/keybindings.toml to override built-in keyboard defaults.
| Input | Effect |
|---|---|
RUST_LOG | Controls tracing_subscriber filtering |
~/.bardo/keybindings.toml | Overrides global and per-screen keybindings |
| Terminal width | Selects Compact, Standard, Wide, or Ultra layout |
| Terminal color and Unicode support | Affects palette fidelity, box drawing, braille sparklines, and block-glyph gauges |
The config path resolves from HOME, USERPROFILE, or HOMEDRIVE + HOMEPATH, then appends .bardo/keybindings.toml.
Module Overview
mainboots tracing, installs the panic hook, enters raw mode and alternate-screen mode, and runs the app loopappownsAppState,ScreenRegistry, screen switching, chrome rendering, and the frame loopscreendefinesScreen,ScreenId,ScreenRegistry, andStubScreenstatedefinesAppState,AppAction, placeholder vitality, connection status, atmosphere animation, progress tracking, and liveSysMetricslayoutcomputesLayoutBreakpointand the sidebar/content splitnavigationowns keybindings, the command palette, modal overlays, and vim-mode routingpalettedefines the terminal color constants, style modifiers, and box-drawing glyphsscreens::homeprovides the concrete home dashboardscreens::protocol_viewsprovides the PROTOCOLS / Protocol Views gridsys_statssamples CPU, memory, network, and disk metrics intoSysMetricswidgetscontains reusable ratatui widgets such asBrailleSparkline,TotalProgressBar,TabBar,EventFeed, andKeyHelpOverlay
API
Binary Entry Point
#[tokio::main]
async fn main() -> anyhow::Result<()>
The entrypoint installs the panic hook, initializes tracing, sets up the terminal, runs App::run, and restores terminal state on exit.
Runtime Scaffold
#![allow(unused)]
fn main() {
pub(crate) struct App {
/* private fields omitted */
}
impl App {
pub(crate) fn new() -> Self;
pub(crate) fn run(
&mut self,
terminal: &mut ratatui::Terminal<
ratatui::backend::CrosstermBackend<std::io::Stdout>,
>,
) -> anyhow::Result<()>;
}
}
App::new() registers HomeScreen, ProtocolViewsScreen, and StubScreen placeholders for every other ScreenId. App::run() polls crossterm events, advances shared state, refreshes system metrics, and renders the current frame.
Screen System
#![allow(unused)]
fn main() {
pub(crate) trait Screen: Send + Sync {
fn id(&self) -> ScreenId;
fn title(&self) -> &str;
fn render(
&self,
frame: &mut ratatui::Frame<'_>,
area: ratatui::layout::Rect,
state: &AppState,
);
fn handle_key(&mut self, key: crossterm::event::KeyEvent) -> Option<AppAction>;
fn on_focus(&mut self) {}
fn on_blur(&mut self) {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum ScreenId {
HearthOverview,
HearthSignals,
HearthOperations,
HearthStatus,
MindPipeline,
MindGrimoire,
MindPlaybook,
MindDreams,
MindInference,
MindChainIntelligence,
MindTechnicalAnalysis,
SomaPortfolio,
SomaTrades,
SomaCustody,
SomaBudget,
SomaSanctum,
WorldSolaris,
WorldClade,
WorldLethe,
WorldBloodstains,
WorldBazaar,
FateMortality,
FateLineage,
FateAchievements,
FateGraveyard,
CommandSteer,
CommandConfig,
CommandEffects,
CommandHermes,
ProtocolViews,
}
impl ScreenId {
pub(crate) fn all() -> &'static [Self];
pub(crate) const fn window_name(self) -> &'static str;
pub(crate) const fn tab_name(self) -> &'static str;
}
pub(crate) struct ScreenRegistry {
/* private fields omitted */
}
impl ScreenRegistry {
pub(crate) fn new() -> Self;
pub(crate) fn register(&mut self, screen: Box<dyn Screen>);
pub(crate) fn get(&self, id: &ScreenId) -> Option<&dyn Screen>;
pub(crate) fn get_mut(&mut self, id: &ScreenId) -> Option<&mut dyn Screen>;
}
pub(crate) struct StubScreen {
/* private fields omitted */
}
impl StubScreen {
pub(crate) fn new(id: ScreenId, title: impl Into<String>) -> Self;
}
pub(crate) struct HomeScreen {
/* private fields omitted */
}
impl HomeScreen {
pub(crate) fn new() -> Self;
}
}
Shared State And Layout
#![allow(unused)]
fn main() {
#[derive(Debug, Clone)]
pub(crate) struct AppState {
pub(crate) tick_count: u64,
pub(crate) connection_status: ConnectionStatus,
pub(crate) vitality: MockVitality,
pub(crate) layout: LayoutBreakpoint,
pub(crate) atmosphere: Atmosphere,
pub(crate) progress: ProgressState,
pub(crate) sys: SysMetrics,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum AppAction {
Quit,
NextScreen,
PrevScreen,
Resize(u16, u16),
GotoScreen(ScreenId),
GotoWindow(WindowId),
OpenCommandPalette,
CloseCommandPalette,
ExecuteCommand(usize),
PaletteInput(char),
PaletteBackspace,
PaletteSelectNext,
PaletteSelectPrev,
ShowHelp,
HideHelp,
CloseModal,
ConfirmModal,
ModalInput(char),
ModalBackspace,
EnterVimMode,
ExitVimMode,
VimNavigate(VimDirection),
VimCommand(String),
ScrollUp,
ScrollDown,
ScrollTop,
ScrollBottom,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum LayoutBreakpoint {
Compact,
Standard,
Wide,
Ultra,
}
impl LayoutBreakpoint {
pub(crate) const fn from_cols(cols: u16) -> Self;
pub(crate) const fn sprite_sidebar_cols(self) -> u16;
pub(crate) const fn panel_count(self) -> u8;
pub(crate) const fn label(self) -> &'static str;
}
pub(crate) fn compute_layout(
frame_size: ratatui::layout::Rect,
bp: LayoutBreakpoint,
) -> (ratatui::layout::Rect, ratatui::layout::Rect);
pub(crate) fn format_duration(secs: f64) -> String;
}
Navigation Layer
#![allow(unused)]
fn main() {
pub struct KeybindingMap {
pub global: std::collections::HashMap<crossterm::event::KeyEvent, AppAction>,
pub per_screen: std::collections::HashMap<
ScreenId,
std::collections::HashMap<crossterm::event::KeyEvent, AppAction>,
>,
pub vim_mode: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CommandPalette {
pub visible: bool,
pub query: String,
pub commands: Vec<Command>,
pub filtered: Vec<usize>,
pub selected: usize,
}
#[derive(Default)]
pub struct ModalManager {
pub stack: Vec<Modal>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VimModeState {
pub mode: VimMode,
pub command_buffer: String,
pub sequence_buffer: Vec<char>,
pub enabled: bool,
}
}
These types are wired into App::handle_key() so raw key events become typed actions before screen-local handlers run.
Palette Tokens
#![allow(unused)]
fn main() {
pub(crate) struct ColorPalette;
pub(crate) const BG_VOID: ratatui::style::Color;
pub(crate) const BG_RAISED: ratatui::style::Color;
pub(crate) const BG_MID: ratatui::style::Color;
pub(crate) const BORDER: ratatui::style::Color;
pub(crate) const BORDER_ACTIVE: ratatui::style::Color;
pub(crate) const ROSE: ratatui::style::Color;
pub(crate) const ROSE_BRIGHT: ratatui::style::Color;
pub(crate) const BONE: ratatui::style::Color;
pub(crate) const TEXT_PRIMARY: ratatui::style::Color;
pub(crate) const DREAM: ratatui::style::Color;
pub(crate) const WARNING: ratatui::style::Color;
pub(crate) const SUCCESS: ratatui::style::Color;
pub(crate) const DANGER: ratatui::style::Color;
}
Usage Examples
Start the binary and navigate between screens:
cargo run -p bardo-terminal
The home screen shows the live scaffold state:
- a creature silhouette in the left panel
- a pipeline progress bar with ETA in the right panel
- connection status and per-task timing
- a four-column system panel for CPU, memory, network, and disk
The responsive layout reacts to terminal width: given the terminal width in columns, the app selects a LayoutBreakpoint with LayoutBreakpoint::from_cols(width), then reads panel_count() and sprite_sidebar_cols() for chrome and sidebar geometry. (Those types live in the binary crate; there is no published bardo_terminal library path to import from another package yet.)
Tab and Shift+Tab cycle through the screen catalog in the exact order returned by ScreenId::all().
Architecture
main
├── install panic hook
├── setup terminal
├── App::new()
├── App::run()
│ ├── poll input
│ ├── tick state
│ ├── sample system metrics
│ ├── render chrome + active screen
│ └── sleep to maintain 60 fps
└── teardown terminal
app
├── screen registry
├── screen switching
├── responsive chrome
└── content rendering
screens::home
├── creature placeholder
├── progress bar
├── connection state
├── task timing
└── system resources
screens::protocol_views
├── four protocol cells (mock data)
└── focused-cell borders and grid/stack layout
References
prd2/18-interfaces/21-screen-catalog.md— six-window grouping (tab order and count:ScreenId::all()in code, currently 30)- bardo-terminal protocol views — Protocol Views screen behavior and layout
prd2/18-interfaces/01-cli.mdsectionsTUI (Interactive Mode),Architecture,Entry points, andThe 15-screen systemprd2/18-interfaces/03-tui.mdsections3. Crate architecture,4. Render loop,5.1 Persistent chrome,5.2 Screen map, and5.3 Screen detailsprd2/20-styx/05-tui-experience.mdsections1. Architecture,4. The Screen System (11 Views), and5. Custom Widgets