raxol
OTP-native terminal framework for Elixir
{:raxol, "~> 2.3"}
Why OTP
Every capability below comes from the BEAM VM, not a library.
| Capability | Raxol | Ratatui | Bubble Tea | Textual | Ink |
|---|---|---|---|---|---|
| Crash isolation per component | yes | -- | -- | -- | -- |
| Hot code reload (no restart) | yes | -- | -- | -- | -- |
| Same app in terminal + browser | yes | -- | -- | partial | -- |
| Built-in SSH serving | yes | -- | via lib | -- | -- |
| AI agent runtime | yes | -- | -- | -- | -- |
| Distributed clustering (CRDTs) | yes | -- | -- | -- | -- |
| Time-travel debugging | yes | -- | -- | -- | -- |
Ratatui and Bubble Tea have excellent rendering and large ecosystems. Raxol's advantage is structural: crash isolation, hot reload, distribution, and SSH come from OTP, not application code.
Hello World
Every Raxol app follows The Elm Architecture:
init,
update,
view.
Here's a counter in 20 lines.
defmodule Counter do
use Raxol.Core.Runtime.Application
@impl true
def init(_ctx), do: %{count: 0}
@impl true
def update(:increment, model), do: {%{model | count: model.count + 1}, []}
def update(:decrement, model), do: {%{model | count: model.count - 1}, []}
def update(_, model), do: {model, []}
@impl true
def view(model) do
column style: %{padding: 1, gap: 1} do
[
text("Count: #{model.count}", style: [:bold]),
row style: %{gap: 1} do
[button("Increment", on_click: :increment), button("Decrement", on_click: :decrement)]
end
]
end
end
@impl true
def subscribe(_model), do: []
end
That counter works in a terminal. The same module renders in Phoenix LiveView. The same module serves over SSH. One codebase, three targets. See the full example with keyboard handling:
What's in the box
Crash Isolation
Wrap any widget in process_component/2. It crashes, it restarts. Your UI keeps running.
Hot Code Reload
Change your view/1 function, save. The running app updates. No restart.
AI Agent Runtime
Agents are TEA apps where input comes from LLMs. Supervised, crash-isolated, streaming.
SSH Serving
Raxol.SSH.serve(MyApp, port: 2222). Each connection gets its own supervised process.
LiveView Bridge
Same TEA app renders to terminal and Phoenix LiveView. One codebase.
Distributed Swarm
CRDTs, node monitoring, elections. Discovery via gossip, DNS, or Tailscale.
Time-Travel Debug
Snapshot every update/2 cycle. Step back, forward, jump, restore.
29 Widgets
Buttons, tables, trees, charts, sparklines. Flexbox + CSS Grid layout.
Performance
On Apple M1 Pro (Elixir 1.19 / OTP 27). 13% of the 60fps budget.
| What | Time |
|---|---|
| Full frame (create + fill + diff) | 2.1 ms |
| Tree diff (100 nodes) | 4 μs |
| Cell write | 0.97 μs |
| ANSI parse | 38 μs |
Standalone Packages
Use the full framework, or pick just the parts you need.
raxol_core
Behaviours, events, config, accessibility, plugins.
765 testsraxol_terminal
VT100/ANSI emulation, screen buffer, termbox2 NIF.
1,874 testsraxol_agent
AI agent framework. Supervised agents with LLM streaming.
131 testsraxol_sensor
Sensor fusion. Zero dependencies.
55 tests