Skip to content

feat: read-only Session Dashboard (agent-tty dashboard)#113

Merged
ThomasK33 merged 1 commit into
mainfrom
feat/session-dashboard
Jun 2, 2026
Merged

feat: read-only Session Dashboard (agent-tty dashboard)#113
ThomasK33 merged 1 commit into
mainfrom
feat/session-dashboard

Conversation

@ThomasK33
Copy link
Copy Markdown
Member

What

Adds agent-tty dashboard: a read-only, interactive Session Dashboard — a master-detail Ink TUI that lists your Sessions and shows a continuously-updated Live View of the selected one. Watch what your agents are doing in their shells, e.g. in a tmux split.

The Live View is produced by Event Log Follow: it tails the Session's append-only events.jsonl and replays it through the in-process libghostty-vt renderer (replayTosnapshot). It reads the Event Log as the source of truth and never queries the live host, so it can't disturb a running Session and behaves identically for live and finished Sessions (ADR 0006).

Closes #109.

Highlights

  • Master-detail with a Tab-toggled focus model: list focused → ↑/↓ j/k select; Live View focused → ↑/↓ h/j/k/l pan.
  • Scope: defaults to Active Sessions (mirrors list); a toggles all (Active + Terminal, excluding destroyed); --all sets the initial scope; --session <id> preselects.
  • Sizing: 1:1 clip-top-left + pan + truncation indicators, letterbox for smaller screens, and a lossy block-glyph overview (z). Never distorts/reflows; never resizes the Session.
  • Lifecycle: pin-selected-through-exit (final screen frozen + exit badge); a collected Event Log surfaces “Event Log collected” and drops on the next refresh.
  • Renderer: requires the optional libghostty-vt (no ghostty-web fallback). Fails fast with an actionable message when absent, and doctor now reports a dashboard readiness capability.
  • Interactive-only: no --json (a deliberate, documented deviation — list --json still covers machine-readable listing); fails fast on a non-interactive terminal.

Four deep modules (unit-tested)

  • SessionEventSource + EventLogTailSource — byte-offset tail seam: partial lines, multibyte split, truncation/rewrite, not-yet-created vs collected, ENOENT offset reset.
  • LiveViewProjection — pure clip / pan (clamped) / letterbox / block-glyph overview, cursor flag, cells-or-text fallback.
  • LiveViewFollower — accumulate → replayTosnapshot, burst coalescing, pin-on-exit freeze + badge, collected precedence, bounded replay (trims applied events).
  • RendererReadinesslibghostty-vt probe → actionable error + the dashboard doctor capability (skips, not fails, when the optional renderer is absent).

Thin glue: session-list scope adapter (reuses listSessions), the Ink shell, and the dashboard CLI command + non-TTY guard.

Build / deps

react + ink moved to dependencies; @types/react added as a devDep; jsx: react-jsx added to tsconfig. @coder/libghostty-vt-node remains an optional dependency. The gitignored throwaway proto/ is removed.

Verification

  • Byte-identical to agent-tty snapshot (cells, visibleLines, cursor, alt-screen) via a hermetic event-log cross-check.
  • Live PTY run: boots, lists sessions, renders the Live View with the exit badge + clip indicator, overview block glyphs, focus/keys, and a clean quit.
  • Gates: format, lint, typecheck, 1190 unit tests, and build — all green. (Integration/e2e create live hosts, so they run in CI rather than locally.)
  • A 9-angle review pass (with adversarial verification) surfaced and fixed 6 issues in the new code: unhandled-rejection resilience (including the dispose-mid-render teardown race), pan clamping, bounded events array, list scroll window, refresh in-flight guard, and the ENOENT offset reset.

Out of scope / follow-up

Input take-over, multi-session grid, busy/idle activity, scrollback/replay-scrubbing, a streaming subscribe RPC, and pixel zoom are deliberately deferred (see the PRD). Wide-character (CJK/emoji) cell alignment is a pre-existing limitation of the shared SnapshotCell representation (the dashboard still matches snapshot) — tracked in #112.

🤖 Generated with Claude Code

A master-detail Ink TUI that lists Sessions and shows a continuously-updated,
read-only Live View of the selected one, reconstructed by Event Log Follow
(file-tail of events.jsonl -> libghostty-vt replayTo/snapshot) per ADR 0006.
It reads the Event Log as the source of truth, never queries the live host,
and never resizes the Session.

- Deep modules (unit-tested): EventLogTailSource/SessionEventSource seam,
  LiveViewProjection (pure clip/pan/letterbox/overview), LiveViewFollower
  (coalescing, pin-on-exit, collected, bounded replay), and RendererReadiness
  plus a `dashboard` doctor capability.
- Tab-toggled focus (list select vs Live View pan), `a` scope toggle (active
  default; all excludes destroyed), `z` block-glyph overview, `--all`/`--session`.
- Requires the optional libghostty-vt renderer (no browser fallback);
  interactive-only (no --json), fails fast on a non-interactive terminal.
- Moves react+ink to dependencies, adds @types/react (dev) and jsx to tsconfig;
  removes the throwaway proto/.

Change-Id: I2b15108a1e7968f9eeeade63d672974111681a59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33 ThomasK33 merged commit 0483b7a into main Jun 2, 2026
13 checks passed
@ThomasK33 ThomasK33 deleted the feat/session-dashboard branch June 2, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PRD: Session Dashboard — read-only live viewer for agent sessions

1 participant