# `ExRatatui.Distributed`
[🔗](https://github.com/mcass19/ex_ratatui/blob/v0.7.1/lib/ex_ratatui/distributed.ex#L1)

Distribution-attach transport for `ExRatatui.App`.

Lets any connected BEAM node attach to a TUI running
on a remote node. The remote node runs the app's `mount/render/
handle_event` callbacks and sends widget lists as BEAM terms over
Erlang distribution. The local node renders those widgets on its own
terminal and forwards input events back.

## Quick start

On the app node (e.g. a Nerves device), add the Listener to your
supervision tree:

    children = [
      {MyApp.TUI, transport: :distributed}
    ]

On your local, connect and attach:

    iex --sname mynode --cookie mycookie -S mix
    iex> ExRatatui.Distributed.attach(:"app@nerves.local", MyApp.TUI)

The TUI takes over your terminal. Press the app's quit key (or
Ctrl-C twice) to disconnect and restore the terminal.

## How it works

1. `attach/2` connects to the remote node if not already connected.
2. A local Client process initializes the terminal.
3. An RPC call spawns a Server in `:distributed_server` mode on
   the remote node, pointing at the Client's pid — this process
   runs the app module and sends `{:ex_ratatui_draw, widgets}`
   messages directly to the Client over distribution.
4. The Client starts monitoring the remote Server and polling
   input events, forwarding them as `{:ex_ratatui_event, event}`
   / `{:ex_ratatui_resize, w, h}`.
5. When either side disconnects, monitors fire, both processes
   clean up, and the terminal is restored.

## Authentication

Delegated entirely to the Erlang distribution cookie. If you can
`Node.connect/1`, you can attach — same trust model as `iex --remsh`.

# `attach`

```elixir
@spec attach(node(), module(), keyword()) :: :ok | {:error, term()}
```

Attaches to a TUI app running on a remote node.

Connects to `node` (if not already connected), starts a remote
session for `mod`, and takes over the local terminal. Blocks until
the session ends (app stops, remote node disconnects, or the local
process is interrupted).

## Options

  * `:listener` — the registered name of the `Distributed.Listener`
    on the remote node (default: `ExRatatui.Distributed.Listener`).
  * `:poll_interval` — local event polling interval in ms (default: 16).
  * `:test_mode` — `{width, height}` for a headless test terminal. In this
    mode the local client does not poll the live terminal for input.

Returns `:ok` when the session ends normally, or `{:error, reason}`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
