mcass19
ex_ratatui
Elixir

Elixir bindings for the Rust ratatui terminal UI library

Last updated Jul 4, 2026
100
Stars
8
Forks
1
Issues
0
Stars/day
Attention Score
46
Language breakdown
No language data available.
โ–ธ Files click to expand
README

ExRatatui

Elixir bindings for the Rust ratatui terminal UI library, via Rustler NIFs.
Build rich terminal UIs in Elixir with ratatui's layout engine, widget library, and styling system together with the BEAM superpowers.

Hex.pm Docs CI License


Features

  • 25 built-in widgets โ€” Paragraph, Block, List, Table, Gauge, BarChart, Chart, Canvas, Calendar, Tabs, TextInput, Textarea, Markdown, Image, BigText, CodeBlock, Viewport3D, and more
  • Constraint-based layout โ€” percentages, lengths, ratios, min/max, and fill constraints, with flex alignment and spacing
  • Rich styling โ€” named, RGB, and 256-indexed colors, text modifiers, per-span rich text, and a semantic theme palette
  • Two runtimes โ€” LiveView-style callbacks or an Elm-style reducer with commands and subscriptions, both OTP-supervised
  • Transport-agnostic apps โ€” the same module serves a local terminal, SSH clients, or remote BEAM nodes over Erlang distribution
  • Non-terminal rendering โ€” expose the rendered cell buffer to Phoenix LiveView, embedded framebuffers, and screenshot tools
  • Images in the terminal โ€” PNG / JPEG / GIF / WebP rendered via Kitty, Sixel, iTerm2, or halfblocks, adapting to the terminal at hand
  • 3D rendering โ€” software-rasterized or ray-traced scenes (Viewport3D) with meshes, lights, materials, a movable camera, and a scene-graph for articulated models, blitted into true-color cells
  • Syntax-highlighted code and big text โ€” CodeBlock with curated themes; oversized 8ร—8 pixel text for titles and banners
  • Full event handling โ€” non-blocking keyboard, mouse, resize, focus, and bracketed-paste events
  • Focus management โ€” a declarative focus ring with Tab cycling and mouse hit-testing for multi-panel apps
  • Custom widgets in pure Elixir โ€” compose primitives into reusable widgets via a protocol, no Rust required
  • First-class testing โ€” headless backend and event injection for CI-friendly assertions
  • Observability built in โ€” :telemetry events across runtime, render, and transports
  • Precompiled NIFs โ€” no Rust toolchain needed; event polling runs on the DirtyIo scheduler and never blocks the BEAM

Installation

Add ex_ratatui to the dependencies in mix.exs:

def deps do
  [
    {:ex_ratatui, "~> 0.11"}
  ]
end

Then fetch and compile:

mix deps.get && mix compile

A precompiled NIF binary for the host platform is downloaded automatically. The native library itself is loaded lazily on first use, so compiling a project that depends on ex_ratatui does not require the NIF to be loaded into the compiler VM.

Prerequisites

  • Elixir 1.17+
  • Erlang/OTP 26 โ€“ 29
Precompiled NIF binaries are available for Linux (x8664, aarch64, armv6/hf, riscv64), macOS (x8664, aarch64), and Windows (x8664), covering NIF ABI versions 2.16 (OTP 26) and 2.17 (OTP 27/28) โ€” no Rust toolchain needed. OTP 29 (NIF 2.18) has no precompiled binary yet, pending support upstream: compiling there requires the Rust toolchain and EXRATATUI_BUILD=true to build from source (see below).

To compile from source instead, install the Rust toolchain and set:

export EXRATATUIBUILD=true

Quick Start

alias ExRatatui.Layout.Rect
alias ExRatatui.Style
alias ExRatatui.Widgets.{Block, Paragraph}

