ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applications that run under OTP supervision — without blocking the BEAM.
Why?
I wanted to build terminal UIs in Elixir with the same ergonomics we’re used to from LiveView. The existing options in the ecosystem are either stale (ratatouille hasn’t been updated in years) or focused on CLI output rather than full-screen interactive apps. Meanwhile, ratatui is one of the most actively maintained TUI libraries in any language — so bridging it to Elixir felt like the right approach.
What it looks like
The ExRatatui.App behaviour uses LiveView-inspired callbacks — mount/1, render/2, handle_event/2, and handle_info/2:
defmodule MyCounter do
use ExRatatui.App
@impl true
def mount(_opts), do: {:ok, %{count: 0}}
@impl true
def render(state, frame) do
alias ExRatatui.Widgets.Paragraph
alias ExRatatui.Layout.Rect
widget = %Paragraph{text: "Count: #{state.count}"}
[{widget, %Rect{x: 0, y: 0, width: frame.width, height: frame.height}}]
end
@impl true
def handle_event(%ExRatatui.Event.Key{code: "up"}, state),
do: {:noreply, %{state | count: state.count + 1}}
def handle_event(%ExRatatui.Event.Key{code: "q"}, state),
do: {:stop, state}
def handle_event(_event, state),
do: {:noreply, state}
end
# Add to your supervision tree
children = [{MyCounter, []}]
Supervisor.start_link(children, strategy: :one_for_one)
Features
- 5 widgets (so far): Paragraph, Block, List, Table, Gauge — with Block composition on all of them
- Constraint-based layout engine — split areas by percentage, length, min, max, or ratio
- Non-blocking event polling — keyboard, mouse, and resize events on BEAM’s DirtyIo scheduler
- OTP-supervised apps via
ExRatatui.Appbehaviour - Full color support — 17 named colors, RGB, and 256-color indexed
- Headless test backend — render to an in-memory buffer for CI-friendly testing
- Precompiled NIF binaries for Linux, macOS, and Windows — no Rust toolchain needed
Installation
def deps do
[{:ex_ratatui, "~> 0.4"}]
end
Precompiled binaries are downloaded automatically. No Rust toolchain required.
Examples
The repo includes several examples you can run directly:
mix run examples/hello_world.exs— minimal paragraph displaymix run examples/counter.exs— interactive counter with key eventsmix run examples/counter_app.exs— counter using the App behaviourmix run examples/system_monitor.exs— system dashboard (CPU, memory, disk, network, BEAM stats)mix run examples/task_manager.exs— full task manager using all widgetsexamples/task_manager/— a complete supervised Ecto + SQLite CRUD app with a TUI interface
What’s next
More widgets (Tabs, Sparkline, BarChart, Scrollbar), rich text primitives (mixed-style spans within a single widget), custom widgets. Beyond that — a theming system, periodic handle_tick callbacks, viewport modes for inline rendering, single-binary distribution via Burrito, etc etc.
The precompiled NIFs already target ARM and RISC-V, so running TUI apps on Nerves devices over SSH should be a natural fit? I haven’t played with it yet!
The issues list is the place to go — ratatui has a huge surface area, so there’s a lot of room to grow.
Contributions are very welcome!!!
Links
I’d love to hear what people think and what you’d want to build with it.






















