romm-tui
Terminal UI for browsing and managing a RomM library. Built on ratatui and crossterm. Depends on romm-api.
Crate path: romm-tui/ in the workspace.
Run the TUI
Prebuilt binaries are on the Releases page under romm-tui-v* tags.
First launch runs a setup wizard if config.json is missing. You can also configure the server from Settings or via romm-cli init — see romm-api configuration.
On startup, the TUI checks for newer releases (disable with ROMM_CHECK_UPDATES=false).
Features
- Library browsing — platforms, collections, and ROM lists;
ffilters the focused pane (consoles, collections, or games);/opens server-wide ROM search - Game detail — cover-first layout with inline image rendering when the terminal supports it (Kitty, iTerm2, Sixel); halfblocks fallback on Windows Terminal;
oopens the cover in a browser;mmatches metadata;Shift+Uunmatches;ttoggles technical details; RetroAchievements list when RomM has matched the ROM and your RA profile is synced (via RomM web UI) - Background downloads — start downloads and keep browsing
- Settings — auth, paths, appearance, save-sync options
- Save downloads — per-console save paths (see api.md — custom save paths)
Screenshots
Game details view

Keyboard (game detail): Enter download · e extras · u upload save · D download save · m match metadata (edit search title, Enter) · Shift+U unmatch · t technical details · o open cover · Esc back
Search view

Theming
Built-in theme IDs include terminal, catppuccin, dracula, nord, tokyo-night, and others from Settings → Appearance.
- Set in Settings → Appearance menu,
config.json(themefield) orROMM_THEMEenv var - Non-
terminalpresets paint full-frame backgrounds when the theme defines a palette background andNO_COLORis unset
Library startup
Choosing Library from the main menu loads a compact on-disk snapshot of platforms and merged collections (if present) so the list renders without waiting for the network. A background task refetches endpoints, updates the UI, and writes a fresh snapshot. Full ROM lists load on demand and use the ROM list cache.
Override snapshot path with ROMM_LIBRARY_METADATA_SNAPSHOT_PATH (default: next to ROMM_CACHE_PATH). See api.md.
Internals
This section describes the TUI implementation for contributors. Read alongside cargo doc -p romm-tui --open and architecture.md.
Event loop
The heart of the TUI lives in romm_tui::tui::app::App::run:
- Enable raw mode and enter the alternate screen
- Loop: drain background tasks → render → poll keys → dispatch → deferred work
The TUI follows an Event → Action → update → render pipeline:
poll_frame_events() # drain_background_events + crossterm input
→ map_event() # AppEvent → Action
→ App::update() # single state-mutation entry point
→ render() # ratatui draw (screens are render-only)
Key modules under romm-tui/src/tui/:
| Path | Role |
|---|---|
app/event.rs |
AppEvent, Action, global key mapping |
app/update.rs |
Applies actions (navigation, spawns, completions) |
app/run.rs |
Thin loop using runtime.rs (TuiSession) |
app/handlers/screen_keys.rs |
Per-screen key → action dispatch |
screens/setup_wizard/event.rs |
First-run wizard events |
Public exports: romm_tui::tui::app::{App, AppScreen}.
Screens
Each screen is a struct under romm-tui/src/tui/screens/:
MainMenuScreen— entry menuLibraryBrowseScreen— consoles/collections + ROM listSearchScreen— text input + results tableGameDetailScreen— detail view for a single ROMMetadataMatchScreen— provider search picker aftermon game detailDownloadScreen— overlay showing downloadsSettingsScreen— config summary and editorsSetupWizard— first-run / reconnect flow
AppScreen in tui::app wraps these so App holds one active screen. StartupSplash (screens/connected_splash) may render before the main menu.
App module layout
app/mod.rs—App,AppScreen,App::new, key dispatchapp/run.rs— terminal event loopapp/render.rs— frame drawing and global overlaysapp/background/— async task completion types and spawn/poll helpersapp/handlers/— one module per screen groupapp/rom_load.rs— ROM list fetch and collection prefetch
Theming implementation
ratatui-themekit presets via tui::theme::RommStyles. Semantic roles (selection, label, success, error, warning, muted) map to theme slots in romm-tui/src/tui/theme.rs. Screen renderers take &RommStyles instead of hardcoded colors.
Layout and scrolling
ratatui::layout::Layout divides the terminal into Rects (main area + footer; library browser splits horizontally). Scrolling uses a scroll_offset index and dynamic visible row counts so the selection stays in the viewport.
Related documentation
- Changelog
- romm-api — configuration and HTTP client
- romm-cli — scripting, automation, and
init/authworkflows - Architecture overview
- Metadata editing
- Troubleshooting authentication