What it is
Ratatui builds rich terminal user interfaces in Rust with an immediate-mode API, layout system and a library of widgets.
The entire UI is redrawn each frame from current state. Layouts split the area into constrained regions, and widgets render into them.
Installation
cargo add ratatui crosstermGetting started
The smallest useful thing you can do with it, and what each part means.
rust
use ratatui::{prelude::*, widgets::*};
fn draw(frame: &mut Frame, app: &App) {
let chunks = Layout::vertical([
Constraint::Length(3), // fixed header
Constraint::Min(0), // body takes the rest
Constraint::Length(1), // status line
])
.split(frame.area());
frame.render_widget(
Paragraph::new("Library").block(Block::bordered()),
chunks[0],
);
let items: Vec<ListItem> = app.books.iter()
.map(|b| ListItem::new(b.title.as_str()))
.collect();
frame.render_stateful_widget(
List::new(items)
.block(Block::bordered().title("Books"))
.highlight_symbol("> "),
chunks[1],
&mut app.list_state, // holds the selection
);
}Advanced usage
Where the library earns its place over a simpler alternative.
rust
fn main() -> Result<()> {
enable_raw_mode()?;
execute!(stdout(), EnterAlternateScreen)?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
// Restore the terminal even if the app panics — otherwise the user is
// left with an unusable shell.
let original = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let _ = disable_raw_mode();
let _ = execute!(stdout(), LeaveAlternateScreen);
original(info);
}));
let result = run(&mut terminal);
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
result
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- The terminal is broken after exit
- Raw mode was not disabled. Add the panic hook and ensure cleanup runs on every path.
- Rendering flickers
- Drawing more often than necessary. Redraw on events and a timer rather than in a tight loop.
Best practices
- Install a panic hook that restores the terminal; a crash otherwise leaves the shell unusable.
- Keep draw a pure function of state — no I/O inside the render path.
- Poll for events with a timeout so the UI redraws on a predictable cadence.
- Use stateful widgets for lists and tables so selection survives redraws.
Background
Why it exists, and what it was reacting to.
Ratatui is the community-maintained continuation of tui-rs after that project was archived. It powers a generation of Rust terminal tools including gitui and bottom.
