Build terminal UIs in Rust with Ratatui. Use when creating TUI applications, immediate-mode rendering, high-performance terminal interfaces, or production Rust CLIs.
Scanned 5/28/2026
Install to Claude Code
npx -y skills add FlorianBruniaux/ccboard --skill ratatui --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ratatui?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/florianbruniaux-ratatui)More formats (shields.io, HTML) on the badges page.
---
name: ratatui
description: Build terminal UIs in Rust with Ratatui. Use when creating TUI applications, immediate-mode rendering, high-performance terminal interfaces, or production Rust CLIs.
effort: medium
allowed-tools: Read, Write, Edit, Bash, Grep
---
# Ratatui (Rust TUI)
Immediate-mode terminal UI framework for Rust using Crossterm backend.
## When to Use
- Creating a new TUI application from scratch in Rust
- Adding an interactive terminal interface to an existing CLI tool
- Implementing tabbed navigation, lists, tables, or charts in the terminal
- High-performance terminal rendering where latency matters (e.g., monitoring dashboards)
**Keywords**: TUI, terminal UI, ratatui, crossterm, interactive CLI, dashboard, ncurses alternative
## Workflow
1. **Add dependencies** to `Cargo.toml` (ratatui + crossterm)
2. **Define App state struct** — holds all mutable data (selected index, input buffer, etc.)
3. **Initialize terminal** — enable raw mode, enter alternate screen
4. **Main event loop** — `terminal.draw(|f| ui(f, &app))` + `event::poll` + key handler
5. **Build UI function** — `Layout::split` → assign chunks → `render_widget` per chunk
6. **Teardown** — disable raw mode, leave alternate screen on exit or panic
## Dependencies
```toml
[dependencies]
ratatui = "0.28"
crossterm = "0.28"
```
## Basic Application
```rust
use crossterm::{
event::{self, Event, KeyCode},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{backend::CrosstermBackend, widgets::{Block, Borders, Paragraph}, Terminal};
use std::io;
struct App {
counter: i32,
}
impl App {
fn new() -> App {
App { counter: 0 }
}
fn on_key(&mut self, key: KeyCode) {
match key {
KeyCode::Up => self.counter += 1,
KeyCode::Down => self.counter -= 1,
_ => {}
}
}
}
fn main() -> Result<(), io::Error> {
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let mut app = App::new();
loop {
terminal.draw(|f| {
let block = Block::default().title("Counter").borders(Borders::ALL);
let paragraph = Paragraph::new(format!("Count: {}", app.counter)).block(block);
f.render_widget(paragraph, f.area());
})?;
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => break,
code => app.on_key(code),
}
}
}
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
Ok(())
}
```
## Event Loop with Polling
```rust
use std::time::Duration;
fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<()> {
loop {
terminal.draw(|f| ui(f, app))?;
if event::poll(Duration::from_millis(100))? {
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => return Ok(()),
KeyCode::Up => app.increment(),
KeyCode::Down => app.decrement(),
_ => {}
}
}
}
}
}
```
## Layout
```rust
use ratatui::layout::{Constraint, Direction, Layout};
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(3), // Fixed height
Constraint::Min(0), // Fill remaining
Constraint::Length(1), // Status bar
])
.split(f.area());
```
## References
- **Widgets**: See [references/widgets.md](references/widgets.md) for List, Table, Paragraph, Gauge
- **Best Practices**: See [references/best-practices.md](references/best-practices.md) for keyboard, accessibility, performance
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!