Model or dataset
es617/claude-replay avatar
es617/claude-replay

claude-replay: turn Claude Code, Cursor and Codex transcripts into a single HTML file

Convert AI coding agent sessions (Claude Code, Cursor, Codex, Gemini, OpenCode, Kimi Code, Hermes) into self-contained, embeddable HTML replays

831 stars62 forksJavaScriptMIT

At a glance

What is it?
claude-replay converts on-disk agent session logs from seven coding agents into one self-contained HTML replay. The mechanism is a format auto-detector plus a bundled template; the constraint is that it reads transcripts, it does not record screens.
Who is it for?
Adopt claude-replay if you already keep agent transcripts on disk and need a shareable artefact for a bug report, a blog post or a docs page, since the output is one HTML file with no external requests. Do not adopt it if you want to record a live screen session or share a session whose transcript you never saved: the tool reads logs that already exist, and Cursor logs in particular carry no timestamps.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 18 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap claude-replay fills: sessions that exist only as logs

A coding agent session is easy to produce and awkward to show. The README states the problem plainly: screen recordings are bulky, and raw transcripts are hard to navigate. Both are true, and they fail in opposite directions. A recording is watchable but heavy and impossible to search. A JSONL transcript is precise but unreadable to anyone who was not there.

claude-replay sits between those two points. It reads the transcript an agent already wrote to disk and emits an interactive HTML page: playback with speed control, collapsible tool calls and thinking blocks, bookmarks, a file activity sidebar, and terminal-style bottom-to-top scrolling. The output is a single file with no external dependencies, so it can be emailed or dropped into documentation.

The audience is narrow and specific. It is for people who finish an agent session, look at the log, and want to send that session to someone else: a maintainer reading a bug report, a writer assembling a walkthrough, a teacher stepping through tool usage. If your sessions are throwaway, this tool has nothing to do. It converts existing artefacts; it does not create them.

How the format auto-detection and template build work

The pipeline has three visible stages. First, input resolution. Given no argument, claude-replay opens a browser-based editor that discovers Claude Code and Cursor sessions. Given a session ID, it searches `~/.claude/projects/`, `~/.cursor/projects/`, `~/.codex/sessions/`, `~/.gemini/tmp/` and the Hermes SQLite databases under `~/.hermes/`. Given a path, it reads that file.

Second, format detection and normalisation. Each agent stores transcripts differently. Claude Code, Cursor and Codex use JSONL; Gemini writes single JSON files with inline thinking blocks; OpenCode keeps sessions in SQLite and must be exported first; Kimi Code writes `wire.jsonl` under `~/.kimi-code/sessions/<project>/<session>/agents/<name>/`; Hermes stores state in `~/.hermes/state.db`. Rather than render seven dialects, claude-replay maps foreign tool names onto Claude Code equivalents. The README gives the example that Codex `exec_command` and `apply_patch` become `Bash` and `Edit`/`Write`, and Gemini `run_shell_command` becomes `Bash`. That mapping is why a diff view and a command preview look the same regardless of which agent produced the session.

Third, emission. The `template/` directory holds the viewer, and `scripts/build-template.mjs` builds it with esbuild. The published package ships `bin/`, `src/` and `template/`, so the generated HTML carries its own viewer code. That is the whole reason the output is portable: nothing is fetched at view time. The trade-off is that the replay is as large as the embedded session plus the template, and a long session with many tool calls will produce a correspondingly heavy file.

Installing claude-replay and generating a first replay

The README gives two install paths. A global install exposes the `claude-replay` binary:

bash
npm install -g claude-replay

Or run it without installing, which is the fastest way to check whether your transcripts are found:

bash
npx claude-replay

With no arguments, the command opens the web editor and auto-discovers Claude Code and Cursor sessions. For a scripted run, pass a session ID and an output path. The README's quick start uses `abc123def456` as a placeholder ID:

bash
claude-replay abc123def456 -o replay.html

You can also pass the full path to a transcript, or chain several sessions into one replay:

bash
claude-replay session1-id session2-id -o combined.html

If you prefer a container, the Dockerfile installs the package globally on `node:22-alpine`, exposes port 7331, and sets the entrypoint to `claude-replay --host 0.0.0.0`. The README's run command mounts the session directory read-only and maps the port:

bash
docker run --rm --init -p 7331:7331 \
  -v ~/.claude/projects:/root/.claude/projects:ro \
  ghcr.io/es617/claude-replay

Open `http://localhost:7331` for the web editor. For a one-off export, the README adds a second volume for output and passes the session path plus `-o /output/replay.html`. What you should see in every case is a single HTML file that opens without a server. The README notes that `--serve --watch` monitors sessions live as they run, which is a different mode: the file is regenerated as the agent writes, rather than produced once at the end.

Timing modes and the Cursor timestamp problem

Playback speed is only meaningful if the replay knows when each event happened. Not every agent records that. The README is explicit that Cursor transcripts do not include timestamps, so playback falls back to paced timing by default. In practice this means a Cursor replay shows the sequence and the content faithfully but invents the rhythm: a tool call that took four minutes and one that took four seconds are paced alike.

For a walkthrough or a demo, paced timing is usually fine, arguably better, because it removes dead air. For a bug report where the delay is the bug, it is the wrong tool. If the timing of a session matters to your argument, check whether the source format carries timestamps before you build the replay, and prefer Claude Code, Codex or Gemini input where it does.

