Browser UI
Local, loopback-only browser UI for exploring sessions, evals, and token usage.
thirdeye ui launches a local browser UI as a richer alternative to the CLI for exploring sessions, visualizing traces, tagging events, authoring evals, and watching token spend over time. The server is opt-in, binds loopback only, and reads/writes the same <thirdeye_home>/ tree the CLI uses.
The preview above mirrors the sessions list at / — saved-views sidebar, filter form with the tag multi-select, the Ask panel, the eval batch bar, and the sessions table. Click a session id in the real UI to drill into its event tree.
Install
The Homebrew package includes the browser UI and all of its dependencies:
brew install duncanmckinnon/tap/thirdeyeFor Python installations, the UI ships as an optional extra so the default pip install thrdi stays lean:
pip install 'thrdi[ui]'Using pipx? Inject the deps into the existing thrdi venv:
pipx inject thrdi starlette uvicorn jinja2Launch
thirdeye ui # http://127.0.0.1:8765 by default
thirdeye ui --port 9000 # pick a port
thirdeye ui --host 127.0.0.1 # interface to bind (loopback only)
thirdeye ui --no-browser # don't auto-open the browserThe CLI opens your default browser unless --no-browser is passed. Ctrl-C stops the server.
If the extra isn't installed, thirdeye ui prints a hint and exits with status 1:
The 'ui' extra is required. Install it with: pip install 'thrdi[ui]'
What you can do
Browse sessions
The list at / shows every recorded session across every platform, with filters for platform, cwd, status (open / closed / stale), date range, and a tag multi-select drawn from every tag in your history. Defaults to the last 7 days, newest first. The active filter persists in localStorage, so navigating away and back keeps your view.
Ask panel (agentic filters)
Both / and /search carry an Ask textarea. Type a natural-language description — "find sessions about the workbench plan", "long-lasting claude runs this week" — pick a CLI agent (claude / codex / gemini), and submit.
The agent receives a grounded vocabulary block (your platforms, cwds, tags) plus the bundled thirdeye-filter skill and returns a structured JSON envelope. The UI auto-fills the existing filter form with the proposed values — review or tweak any field, then hit Search / Filter to run. No auto-execute, no separate Run button to learn.
Saved filter views
From /, name a filter combination and pin it to the sidebar. Saved views persist on disk at <thirdeye_home>/views/sessions.json and are manageable from the CLI too:
thirdeye views list --page sessions
thirdeye views save my-view --page sessions
thirdeye views delete my-view --page sessionsSession view
Each session view renders the event stream as a collapsible tree, color-coded by event type (user, assistant, tool call, tool result, etc.). Click any event to expand its full JSON payload in the side pane. Tag any event inline — tags hit the same per-session store the CLI uses, so thirdeye search --tag <name> picks them up immediately.
Live-tail open sessions
Sessions that are still receiving events stream new entries into the tree in real time via Server-Sent Events. No refresh needed.
Search across sessions
Substring search with the same filters as thirdeye search. Each hit links straight to the event in its session.
Usage charts
/usage renders daily tokens-over-time (stacked input / output) and sessions-per-day charts via vendored Chart.js, plus totals cards. Filter by platform / since / until. Per-session usage at /sessions/<id>/usage keeps the existing per-turn detail view.
Author and run evals
Browse, edit, and create eval definitions (YAML rubrics) in the browser. Dispatch a run against any single session, or select multiple sessions on / and dispatch a batch of runs in one click. Each run gets a unique run_id; the same definition can be re-run on the same session.
Two complementary cross-cuts ship in the UI:
/evals/defs/<name>/results— every run of one definition across every session it's been applied to. Sortable, with verdict / agent / started-at / duration and a link to each run's findings. Useful for tracking how one rubric grades across your history./sessions/<id>/evals/<def_name>— every run of one definition on one session. Renders the definition's full directive text plus a table of every run on that session, with parsed columns: run id, verdict, one column per score key seen across runs (with—for absent), findings count, duration, started, agent. Useful for comparing iterations of the same rubric on a single session.
Keyboard shortcuts
Inside the session tree:
| Key | Action |
|---|---|
↑ / ↓ | Move between sibling events. |
← | Collapse the focused node (or jump to its parent if already collapsed). |
→ | Expand the focused node. |
Enter | Open the focused event in the side pane. |
Security model
- The server binds
127.0.0.1by default and refuses to listen on other interfaces unless--hostis overridden explicitly. - No authentication. The UI is intended for local use on a trusted workstation. Don't expose it over a network or tunnel it without adding your own auth layer in front.
- All reads and writes operate on the same
<thirdeye_home>/tree the CLI uses (THIRDEYE_HOMEenv var, default~/.thirdeye/).
Troubleshooting
ModuleNotFoundError: starlette— a Python installation is missing theuiextra. Runpip install 'thrdi[ui]'(orpipx inject thrdi starlette uvicorn jinja2). Homebrew installs already include it.OSError: [Errno 48] Address already in use— another process holds the port. Pass--portwith a free port, or stop the other process.- Browser didn't open — pass
--no-browserto suppress the auto-open and copy the printed URL manually. On headless machines, always use--no-browser. - Live tail isn't updating — confirm the session is still
open(the session header shows status). Closed sessions render the full timeline but don't stream. Some restrictive corporate proxies break SSE; running the browser on the same host as the server avoids the proxy entirely. - 404 on a session ID — IDs accept any unique prefix. If you typed an ambiguous prefix the 404 page lists the closest matches; click one to disambiguate.