ai-replay 🎬
Convert Claude Code, Cursor, Codex CLI, OpenCode, Pi, and GitHub Copilot (CLI and VS Code Chat) session transcripts to interactive HTML replays.
▶️ See a live demo — preview what a generated replay looks like before you install anything.
Python port of claude-replay by es617 (original JavaScript version).
Inspired by claude-code-transcripts by Simon Willison — the interactive session picker, --gist publishing flow, and output folder naming convention (<agent>-<sessionID>/index.html) are all modelled after his work.
Installation
uv tool install ai-replay
Usage
# Interactive session picker (default — runs when no arguments given)
ai-replay
# Generate HTML replay from a session file
ai-replay session.jsonl -o replay.html
# Generate from a session ID (auto-discovered)
ai-replay <session-id> -o replay.html
# Extract turns from a generated replay
ai-replay extract replay.html
# Serve replay on local HTTP server
ai-replay session.jsonl --serve --port 4000
OpenCode
OpenCode stores sessions in a SQLite database rather than on-disk JSONL files,
so export a session to JSON first and pass the file to ai-replay (the format
is auto-detected):
opencode export <sessionID> > session.json
ai-replay session.json -o replay.html
OpenCode's lowercase tool names (bash, read, write, edit, …) are mapped
to their Claude Code equivalents so they render with the same diff views and
command previews. Reasoning blocks render as thinking blocks.
Pi
Pi stores sessions as on-disk JSONL under
~/.pi/agent/sessions/--<cwd>--/<timestamp>_<uuid>.jsonl (overridable via the
PI_CODING_AGENT_DIR environment variable), so they are auto-discovered by the
picker and parsed automatically — no export step needed:
ai-replay <session-id> -o replay.html
Pi's lowercase built-in tool names (bash, read, write, edit, grep,
find, ls) are mapped to their Claude Code equivalents so they render with
the same diff views and command previews. thinking blocks render as thinking
blocks.
GitHub Copilot CLI
The GitHub Copilot CLI writes an event
log to ~/.copilot/session-state/<uuid>/events.jsonl (overridable via the
COPILOT_CLI_DIR environment variable), so sessions are auto-discovered by the
picker and parsed automatically — no export step needed:
ai-replay <session-id> -o replay.html
The session ID is the directory UUID; a leading fragment is enough. Because
Copilot names its directories by UUID rather than by path, the project name
shown in the picker comes from the cwd recorded in the session's
session.start event.
Copilot's lowercase tool names (bash, view, create, edit, grep, …) are
mapped to their Claude Code equivalents so they render with the same diff views
and command previews. Reasoning (reasoningText) renders as thinking blocks,
and the harness's own system prompt is skipped.
VS Code Copilot Chat
Copilot Chat inside VS Code stores each conversation as a journal at
~/Library/Application Support/Code/User/workspaceStorage/<workspace>/chatSessions/<id>.jsonl
(%APPDATA%\Code\... on Windows, ~/.config/Code/... on Linux). These are
auto-discovered by the picker and listed as Copilot Chat, or you can pass a
file or session ID directly:
ai-replay <session-id> -o replay.html
ai-replay chatSessions/<id>.jsonl -o replay.html
VS Code Insiders and VSCodium are scanned too; set VSCODE_USER_DIR to point at
a different User directory. Because workspaceStorage directories are opaque
hashes, the project name shown in the picker is read from the workspace's
workspace.json. VS Code creates a journal as soon as a chat panel is opened,
so sessions with no prompt in them are skipped.
Unlike every other supported format this is not an append-only transcript: the first line is a full snapshot and later lines are patches that set or append at a key path, so a streamed answer typically lands on a different line from the question it answers. ai-replay replays the journal to its final state before extracting turns.
VS Code tool ids (run_in_terminal, copilot_readFile, copilot_createFile, …)
are mapped to their Claude Code equivalents; MCP tools keep their descriptive
id. Terminal commands use the command you typed rather than VS Code's
environment-prefixed rewrite.
VS Code also writes a
GitHub.copilot-chat/transcripts/<id>.jsonlin the same Copilot CLI event format. It is often incomplete for a live session, so prefer thechatSessions/journal.
Interactive picker options
ai-replay pick # explicit invocation
ai-replay pick --limit 30 # show more sessions (default: 20)
ai-replay pick --agent codex # filter to one agent (partial match)
Options
-o, --output FILE: Output HTML file (default: stdout)--title TEXT: Custom page title--theme NAME: Color theme (default: dark-knight)--no-redact: Disable automatic secret redaction--open: Open in browser after generating--no-compress: Embed raw JSON instead of compressed--serve: Serve on a local HTTP server--port INTEGER: Port for --serve (default: 4000)--turns TEXT: Turn range filter (e.g. "1-10")--exclude TEXT: Exclude specific turns (e.g. "3,7")
Development
Prerequisites
- Python 3.10+
- uv (recommended) or pip
Install the dev version from this branch
With uv (recommended):
# Clone the repo (or your fork)
git clone https://github.com/jeanclawd/ai-replay.git
cd ai-replay
# Check out the feature branch
git checkout feat/interactive-tui-picker
# Create a virtual environment and install in editable mode
uv venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -e .
# Verify
ai-replay --version
With pip:
git clone https://github.com/jeanclawd/ai-replay.git
cd ai-replay
git checkout feat/interactive-tui-picker
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
# Verify
ai-replay --version
Run the tests
# With uv (inside the activated venv)
uv pip install pytest
pytest
# Or without activating:
uv run pytest
Expected output:
collected 6 items
tests/test_discover.py::test_discover_claude_and_codex PASSED
tests/test_discover.py::test_discover_agent_field PASSED
tests/test_discover.py::test_discover_limit PASSED
tests/test_discover.py::test_discover_summary_extraction PASSED
tests/test_discover.py::test_discover_no_sessions PASSED
tests/test_discover.py::test_discover_skips_agent_files PASSED
6 passed in 0.17s
Try the interactive picker
# Launch the TUI picker (requires Claude Code, Codex, or Cursor sessions on disk)
ai-replay
# Or explicitly:
ai-replay pick --limit 10
You should see an arrow-key menu like:
Loading sessions...
? Select a session to replay:
❯ Claude Code 2026-03-24 18:42 142 KB Fix auth bug in middleware
Codex 2026-03-23 11:10 98 KB Add streaming support
Cursor 2026-03-22 09:55 210 KB Initial project scaffold
Select a session and it will:
- Create
<agent>-<sessionID>/in your current working directory - Write the replay as
index.htmlinside that folder - Open it in your browser
Output: ./claude-abc123def456/
The folder naming mirrors claude-code-transcripts — claude- for Claude Code, codex- for Codex, cursor- for Cursor.
Project structure
src/ai_replay/
├── __init__.py # CLI entrypoint (click commands)
├── discover.py # Session discovery across all agents ← new in this branch
├── parser.py # JSONL/JSON session parser
├── renderer.py # HTML renderer
├── resolve_session.py # Resolve session ID → file path
├── secrets.py # Secret redaction
└── templates/ # HTML templates
tests/
└── test_discover.py # Discovery tests ← new in this branch
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ai_replay-0.5.1.tar.gz.
File metadata
- Download URL: ai_replay-0.5.1.tar.gz
- Upload date:
- Size: 56.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f69fdbcf0eaa4d307477bf5ff3d55e7143c1593b63ea5846435bfda63b0e722
|
|
| MD5 |
1c3cf1ffc783193cc09c2380c978634e
|
|
| BLAKE2b-256 |
5d40046ef0d751f986d7790aa79570056bd3b1c0ec61f97e198474e1d952c58d
|
Provenance
The following attestation bundles were made for ai_replay-0.5.1.tar.gz:
Publisher:
cicd.yml on yanndebray/ai-replay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_replay-0.5.1.tar.gz -
Subject digest:
3f69fdbcf0eaa4d307477bf5ff3d55e7143c1593b63ea5846435bfda63b0e722 - Sigstore transparency entry: 2498521282
- Sigstore integration time:
-
Permalink:
yanndebray/ai-replay@f8fe51bc7d239cdb372c555644fd62359a046500 -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/yanndebray
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cicd.yml@f8fe51bc7d239cdb372c555644fd62359a046500 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ai_replay-0.5.1-py3-none-any.whl.
File metadata
- Download URL: ai_replay-0.5.1-py3-none-any.whl
- Upload date:
- Size: 60.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4fd747488dff6c5fe1e1d7c8a241054c56fb2d629a73173af375e329363f9e7
|
|
| MD5 |
a16276979f56b92bdbb66c0f93f3627c
|
|
| BLAKE2b-256 |
3b3f3d3b1c996c215a5918ab536ee114d32f70bff1b618b7ee08371dc0f17b36
|
Provenance
The following attestation bundles were made for ai_replay-0.5.1-py3-none-any.whl:
Publisher:
cicd.yml on yanndebray/ai-replay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_replay-0.5.1-py3-none-any.whl -
Subject digest:
a4fd747488dff6c5fe1e1d7c8a241054c56fb2d629a73173af375e329363f9e7 - Sigstore transparency entry: 2498521288
- Sigstore integration time:
-
Permalink:
yanndebray/ai-replay@f8fe51bc7d239cdb372c555644fd62359a046500 -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/yanndebray
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cicd.yml@f8fe51bc7d239cdb372c555644fd62359a046500 -
Trigger Event:
push
-
Statement type: