open-transcript-viewer
v1.0.0
Published
Render Claude Code, Codex, and OpenClaw session JSONL transcripts as polished standalone HTML.
Maintainers
Readme
open-transcript-viewer
Render Claude Code, Codex, and OpenClaw session JSONL transcripts as polished, standalone HTML pages.
A Node.js take on daaain/claude-code-log — zero runtime dependencies, pure ESM, Node ≥ 18. Each provider has its own JSONL shape; this tool normalises them through a shared block model and emits one set of styled HTML pages.
Repo: https://github.com/vagusX/cclog · Package:
open-transcript-viewer· Bins:open-transcript-viewer,otv
Install
npm install -g open-transcript-viewer
# or one-shot
npx open-transcript-viewer --helpAfter install both open-transcript-viewer and otv are on PATH.
Quickstart
# Render everything you have, in one shot, and open the index in your browser
otv --everything -o /tmp/transcripts --open
# Single file — provider auto-detected from the first events
otv ~/.claude/projects/<slug>/<uuid>.jsonl -o cc.html
otv ~/.codex/sessions/2026/05/.../rollout-*.jsonl -o codex.html
otv ~/.openclaw/agents/main/sessions/<id>.jsonl -o oc.html
# A whole provider tree
otv --all-projects --provider codex -o /tmp/codex-log
otv --all-projects --provider openclaw -o /tmp/oc-log
# Default (no args) ≈ claude-code, default root
otvWhat gets rendered
| Provider | Default root | Source events | Tool calls | Thinking |
| ------------ | --------------------------- | ---------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------- |
| claude code | ~/.claude/projects | {type:'user'/'assistant', message:{...}} | content[].type=tool_use + tool_result | content[].type=thinking |
| codex | ~/.codex/sessions | {type:'response_item', payload:{...}} | function_call + custom_tool_call + _output | event_msg:agent_reasoning (plaintext) — see below |
| openclaw | ~/.openclaw/agents | {type:'message', message:{...}} | content[].type=toolCall + role toolResult msgs | content[].type=thinking |
Noise events (Claude's hook_success, Codex's event_msg:* that duplicates response_item, OpenClaw's custom:model-snapshot and runtime-context messages with display:false) are dropped, but a counter is kept and shown at the page footer.
Codex reasoning note
Codex rollouts write two parallel tracks:
response_item:reasoning— usually onlyencrypted_content(opaque blob).event_msg:agent_reasoning— the plaintext summary the TUI actually shows.
open-transcript-viewer reads agent_reasoning and dedupes the encrypted twin. Pre-2026-04 sessions don't have the plaintext track on disk; for those, the encrypted placeholder is preserved.
CLI
otv [path] [options]
Options:
--all-projects Process the provider's default root (one --provider).
--everything Render claude-code + codex + openclaw side-by-side.
-o, --output <path> Output file (single session) or directory.
--no-individual Skip per-session HTML pages.
--provider <name> Provider name (auto-detected if omitted).
Available: claude-code, codex, openclaw.
--from <iso> Only include messages on/after this ISO timestamp.
--to <iso> Only include messages on/before this ISO timestamp.
--open Open the resulting HTML in the default browser.
-h, --help Show this help.Output layout
<out>/
├── index.html # master index (provider cards when --everything)
└── <slug>/
├── combined_transcripts.html # one card per session (preview, time, model, tokens)
└── session-<id>.html # single-session page (chips, stats, rail, avatar, tool blocks)Single-session pages include:
- Sticky frosted-glass header with
provider · model · cwd · branch · id · time · token totalchips - A 4px role rail + circular avatar on every message, so a single glance tells you who said what
- Stats summary (msgs / user / reply / tools) in the top-right
- Collapsible
<details>for tool calls — header shows tool name + first line of arguments even when collapsed thinkingblocks rendered as a distinct purple tag- Per-message
in / out / cache / costfooter - GitHub-dark default theme; light theme via
prefers-color-scheme - Keyboard shortcuts:
eexpand all details,ccollapse all
Library API
import {
renderSessionFile, // → outputPath
renderProject, // → { project, combinedPath, sessionPaths }
renderAll, // → { indexPath, projects }
getProvider,
detectProviderFromFile,
detectProviderFromDir,
} from 'open-transcript-viewer';
await renderSessionFile({
inputPath: '/path/to/session.jsonl',
outputPath: '/tmp/out.html',
// provider: 'codex', // optional — auto-detected if omitted
// filter: { from: '2026-05-01T00:00:00Z', to: '2026-05-31T23:59:59Z' },
});Each provider exports { id, label, defaultRoot, discoverProjects, parseSession } and can be plugged into the same renderer.
Provider extension contract
discoverProjects(root) → [{ slug, label, dir, sessions: [{ id, path }] }]
parseSession(filePath) → {
meta: { sessionId, provider, model, cwd, branch, startedAt, endedAt, usage, ...},
messages: [{ role, timestamp, blocks: [...], meta }],
droppedEventCounts: { '<reason>': n, ... },
}Blocks are provider-agnostic: text · thinking · tool_use · tool_result · image · unknown. To add a new transcript format, implement the two functions above and register the module in src/providers/index.js.
Develop / test
git clone [email protected]:vagusX/cclog.git
cd cclog
node --test 'test/**/*.test.js'There are 11 unit tests covering the three parsers, the provider sniffer, HTML escaping, and the Markdown subset. No npm install step — the package itself has zero runtime dependencies.
Design choices
- No runtime deps.
npx open-transcript-viewerruns offline. Markdown is rendered by a small handwritten subset (code blocks, inline code, bold/italic, links, lists, blockquotes); CLI arg parsing is manual. - Static output only. v1 doesn't include a TUI or a local server. Pages are self-contained HTML you can open anywhere.
- Conservative event filtering. Unknown event types are not silently dropped; they're either rendered as
unknownblocks or counted in a per-page footer so you can tell when the parser is undercounting. - Provider sniffing. When no
--provideris given, the CLI peeks at the first ~10 events and at the directory shape (YYYY/vssessions/vs Claude's flattened cwd).
Status & roadmap
- [x] Claude Code transcripts
- [x] Codex rollouts (with plaintext reasoning track)
- [x] OpenClaw sessions
- [x] Master + project-level + per-session pages
- [x] Auto provider detection
- [ ] Client-side search (cross-session)
- [ ] Markdown export (
--format md) - [ ] Interactive picker (TUI or local web)
License
MIT © Vagus X
