Claude Transcripts docs GitHub
Work in progressUnder active development — not tested as ready for use. Breaking changes land without notice, stored data may need to be discarded between revisions, and there is no auth or security model.

webui

packages/webui/: a React single-page app for browsing history, served by the webapi at /app. Optional; everything it shows is reachable through the API and CLI. Stack: React 19, Vite 6, MUI 6, TanStack Router and TanStack Query, with an orval-generated API client.

bun run dev:webui     # http://127.0.0.1:7651/app/, proxies /api to the webapi
bun run build         # → packages/webui/dist/, served via CT_STATIC_DIR

Pages

Filters (cwd, model, hostname, source, from/to) are URL parameters passed to GET /api/sessions, shown as removable chips.

Status reads live (running, a pulsing dot), abandoned (incomplete, a hollow ring) or ended (a square); provenance chips read live or backfilled. Active time is runtime minus gaps longer than system.sessions.idleThresholdMs; it shows — where the API couldn't derive it.

Transcript viewer

A Both / You / Claude toggle picks the speaker. You or Claude shows one side of the conversation from GET /api/sessions/{id}/turns (empty without full-content chunks). Both shows the full transcript in one of two readers over the same paged entries:

Entries load in blocks of userSettings.transcriptPageSize as you scroll and in the background while the tab is visible. After userSettings.transcriptAutoLoadMax entries a button offers to load the rest, because the list isn't virtualised. Arriving from search (?q=) opens at the matching entry with terms highlighted.

Title and build version (from /api/blueprint), the omnibox, and four menus, all projected from the blueprint (src/nav-menus.ts):

The webui has one theme, dark.

The omnibox takes free text, project: / host: / model: / source: operators, date phrases, an id prefix or > commands. Enter filters the list, Shift+Enter searches, Ctrl/Cmd+K focuses it. Its dropdown previews search hits, recent searches and saved filters, and shows a hint when search is off.

Code

Path (src/)Holds
main.tsx, router.tsxRoot: Query client (30 s staleTime, no refetch on focus, retry: 1), the theme, code-based router with basepath /app. Each route validates its own query-string state and falls back to defaults.
theme.tsThe one (dark) MUI theme; components use semantic palette tokens.
nav-menus.tsThe header menus and a session's data links, projected from /api/blueprint.
api/generated.tsorval output: types, fetchers, query-key helpers, React Query hooks. Never edit; bun run gen:clients.
api/http.tsThe orval mutator: same-origin requests, unwraps the body, throws ApiRequestError on non-2xx.
api/blueprint.tsHand-written useAppBlueprint for /api/blueprint, which is not in the OpenAPI spec.
routes/root, sessions-list, session-detail, search-results.
components/UI; components/sessions/ holds the list and calendar.
omnibox/Input parsing, > commands, recent searches, saved filters.
hooks/Infinite paging for the list and transcript, and the scroll sentinel.

Logic worth testing lives in pure modules: format.ts, search-query.ts, sessions-view.ts, transcript-entry.ts, transcript-timeline.ts, omnibox/parse.ts.

When passing queryKey explicitly, use the generated helpers (getListSessionsQueryKey(params)); a hand-made key splits the cache. orval generates useQuery hooks only, so infinite lists wrap the raw fetchers (useInfiniteSessionList, useInfiniteTranscript).

Dev server

vite.config.ts loads the repo-root .env for WEBUI_HOST/WEBUI_PORT and the proxy target. dev/webapi-target.ts picks the target the same way the CLI does: WEBAPI_PORT if set, else the installed instance's port from instance.env, else 7650. When nothing is listening, proxied calls return 502 with a body naming the dead target.

Planned

Virtualised lists (which would remove the transcriptAutoLoadMax ceiling), configurable columns, server-side sorting of the session list (a sort/dir parameter on GET /api/sessions), a cross-session view over /api/turns, keyboard navigation, and a visual design pass.