The same caution applies to chained sessions. Passing two session IDs produces one combined replay, but the README does not document how gaps between sessions are represented, so treat the seam as unverified until you look at the output yourself.

Redaction, and why it is not a substitute for review

Sessions contain secrets. API keys typed into a prompt, tokens echoed by a command, internal hostnames in a patch: all of it lands in the transcript and would land in the replay. claude-replay includes a secret redaction pass before export, and the project's homepage links a live demo of redaction in action.

The README does not document which patterns the redaction covers, and it does not document rollback or an audit of what was removed. That silence matters. A redaction pass that runs before export is a filter, not a guarantee, and the failure mode is quiet: the replay looks clean and one token survives inside a diff hunk. If you are publishing a replay outside your organisation, open the generated HTML and search it for the strings you care about before you send it. The self-contained format works in your favour here, because there is exactly one file to inspect.

Where claude-replay is the wrong choice

Two cases stand out. The first is live demonstration. claude-replay renders history; `--serve --watch` tails a session as it grows, but that is monitoring a log, not capturing a screen. If you need to show a GUI interaction, a browser flow, or anything the agent did outside its own tool calls, a screen recording is still the right artefact and claude-replay will not help.

The second is any session whose transcript was never persisted. OpenCode keeps sessions in a SQLite database and the README requires an explicit export step before replay:

bash
opencode export <sessionID> > session.jsonl
claude-replay session.jsonl -o replay.html

If that export was never run and the database is gone, there is nothing to convert. Hermes is a partial exception: on Node 22.5 and above, claude-replay reads the live SQLite store directly, or you can use `hermes sessions export`. Note the version floor. The package declares `"node": ">=18"` in `engines`, but the direct Hermes database read needs Node 22.5 or later, so a Node 18 or 20 environment falls back to the export path. That is a real constraint the engines field alone does not convey.

claude-replay versus asciinema and terminal recorders

The closest alternative in spirit is a terminal session recorder such as asciinema. The difference is where the data comes from. A terminal recorder captures a pty in real time: you start it, it records what the terminal draws, and the result is a faithful, timestamped cast of that terminal session. It knows nothing about agents, tool calls, thinking blocks or file diffs.

claude-replay inverts that. It never observes the process. It parses a structured log after the fact, which means it can render things a terminal capture cannot: a collapsible thinking block, a sidebar of touched files, a jump from a file to the tool calls that modified it. It also means it can only show what the agent chose to log, in the format the agent chose to log it, and it inherits every gap in that format, including Cursor's missing timestamps.

If your goal is a faithful record of a terminal, use a terminal recorder. If your goal is a navigable, embeddable account of an agent session, use claude-replay. They are not competing for the same job, and the choice is decided by whether the session you want to share is a terminal or an agent conversation.

Maintenance, licence and upgrade cost

The repository is not archived. The last push was on 2026-08-29, and v0.11.0 was released the same day, following v0.10.0 on 2026-07-24 and v0.9.0 on 2026-07-20. Three releases across roughly six weeks is a steady cadence, and the version numbering signals that the project is still moving through the 0.x range, so minor releases may carry behavioural changes.

The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. Two practical notes follow from that, offered as observations rather than legal advice. First, the generated replay is your content, but it embeds the viewer from `template/`, so the MIT notice travels with the output. Second, the project is a community tool and the README states it is not affiliated with or endorsed by Anthropic, so do not read the name as a support relationship.

Upgrade cost is low by construction. The package has zero runtime dependencies, ships `bin/`, `src/` and `template/`, and the build step is esbuild over the template. There is no plugin API documented in the README, so an upgrade is unlikely to break an integration you wrote. What can change between 0.x versions is the rendered output and the auto-detection rules for a given agent format, which is exactly the surface you would notice. The repository keeps a CHANGELOG.md at the top level, which is the file to read before bumping the version.

Editorial conclusion

Adopt claude-replay if you already keep agent transcripts on disk and need a shareable artefact for a bug report, a blog post or a docs page, since the output is one HTML file with no external requests. Do not adopt it if you want to record a live screen session or share a session whose transcript you never saved: the tool reads logs that already exist, and Cursor logs in particular carry no timestamps. Before relying on it, generate a replay from one real session and open the file offline to confirm the redaction pass and the timing mode behave as you expect.

Frequently asked questions

How do I install claude-replay?

Install it globally with npm, or run it without installing via npx. The README also publishes a container image that installs the package on node:22-alpine and exposes port 7331.

Does claude-replay work with Cursor and Codex sessions, or only Claude Code?

It supports Claude Code, Cursor, Codex CLI, Gemini CLI, OpenCode, Kimi Code and Hermes Agent, and auto-detects the format. Foreign tool names are mapped to Claude Code equivalents so diffs and command previews render consistently.

Why does my Cursor replay not match the real timing of the session?

The README states that Cursor transcripts do not include timestamps, so playback uses paced timing by default. The sequence and content are preserved, but the intervals between events are not taken from the original session.

How do I replay an OpenCode session?

OpenCode stores sessions in a SQLite database, so you must export the session first with the OpenCode CLI, then pass the exported file to claude-replay. The README gives the export command as opencode export followed by the session ID.

Official sources

  1. es617/claude-replay on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes