{"slug": "show-hn-a-local-extensible-session-viewer-for-pi-and-codex", "title": "Show HN: A local, extensible session viewer for Pi and Codex", "summary": "A developer released a local, extensible web viewer for coding-agent session archives that supports Pi and Codex, normalizing both formats into a searchable timeline while preserving raw JSON. The viewer requires Node.js 18 or newer and runs without package installation or build steps, offering features like search, sort, token usage display, and responsive layout.", "body_md": "A local, read-only web viewer for coding-agent session archives.\n\nBuilt-in extensions support [Pi](https://github.com/badlogic/pi-mono) and Codex. The viewer normalizes both formats into one searchable timeline while retaining the original records as expandable raw JSON.\n\n- Select between installed session harnesses\n- Search by prompt, path, session ID, model, or thinking mode\n- Sort by date, project path, or session ID\n- Show model, provider, and thinking mode on every event\n- Display token usage, cache usage, cost when available, timestamps, IDs, and file metadata\n- Render file writes as code, edits and patches as diffs, and shell calls as commands\n- Show multi-agent message type, task path, sender, and recipient\n- Keep tool calls, tool results, skills, reasoning, and raw JSON collapsed until requested\n- Preserve harness-specific fields in expandable raw JSON\n- Link directly to a harness and session\n- Responsive desktop and mobile layout\n\n| Harness | Session directory | Default |\n|---|---|---|\n| Pi | `~/.pi/agent/sessions` |\nYes |\n| Codex | `~/.codex/sessions` |\nNo |\n\nOnly the selected harness is scanned. Results are cached until **Refresh** is clicked. Codex archives store token usage but not monetary cost, so the viewer reports **Not stored** instead of inventing an estimate.\n\n- Node.js 18 or newer\n- At least one supported session directory\n\nNo package installation, template compiler, or build step is required.\n\n```\nnode server.js\n```\n\nOpen [http://127.0.0.1:4173](http://127.0.0.1:4173).\n\nHarness-aware deep links use this format:\n\n```\nhttp://127.0.0.1:4173/#pi/019f8b7f-f4f4-7441-8291-f18fef3372cf\nhttp://127.0.0.1:4173/#codex/SESSION_ID\n```\n\nBare `#SESSION_ID`\n\nlinks open with whichever installed extension declares `default: true`\n\n.\n\n| Environment variable | Default | Purpose |\n|---|---|---|\n`PORT` |\n`4173` |\nLocal HTTP port |\n`PI_SESSIONS_DIR` |\n`~/.pi/agent/sessions` |\nPi session directory |\n`CODEX_SESSIONS_DIR` |\n`~/.codex/sessions` |\nCodex session directory |\n\nExample:\n\n```\nPORT=8080 CODEX_SESSIONS_DIR=~/archives/codex node server.js\n```\n\nEvery enabled JavaScript file in `extensions/`\n\nis loaded as trusted local code. An extension implements two operations behind one interface:\n\n```\nmodule.exports = {\n  enabled: true,\n  default: false,\n  id: 'my-harness',\n  label: 'My Harness',\n  defaultRoot: '~/.my-harness/sessions',\n  rootEnv: 'MY_HARNESS_SESSIONS_DIR',\n\n  async listSessions({ root }) {\n    return { sessions: [], errors: [] };\n  },\n\n  async loadSession({ root, id }) {\n    return { summary: {}, events: [], parseErrors: [] };\n  },\n};\n```\n\nCopy `extensions/custom-example.js`\n\n, implement the two methods, and set `enabled: true`\n\n. Extensions may use JSONL, SQLite, or any other local format, but must normalize data into the viewer's shared `summary`\n\nand `events`\n\nshape.\n\nThe server and browser contain no harness IDs or harness event/tool names. Extensions normalize their records into generic events (`title`\n\n, `summary`\n\n, `display`\n\n) and message content primitives such as `text`\n\n, `context`\n\n, `toolCall`\n\n, `toolResult`\n\n, `command`\n\n, `code`\n\n, `diff`\n\n, and `fileChange`\n\n. Adding a harness therefore requires only an extension file.\n\nExtensions execute with the same filesystem permissions as the server. Install only code you trust.\n\nWith Node.js:\n\n```\nnode server.test.js\n```\n\nWith Bun:\n\n```\nbun test server.test.js\n```\n\nUse `bun test`\n\n, not `bun run`\n\n: Bun must start its test runner for the `node:test`\n\nAPI.\n\n| File | Purpose |\n|---|---|\n`server.js` |\nExtension discovery, scan cache, and local HTTP routes |\n`page.html` |\nStatic application shell |\n`public/app.js` |\nHarness selector and normalized timeline renderer |\n`public/style.css` |\nResponsive interface styling |\n`extensions/pi.js` |\nPi adapter |\n`extensions/codex.js` |\nCodex adapter |\n`extensions/custom-example.js` |\nDisabled extension template |\n`extensions/index.js` |\nTrusted extension discovery and validation |\n`lib/jsonl.js` |\nShared tolerant JSONL reading and recursive discovery |\n`server.test.js` |\nPi, Codex, extension, page, and stylesheet checks |\n\nSession files can contain prompts, source code, command output, paths, and tool results. The viewer:\n\n- listens only on localhost;\n- reads but never modifies session files;\n- makes no external network requests;\n- uses only Node.js built-ins at runtime.", "url": "https://wpnews.pro/news/show-hn-a-local-extensible-session-viewer-for-pi-and-codex", "canonical_source": "https://github.com/skorotkiewicz/sessions-viewer", "published_at": "2026-07-23 00:29:20+00:00", "updated_at": "2026-07-23 00:52:24.615752+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Pi", "Codex", "Node.js"], "alternates": {"html": "https://wpnews.pro/news/show-hn-a-local-extensible-session-viewer-for-pi-and-codex", "markdown": "https://wpnews.pro/news/show-hn-a-local-extensible-session-viewer-for-pi-and-codex.md", "text": "https://wpnews.pro/news/show-hn-a-local-extensible-session-viewer-for-pi-and-codex.txt", "jsonld": "https://wpnews.pro/news/show-hn-a-local-extensible-session-viewer-for-pi-and-codex.jsonld"}}