Raxol Skill
Elixir TEA framework for terminal UIs + AI agent orchestration. The same TEA model
runs in the terminal, browser (LiveView), SSH, and as MCP tools/resources. OTP
provides supervision, crash isolation, and hot reload.
Raxol v2.6.1 targets Elixir 1.20 / OTP 29 and supports 1.17+. The repo holds 18 Mix
projects: 17 under packages/ plus the root raxol package. Both numbers are correct
and they count different things, so a packages/ listing showing 17 is not stale.
The terminal emulator + termbox2 NIF were extracted from the root raxol package into
raxol_terminal. raxol is now the full-framework package, and it is a plain Mix
project rather than a Mix umbrella (the root mix.exs has no apps_path): it depends on
raxol_core, raxol_terminal, raxol_sensor, raxol_mcp, raxol_liveview, and
raxol_plugin. The 15 packages this skill covers:
raxol_core -- TEA runtime, buffer/rendering, events, directives, telemetry
raxol -- full-framework package at the REPO ROOT, not under packages/
(depends on core, terminal, sensor, mcp, liveview, plugin)
raxol_terminal -- VT/ANSI emulator, screen buffers, driver, input, sessions,
termbox2 NIF (extracted from raxol in v2.6)
raxol_agent -- agent framework: TEA/Process agents, turn driver, memory,
self-improving skills, journal, backends, coding harness, teams
raxol_mcp -- MCP server/client: tool auto-derivation, focus lens, resources
raxol_liveview -- Phoenix LiveView bridge (buffer -> HTML, a11y)
raxol_plugin -- plugin SDK (mix raxol.gen.plugin)
raxol_sensor -- sensor fusion for Process agents
raxol_gateway -- unified messaging gateway: one daemon, many chat platforms via a
shared adapter contract, process-per-chat sessions, DM pairing auth
raxol_speech -- speech surface: TTS reads a11y announcements, STT captures voice
input via Bumblebee/Whisper and injects events
raxol_telegram -- Telegram surface: renders TEA apps as monospace code blocks with
inline-keyboard navigation
raxol_watch -- Watch notification bridge: glanceable summaries to Apple Watch (APNS)
and Wear OS (FCM); tap actions route back as events
raxol_agent_client_protocol -- Elixir/OTP implementation of ACP (Agent CLIENT
Protocol): JSON-RPC 2.0 between editors and coding agents, pluggable transports
raxol_cli -- the raxol command: interactive AI agent + toolkit as a self-contained
binary via npm wrapper
raxol_console -- console runtime: boots an ACP Console agent package onto the gateway stack
Payments / the Agent COMMERCE Protocol (raxol_payments, raxol_earn) and the Symphony
orchestrator (raxol_symphony) have their own skills -- see below. Do not confuse
raxol_earn (Agent Commerce Protocol, payments) with raxol_agent_client_protocol
(Agent Client Protocol, in scope here).
What You Get
- TEA agent and Process agent patterns with lifecycle examples
- Turn driver + memory stack + self-improving skills (v2.6)
- Workflow engine: graph DSL, checkpointing, human-in-the-loop, saga rollback
- AI backends (HTTP, Mock, native ClaudeCode/Cursor, OpenRouter) + harness selection
- MCP server (auto-derive tools from the widget tree) and MCP client
- LiveView surface (buffer -> HTML, themes, accessibility)
- Multi-agent orchestration (teams, cockpit, message protocol)
- Agent skills / procedural memory + the journal (blast radius, spend gate)
- Coding agent harness (
mix raxol.code, mix raxol.p) with tool classification
- Chat surfaces via the gateway (Telegram, Discord, email) + speech (TTS/STT)
- Agent Client Protocol: editor <-> agent JSON-RPC (distinct from ACP payments)
- Headless sessions and agent testing patterns (unit, integration, E2E)
Two Agent Models
|
TEA Agent (use Raxol.Agent) |
Process Agent (use Raxol.Agent.UseProcess) |
| Loop |
Message-driven (update/2) |
Tick-driven (observe/think/act) |
| Rendering |
Optional view/1 |
Headless only |
| Input |
Messages from agents, commands, MCP |
Events buffer, directives |
| Best for |
Agents with UI, reactive workflows |
Autonomous background agents |
| Crash recovery |
OTP restart, fresh init/1 |
context_snapshot + restore_context |
| AI backend |
Manual (call in async commands) |
Built-in via Strategy |
For a full LLM chat turn (memory + skills + user model + tool loop) use the
Raxol.Agent.Turn driver -- see agents/turn-memory.md.
See also
raxol-payments -- agentic commerce: Xochi/Riddler/ACP, agent wallets, privacy tiers
raxol-symphony -- tracker-driven coding-agent orchestrator (Symphony)
droo-stack -- general Elixir patterns (pipes, pattern matching, ExUnit)
design-ux -- TUI design principles (terminal layout, box-drawing, density)
claude-api -- Anthropic SDK integration in Elixir
Reading Guide
| Task |
File |
| Build a TEA agent + messaging |
agents/tea-agent.md |
| Build an autonomous agent |
agents/process-agent.md |
| Full LLM turn: memory + skills |
agents/turn-memory.md |
| Agent skills / procedural memory |
agents/skills-procedural-memory.md |
| Coding agent harness (raxol.code) |
agents/coding-harness.md |
| Reusable actions / LLM tools |
agents/actions-pipelines.md |
| Multi-agent teams / cockpit |
agents/teams-orchestrator.md |
| Orchestrate steps as a graph |
workflow/graph.md |
| AI backend + harness selection |
ai/backends.md |
| Consume external MCP servers |
ai/mcp-client.md |
| Editor<->agent ACP (Zed, not payments) |
ai/agent-client-protocol.md |
| Expose your app as MCP tools |
mcp/server.md |
| Render a TEA app in LiveView |
surfaces/liveview.md |
| Chat surfaces: gateway / Telegram |
surfaces/messaging.md |
| Speech surface (TTS/STT) |
surfaces/speech.md |
| Headless sessions + MCP tools |
headless/sessions.md |
| Testing agents and actions |
testing/agent-testing.md |
Message Protocol
All TEA agents receive these in update/2. Defined once here, referenced
from other files.
# Async message from another agent
{:agent_message, from_id, payload}
# Sync call -- MUST reply with send(pid, {:agent_reply, ref, reply})
{:call, caller_pid, ref, message}
# Team broadcast
{:team_broadcast, team_id, payload}
# Async command / directive results
{:command_result, result}
{:command_result, {:shell_result, %{output: string, exit_status: int}}}
{:command_result, {:action_result, module, result_map}}
{:command_result, {:action_error, module, reason}}
{:command_result, {:pipeline_result, result_map}}
{:command_result, {:pipeline_error, step_module, reason}}
Key Conventions
- All agents auto-register in
Raxol.Agent.Registry by :id
- Always return
{model, command} from update/2, never bare model
view/1 returning nil = headless (no rendering overhead)
- Effects are struct-based
Directives (v2.6): Raxol.Core.Runtime.Directive
(stop/1, schedule/2, spawn_task/1) and Raxol.Agent.Directive
(async/1, shell/2, send_agent/2). The use Raxol.Agent helpers wrap these.
- Session agents register as
agent_id, Process agents as {:process, agent_id},
MCP clients as {:mcp_client, name}
- Agent package:
packages/raxol_agent/
Common Pitfalls
- Wrong update/2 return -- must return
{model, Command.none()} not bare model
- Forgetting call reply --
{:call, pid, ref, msg} requires send(pid, {:agent_reply, ref, reply}); caller blocks with timeout
- Mixing agent models -- TEA callbacks and ProcessBehaviour callbacks are separate behaviours
- Sync call deadlocks -- Agent A calls B, B calls A = deadlock. Break cycles with async
send_agent/2
- String vs atom keys -- Headless
send_key uses atoms for special keys (:tab), strings for characters ("q")
- Real backends in tests -- always use
Backend.Mock, never HTTP
Design Context
Raxol treats each rendering surface (terminal, web, SSH, MCP) as a functor
from the TEA model. Same update/2, same model, different projections. In v2.6
MCP is a first-class surface (raxol_mcp): widgets auto-export tools via the
Raxol.MCP.ToolProvider behaviour, model state is exposed via ResourceProvider,
and FocusLens filters tools by attention. When building features, consider how
they surface as MCP tools -- see mcp/server.md.
1---2name: raxol3description: Raxol terminal framework for TUI apps and AI agents in Elixir (v2.6.1; 17 packages under packages/ plus the root raxol package). TRIGGER when: code imports Raxol modules (Raxol.Agent, Raxol.Core, Raxol.MCP, Raxol.LiveView, Raxol.Workflow, Raxol.Headless, Raxol.Agent.Harness, Raxol.Agent.Skills, Raxol.Agent.Journal, Raxol.Gateway, Raxol.Telegram, Raxol.Watch, Raxol.Speech, Raxol.Agent.ClientProtocol, Raxol.AgentClientProtocol), mix.exs lists :raxol / :raxol_agent / :raxol_core / :raxol_mcp / :raxol_terminal / :raxol_gateway / :raxol_telegram / :raxol_watch / :raxol_speech / :raxol_agent_client_protocol as a dependency, commands "mix raxol.code" or "mix raxol.p", user asks about building TUI apps or AI agents with Raxol, agent memory/self-improvement, agent skills / procedural memory, the coding agent harness, the workflow engine, blast radius / spend gate, or Raxol headless/MCP tools. DO NOT TRIGGER when: general Elixir patterns (use droo-stack skill), Claude API / Anthropic SDK usage (use claude-api skill), a4---56# Raxol Skill78Elixir TEA framework for terminal UIs + AI agent orchestration. The same TEA model9runs in the terminal, browser (LiveView), SSH, and as MCP tools/resources. OTP10provides supervision, crash isolation, and hot reload.1112Raxol v2.6.1 targets Elixir 1.20 / OTP 29 and supports 1.17+. The repo holds 18 Mix13projects: 17 under `packages/` plus the root `raxol` package. Both numbers are correct14and they count different things, so a `packages/` listing showing 17 is not stale.1516The terminal emulator + termbox2 NIF were extracted from the root `raxol` package into17`raxol_terminal`. `raxol` is now the full-framework package, and it is a plain Mix18project rather than a Mix umbrella (the root `mix.exs` has no `apps_path`): it depends on19`raxol_core`, `raxol_terminal`, `raxol_sensor`, `raxol_mcp`, `raxol_liveview`, and20`raxol_plugin`. The 15 packages this skill covers:2122- `raxol_core` -- TEA runtime, buffer/rendering, events, directives, telemetry23- `raxol` -- full-framework package at the REPO ROOT, not under `packages/`24 (depends on core, terminal, sensor, mcp, liveview, plugin)25- `raxol_terminal` -- VT/ANSI emulator, screen buffers, driver, input, sessions,26 termbox2 NIF (extracted from `raxol` in v2.6)27- `raxol_agent` -- agent framework: TEA/Process agents, turn driver, memory,28 self-improving skills, journal, backends, coding harness, teams29- `raxol_mcp` -- MCP server/client: tool auto-derivation, focus lens, resources30- `raxol_liveview` -- Phoenix LiveView bridge (buffer -> HTML, a11y)31- `raxol_plugin` -- plugin SDK (`mix raxol.gen.plugin`)32- `raxol_sensor` -- sensor fusion for Process agents33- `raxol_gateway` -- unified messaging gateway: one daemon, many chat platforms via a34 shared adapter contract, process-per-chat sessions, DM pairing auth35- `raxol_speech` -- speech surface: TTS reads a11y announcements, STT captures voice36 input via Bumblebee/Whisper and injects events37- `raxol_telegram` -- Telegram surface: renders TEA apps as monospace code blocks with38 inline-keyboard navigation39- `raxol_watch` -- Watch notification bridge: glanceable summaries to Apple Watch (APNS)40 and Wear OS (FCM); tap actions route back as events41- `raxol_agent_client_protocol` -- Elixir/OTP implementation of ACP (Agent CLIENT42 Protocol): JSON-RPC 2.0 between editors and coding agents, pluggable transports43- `raxol_cli` -- the `raxol` command: interactive AI agent + toolkit as a self-contained44 binary via npm wrapper45- `raxol_console` -- console runtime: boots an ACP Console agent package onto the gateway stack4647Payments / the Agent COMMERCE Protocol (`raxol_payments`, `raxol_earn`) and the Symphony48orchestrator (`raxol_symphony`) have their own skills -- see below. Do not confuse49`raxol_earn` (Agent Commerce Protocol, payments) with `raxol_agent_client_protocol`50(Agent Client Protocol, in scope here).5152## What You Get5354- TEA agent and Process agent patterns with lifecycle examples55- Turn driver + memory stack + self-improving skills (v2.6)56- Workflow engine: graph DSL, checkpointing, human-in-the-loop, saga rollback57- AI backends (HTTP, Mock, native ClaudeCode/Cursor, OpenRouter) + harness selection58- MCP server (auto-derive tools from the widget tree) and MCP client59- LiveView surface (buffer -> HTML, themes, accessibility)60- Multi-agent orchestration (teams, cockpit, message protocol)61- Agent skills / procedural memory + the journal (blast radius, spend gate)62- Coding agent harness (`mix raxol.code`, `mix raxol.p`) with tool classification63- Chat surfaces via the gateway (Telegram, Discord, email) + speech (TTS/STT)64- Agent Client Protocol: editor <-> agent JSON-RPC (distinct from ACP payments)65- Headless sessions and agent testing patterns (unit, integration, E2E)6667## Two Agent Models6869| | TEA Agent (`use Raxol.Agent`) | Process Agent (`use Raxol.Agent.UseProcess`) |70| -------------- | ----------------------------------- | -------------------------------------------- |71| Loop | Message-driven (`update/2`) | Tick-driven (observe/think/act) |72| Rendering | Optional `view/1` | Headless only |73| Input | Messages from agents, commands, MCP | Events buffer, directives |74| Best for | Agents with UI, reactive workflows | Autonomous background agents |75| Crash recovery | OTP restart, fresh `init/1` | `context_snapshot` + `restore_context` |76| AI backend | Manual (call in async commands) | Built-in via Strategy |7778For a full LLM chat turn (memory + skills + user model + tool loop) use the79`Raxol.Agent.Turn` driver -- see `agents/turn-memory.md`.8081## See also8283- `raxol-payments` -- agentic commerce: Xochi/Riddler/ACP, agent wallets, privacy tiers84- `raxol-symphony` -- tracker-driven coding-agent orchestrator (Symphony)85- `droo-stack` -- general Elixir patterns (pipes, pattern matching, ExUnit)86- `design-ux` -- TUI design principles (terminal layout, box-drawing, density)87- `claude-api` -- Anthropic SDK integration in Elixir8889## Reading Guide9091| Task | File |92| --------------------------------- | ------------------------------ |93| Build a TEA agent + messaging | `agents/tea-agent.md` |94| Build an autonomous agent | `agents/process-agent.md` |95| Full LLM turn: memory + skills | `agents/turn-memory.md` |96| Agent skills / procedural memory | `agents/skills-procedural-memory.md` |97| Coding agent harness (raxol.code) | `agents/coding-harness.md` |98| Reusable actions / LLM tools | `agents/actions-pipelines.md` |99| Multi-agent teams / cockpit | `agents/teams-orchestrator.md` |100| Orchestrate steps as a graph | `workflow/graph.md` |101| AI backend + harness selection | `ai/backends.md` |102| Consume external MCP servers | `ai/mcp-client.md` |103| Editor<->agent ACP (Zed, not payments) | `ai/agent-client-protocol.md` |104| Expose your app as MCP tools | `mcp/server.md` |105| Render a TEA app in LiveView | `surfaces/liveview.md` |106| Chat surfaces: gateway / Telegram | `surfaces/messaging.md` |107| Speech surface (TTS/STT) | `surfaces/speech.md` |108| Headless sessions + MCP tools | `headless/sessions.md` |109| Testing agents and actions | `testing/agent-testing.md` |110111## Message Protocol112113All TEA agents receive these in `update/2`. Defined once here, referenced114from other files.115116```elixir117# Async message from another agent118{:agent_message, from_id, payload}119120# Sync call -- MUST reply with send(pid, {:agent_reply, ref, reply})121{:call, caller_pid, ref, message}122123# Team broadcast124{:team_broadcast, team_id, payload}125126# Async command / directive results127{:command_result, result}128{:command_result, {:shell_result, %{output: string, exit_status: int}}}129{:command_result, {:action_result, module, result_map}}130{:command_result, {:action_error, module, reason}}131{:command_result, {:pipeline_result, result_map}}132{:command_result, {:pipeline_error, step_module, reason}}133```134135## Key Conventions136137- All agents auto-register in `Raxol.Agent.Registry` by `:id`138- Always return `{model, command}` from `update/2`, never bare `model`139- `view/1` returning `nil` = headless (no rendering overhead)140- Effects are struct-based `Directive`s (v2.6): `Raxol.Core.Runtime.Directive`141 (`stop/1`, `schedule/2`, `spawn_task/1`) and `Raxol.Agent.Directive`142 (`async/1`, `shell/2`, `send_agent/2`). The `use Raxol.Agent` helpers wrap these.143- Session agents register as `agent_id`, Process agents as `{:process, agent_id}`,144 MCP clients as `{:mcp_client, name}`145- Agent package: `packages/raxol_agent/`146147## Common Pitfalls1481491. **Wrong update/2 return** -- must return `{model, Command.none()}` not bare `model`1502. **Forgetting call reply** -- `{:call, pid, ref, msg}` requires `send(pid, {:agent_reply, ref, reply})`; caller blocks with timeout1513. **Mixing agent models** -- TEA callbacks and ProcessBehaviour callbacks are separate behaviours1524. **Sync call deadlocks** -- Agent A calls B, B calls A = deadlock. Break cycles with async `send_agent/2`1535. **String vs atom keys** -- Headless `send_key` uses atoms for special keys (`:tab`), strings for characters (`"q"`)1546. **Real backends in tests** -- always use `Backend.Mock`, never HTTP155156## Design Context157158Raxol treats each rendering surface (terminal, web, SSH, MCP) as a functor159from the TEA model. Same `update/2`, same model, different projections. In v2.6160MCP is a first-class surface (`raxol_mcp`): widgets auto-export tools via the161`Raxol.MCP.ToolProvider` behaviour, model state is exposed via `ResourceProvider`,162and `FocusLens` filters tools by attention. When building features, consider how163they surface as MCP tools -- see `mcp/server.md`.