ExRatatui.run(fn terminal -> {w, h} = ExRatatui.terminal_size()

paragraph = %Paragraph{ text: "Hello from ExRatatui!\n\nPress any key to exit.", style: %Style{fg: :green, modifiers: [:bold]}, alignment: :center, block: %Block{ title: " Hello World ", borders: [:all], border_type: :rounded, border_style: %Style{fg: :cyan} } }

ExRatatui.draw(terminal, [{paragraph, %Rect{x: 0, y: 0, width: w, height: h}}])

# Wait for a keypress, then exit ExRatatui.pollevent(60000) end)

Try the examples catalog for more โ€” every widget has a focused, copyable demo, e.g. mix run examples/basics/hello_world.exs.

New here? The Getting Started guide builds a supervised todo app from mix new to a working TUI.

Runtimes and Transports

ExRatatui offers two ways to structure a supervised app and several ways to serve it โ€” every combination works, and switching transport doesn't change the app module.

Guides

| Guide | Description | |-------|-------------| | Getting Started | Walk-through from mix new to a supervised TUI โ€” the place to start | | Building UIs | Widgets, layout, styles, rich text, and events โ€” everything for render/2 | | Custom Widgets | Compose primitives into reusable widgets via the ExRatatui.Widget protocol | | Images | Image rendering across terminals and transports โ€” protocols, resizing, telemetry | | 3D Rendering | Lit 3D scenes with Viewport3D โ€” meshes, camera, render modes, and pipelines | | Paste and Clipboard | Bracketed paste behaviour, batch-insert helpers, and an OSC 52 copy snippet | | Callback Runtime | OTP-supervised apps with mount, render, handleevent, and handle_info callbacks | | Reducer Runtime | Elm-style apps with init, update, subscriptions, commands, and runtime inspection | | State Machine Patterns | Multi-screen apps, modals, and conditional UI without the tangle | | Transports | Canonical feature matrix โ€” what works where across Local / Session / SSH / Distributed / CellSession | | Running TUIs over SSH | Serve any app as a remote TUI over SSH, standalone or under nervesssh | | Running TUIs over Erlang Distribution | Drive a TUI from a remote BEAM node with zero NIF on the app side | | Custom Transports | Plug in a custom transport (TCP, Livebook, WebSocket) via the ExRatatui.Transport behaviour | | Rendering to Non-Terminal Surfaces | Use ExRatatui.CellSession to expose the rendered cell buffer to LiveView, framebuffers, screenshot tools, and other non-ANSI consumers | | Architecture | The NIF bridge and the per-transport process trees | | Testing | Headless backend, testmode, injectevent, and assertion patterns | | Debugging | Runtime.snapshot, tracing, buffer inspection, and common errors | | Performance | Render-loop tuning, render?: false, large trees, async effects | | Telemetry | :telemetry events for runtime, render, transport, and session โ€” logging, metrics, OpenTelemetry | | Widgets Cheatsheet | One-page reference with every struct and its key fields |

How It Works

ExRatatui bridges Elixir and Rust through Rustler NIFs: widget structs are encoded across the NIF boundary and decoded into ratatui types for rendering, while terminal events are polled on BEAM's DirtyIo scheduler so nothing blocks Elixir processes. Every transport builds on the same supervised Server process, with full session isolation per connected client.

The Architecture guide has the full picture โ€” the NIF bridge and the per-transport process trees.

Ecosystem

Built with ExRatatui

  • ashtui โ€” Interactive terminal explorer for Ash domains, resources, attributes, actions, and more.
  • bbtui โ€” Terminal-based dashboard for Beam Bots robots.
  • switchyard โ€” Full-featured reducer runtime workbench exercising command batching, async effects, subscription reconciliation, runtime snapshots, distributed attach, and row-scrolled WidgetList.
  • caudata โ€” Zero-config multi-server log streamer aggregating real-time logs from remote Linux hosts over native SSH, with Docker/Systemd/Launchd discovery and live CPU, RAM, and disk metrics.
  • ex_athena โ€” Provider-agnostic AI agent loop with a terminal chat TUI (via mix athena.chat), supporting Ollama, OpenAI-compatible, llama.cpp, and Anthropic backends.
  • beamcore โ€” Terminal coding agent where each instance is a distributed OTP node, with in-VM code execution, persistent memory, mesh RPC, live runtime attachment, and multi-provider LLM support.
  • extop โ€” Live Linux system monitor with real-time CPU, GPU, memory, disk, and network charts alongside a sortable, filterable process table with signal management.
  • phoenixgenapitui โ€” Terminal-based explorer for PhoenixGenApi applications, with runtime inspection of services, call flows, cluster topology, health, and rate limits โ€” no database connection required.
  • nervesexratatuiexample โ€” Example Nerves project with two TUIs (system monitor and LED control) on embedded hardware, reachable over SSH subsystems and Erlang distribution.
  • phoenixexratatuiexample โ€” Example Phoenix project with a TUI served over SSH and Erlang distribution alongside a public LiveView chat room, sharing PubSub between the browser and the terminal.
  • ... yours? Open a PR! Plenty of ideas to explore in awesome-ratatui.

Contributing

Contributions are welcome! See CONTRIBUTING.md for development setup and PR guidelines.

Acknowledgements

ExRatatui is undeniably inspired by ratatui. Having such a great terminal UI library in Rust was the motivation to bring the same experience to the Elixir world and combine the best of both worlds. Special thanks to the great community behind ratatui.

The ExRatatui logo adapts the ratatui logo designed by Pavel Fomchenkov, with the Elixir drop and exratatui wordmark added by Malena Merlina.

License

MIT โ€” see LICENSE for details.

๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท mcass19/ex_ratatui ยท Updated daily from GitHub