Skip to main content

guides/transports.md

# Transports

PhoenixGenApiTui supports three transport modes. Each transport provides full session isolation: every connected client gets its own independent explorer state.

## Local (default)

Run directly in your IEx session. This is the default when no transport option is given.

```elixir
iex> PhoenixGenApiTui.ui()
# or explicitly
iex> PhoenixGenApiTui.explore()
```

Programmatic usage with options:

```elixir
PhoenixGenApiTui.explore(transport: :local)
```

## SSH

Serves the explorer over SSH. Multiple clients can connect simultaneously, each with an isolated session. Useful for inspecting PhoenixGenApi resources on a remote server.

```elixir
iex> PhoenixGenApiTui.explore(transport: :ssh)
```

Then connect from another terminal:

```bash
ssh phoenix@localhost -p 4546
# password: tui
```

Custom port:

```elixir
PhoenixGenApiTui.explore(transport: :ssh, port: 4000)
```

Custom credentials:

```elixir
PhoenixGenApiTui.explore(
  transport: :ssh,
  port: 4000,
  user_passwords: [{~c"admin", ~c"secret"}]
)
```

## Erlang Distribution

Starts a listener on the current node. Remote BEAM nodes attach over Erlang distribution — useful for headless servers or cross-architecture inspection.

```bash
# Terminal 1 — start the listener
iex --sname app --cookie demo -S mix
iex> PhoenixGenApiTui.explore(transport: :distributed)

# Terminal 2 — attach from another node
iex --sname local --cookie demo -S mix
iex> ExRatatui.Distributed.attach(:"app@hostname", PhoenixGenApiTui.App)
```

## Embedding in a Supervision Tree

For deployed applications, you can embed the SSH daemon or distribution listener directly in your supervision tree:

```elixir
# In your application.ex
def start(_type, _args) do
  state = PhoenixGenApiTui.Introspection.load()
  tui_state = PhoenixGenApiTui.State.new(state)

  children = [
    # ... your existing children ...
    {PhoenixGenApiTui.App,
     transport: :ssh,
     port: 2222,
     auto_host_key: true,
     auth_methods: ~c"password",
     user_passwords: [{~c"admin", ~c"secret"}],
     app_opts: [state: tui_state]}
  ]

  Supervisor.start_link(children, strategy: :one_for_one)
end
```