# elelem-ratatui

> Replaces elelem's line-based terminal with a full-screen ratatui interface, drawn by a small Rust binary that talks to Ruby over JSON lines. Early, and not published to RubyGems.

Maturity: alpha.  Source: https://src.mokhan.ca/elelem/ratatui/


`elelem-ratatui` is an early experiment: a full-screen terminal UI for
elelem, written in Rust with [ratatui](https://ratatui.rs). The screen has
a log pane for replies, thinking, and tool calls, and an input box below
it. It is basic, with no scrolling and minimal line editing, and it is not
on RubyGems; build it from source.

## Install

You need Ruby 4.0, Bundler, and a Rust toolchain with `cargo`.

```bash
git clone https://git.mokhan.ca/elelem/ratatui.git
cd ratatui
bin/setup
```

`bin/setup` runs `bundle install`, then `bundle exec rake compile`. The
compile task runs `cargo build --release` in `rust/` and copies the binary
to `ext/elelem/ratatui/native/elelem-ratatui`.

To install it as a gem instead, build the gem from the clone. `gem install`
runs the same Rust build:

```bash
gem build elelem-ratatui.gemspec
gem install ./elelem-ratatui-0.1.0.gem
```

## Use

From the clone:

```bash
bin/run chat -p ollama
```

Installed as a gem:

```bash
elelem-ratatui chat -p anthropic
```

`elelem-ratatui` takes the same commands and options as `elelem` (`chat`,
`ask`, `files`, `-p`, `--model`, `--system-prompt`) and loads
`elelem-builtins` if it is installed. The difference is the screen.

| Key | Action |
|---|---|
| any character | type into the input box |
| Backspace | delete the last character |
| Enter | send the input |
| Ctrl+D | quit, at a prompt |
| Ctrl+C | close the UI, when no prompt is pending |

The input box title shows the pending prompt, including permission
questions from tools. The log pane's title reads `elelem (waiting…)`
while a request to the model is in flight.

## How it works

Loading `elelem/ratatui` replaces elelem's input and output with 2 small
Ruby classes. When the session is built, they start the Rust binary and
keep it running until elelem exits.

The 2 processes talk over the binary's stdin and stdout, one JSON object
per line. The binary draws on `/dev/tty`, so stdout stays free for the
protocol.

Ruby to Rust:

```json
{"type":"say","text":"Done.","as":"markdown"}
{"type":"print","text":"partial text"}
{"type":"thinking","text":"Reading the file first."}
{"type":"doing","header":"+ read({\"path\":\"README.md\"})"}
{"type":"waiting"}
{"type":"ask","prompt":"> "}
```

Rust to Ruby, once per `ask`:

```json
{"line":"fix the failing test"}
{"line":null}
```

`null` means the user pressed Ctrl+D, which ends the session. The binary
also understands `oops` and `display_file` events, but the Ruby side does
not send them. A line it cannot parse is reported on stderr and ignored.

## Limitations

- The log pane does not scroll. Rows are drawn from the top, so once the
  pane is full, new output lands below the visible area.
- Line editing is limited to typing and Backspace. There is no cursor
  movement, history, or tab completion.
- At a prompt, Ctrl+C types a `c`. Use Ctrl+D to quit.
- The `as` field is ignored, so errors look like any other text.
- Needs `/dev/tty`, so it will not run on Windows.
- `ask` behaves as it does in `elelem`; the full-screen UI is only used by
  `chat`.
- The repository has no specs yet.

## Development

```bash
git clone https://git.mokhan.ca/elelem/ratatui.git
cd ratatui
bin/setup
bundle exec rake compile
bin/run
```

Run `bundle exec rake compile` after changing anything in `rust/`. The
development Gemfile includes `elelem-builtins`, `elelem-llama`, and
`elelem-ollama`.


Canonical: https://elelem.sh/plugins/ratatui/

