# `nymph tui`

A live, read-only status monitor for **one** local daemon. It renders a
status header and a scrolling, level-filterable event log by polling the
daemon's loopback [introspection endpoint](/nymph/telemetry.md).

```bash
nymph tui
nymph tui --url http://127.0.0.1:9876 --interval 1
```

`tui` is the only subcommand the `nymph` binary has — running `nymph`
with no subcommand runs the daemon itself.

This is a different tool from [`lakeshore tui`](/cli/tui.md): that one is a
control-plane dashboard over **all** your workers and can act on them.
`nymph tui` watches a **single daemon on this host** and is strictly
read-only — it does not even install the daemon's tracing subscriber. It
is the tool you run next to a daemon you are debugging.

## Prerequisites

The daemon's introspection server must be on — `[introspect] enabled =
true` in `udf-daemon.toml`. See
[Telemetry and introspection](/nymph/telemetry.md). When the daemon is
unreachable the monitor renders a waiting banner and keeps retrying on
the interval; it never panics.

## Flags

| Flag                   | Default             | Meaning                                                                                                          |
| ---------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `--url <url>`          | derived from config | Introspection base URL. When omitted, derived as `http://<[introspect] bind>:<port>`, falling back to `http://127.0.0.1:9876`. |
| `--config <path>`      | config precedence   | Path to `udf-daemon.toml`, used **only** to derive the default `--url`. Same precedence as the daemon; also honours `LAKESHORED_CONFIG`. |
| `--interval <seconds>` | `2.0`               | Poll interval, clamped to a minimum of `0.1`. Each tick fetches `/status` and `/events` together.                  |

A config that fails to load is not fatal here — the TUI falls back to
built-in defaults so it still launches.

## Layout

Three stacked sections.

**1. Status header.** A connection banner plus the daemon's current
state, from [`GET /status`](/nymph/telemetry.md#get-status): `run-state`
(colour-coded), `version`, `queue`, `worker`, `uptime`, `last poll`,
`backoff`, and `in-flight`. The banner reads one of:

```text
● connected
◌ waiting for daemon at <url> (retrying…)
✗ daemon unreachable at <url> — <reason> (retrying every Ns)
```

Status fields keep rendering from the last good snapshot even while
unreachable, so a blip does not blank the context. Before the first
successful poll the header reads *"no status yet — the header populates
on the first successful poll"*.

**2. Events log.** The stream from
[`GET /events`](/nymph/telemetry.md#get-events), one row per event as
`HH:MM:SS  LEVEL  target  message`, with a `[+N fields — enter]` hint
when the selected event carries structured fields. The pane title shows
the active filter, `shown/capacity`, and whether you are in `⏵follow` or
`⏸manual` mode (plus `⏸ PAUSED` when polling is frozen).

Filtering is applied at **render** time against the events already
fetched, so switching levels is instant and never waits for a re-poll.

**3. Footer legend.** Always visible.

## Keybindings

The footer prints them verbatim:

```text
[e]rror [w]arn [i]nfo [d]ebug [t]race  [f]ollow  [space]pause  ↑/↓ scroll  [enter]expand  [q]uit
```

| Key                         | Action                                                                        |
| --------------------------- | ------------------------------------------------------------------------------- |
| `e` / `w` / `i` / `d` / `t` | Set the minimum severity shown. `e` = errors only; `t` = everything. Default `i`. |
| `f`                         | Toggle **follow** — snap to the newest event vs. stay put.                      |
| `Space`                     | Toggle **pause** — freeze polling and the view.                                 |
| `↑` / `↓` (or `k` / `j`)    | Scroll the event log. Any manual scroll drops follow mode; scrolling back to the bottom re-enables it. |
| `Enter`                     | Expand / collapse the selected event's structured fields.                       |
| `q` / `Esc` / `Ctrl-C`      | Quit.                                                                           |

If the log looks empty, you are probably filtered above the events that
exist — drop to `[d]ebug` or `[t]race`.

The terminal is restored on drop, including on panic, so a crash never
leaves your shell in raw mode.

## Read next

- [Telemetry and introspection](/nymph/telemetry.md) — the `/status` and
  `/events` endpoints this monitor renders, and how to enable them.
- [`lakeshore tui`](/cli/tui.md) — the control-plane dashboard over all
  workers. It acts on resources; this monitor only observes one daemon.
- [Daemon lifecycle](/nymph/daemon-lifecycle.md) — the remote equivalents
  (`lakeshore daemon list --watch`, `daemon show`).
