Forensic timeline + rollback hints for AI coding sessions (Claude Code, Cursor).
Claude Code or Cursor runs for an hour, fires 50–300 tool calls, edits files, runs rm, calls MCP servers — and at 3am you wake up to broken state. The session log on disk has every step, but it's a 1.4MB JSONL (Claude Code) or a 1GB SQLite blob (Cursor): grep-only and human-illegible.
Three practical questions you can't answer without scrolling for an hour:
- What did it actually run? A clean chronological timeline of every bash / edit / write / read / MCP call.
- Where did it go wrong? Filter by kind, jump by turn, see input / output / cost per node.
- Can I undo this
rm -rf? Per-node copy-pasteable rollback hints (reversemv,git restore,git reflogpointers).
agent-replay answers all three. Local CLI + TUI, no daemon, no network, no upload.
Two read-only loaders (loader.py for Claude Code JSONL, cursor_loader.py for Cursor's SQLite — opened with mode=ro so it never takes a write lock) normalize each session into a single trajectory of typed nodes (bash / edit / write / read / mcp / message). A pure-function rollback annotator scans every node for destructive verbs (rm, mv, dd, git reset --hard, overwrite redirects) and attaches a copy-pasteable undo hint. Three renderers consume the same annotated trajectory — the Rich timeline, the Textual TUI, and the rollback_*.md sidecar — and the whole pipeline runs on your machine with zero outbound sockets (provable via --self-check-network).
Terminal recording rendered in CI by vhs from docs/demo.tape on every tag.
pipx install agent-replay
agent-replay --list-sessions
agent-replay --pick 1 --show-rollbackOffline / air-gapped / behind GFW? See Air-gap install below.
| Command | What it does |
|---|---|
agent-replay session.jsonl |
Static Rich-coloured chronological timeline |
--filter bash --filter edit |
Show only matching kinds (repeatable) |
--show-rollback |
Add a rollback column + write rollback_<sid>.md |
--tui session.jsonl |
Textual three-pane TUI; enter copies hint to clipboard |
--cursor --pick 1 |
Read sessions from Cursor's SQLite globalStorage |
--list-sessions |
Sort by mtime, --limit N / --all / --pick N |
--self-check-network |
Prove zero outbound sockets at runtime (compliance audit) |
agent-replay reads session logs from your disk. It never makes a network call (verifiable: agent-replay --self-check-network runs the tool under lsof and reports any sockets seen). For air-gapped / regulated environments, this means:
- Session data stays on the machine that produced it.
- Safe to run on workstations under SOX / HIPAA / GDPR / 等保 2.0 / 个保法.
- No SaaS dashboard, no telemetry, no "cloud sync".
The Cursor adapter opens its SQLite read-only via sqlite3.connect("file:...?mode=ro", uri=True) — Cursor can keep writing while you replay; we never take a write lock or modify the database.
# Option 1 — auto-detect fastest mirror (tsinghua / aliyun / ustc / tencent → fallback to PyPI)
curl -fsSL https://raw.githubusercontent.com/SuperMarioYL/agent-replay/main/install.sh | bash
# Option 2 — pin a specific PyPI mirror
pipx install --index-url https://pypi.tuna.tsinghua.edu.cn/simple/ agent-replay
# Option 3 — fully offline: download wheel from GitHub Release, install
wget https://github.com/SuperMarioYL/agent-replay/releases/download/v0.2.0/agent_replay-0.2.0-py3-none-any.whl
pipx install ./agent_replay-0.2.0-py3-none-any.whlGitee mirror: gitee.com/SuperMarioYL/agent-replay (auto-synced on every push to main).
- Claude Code: parses JSONL files at
~/.claude/projects/<project>/<session>.jsonl, drops session-management noise (queue-operation/attachment/last-prompt/system) and assistantthinkingblocks (opt-in via--include-thinking). - Cursor: reads
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb(linux + windows paths handled too). Reconstructs a trajectory fromcomposerData:*headers +bubbleId:*rows.toolFormerData.namemaps to agent-replay's kind:read_file/read_lints/grep/list_dir/codebase_search→ READ;search_replace→ EDIT;write→ WRITE;run_terminal_cmd→ BASH;mcp_*→ MCP. - Rollback hints: pure-function dispatch on each node — destructive verb detection (
rm,mv,dd,truncate,git reset --hard,git checkout --,git clean), stdout-redirect detection (>overwrite but not>>append, excludes/dev/nullsinks), per-Edit reverse-Edit, Write →git restore.
- v0.3: cross-session metrics ("you ran 1,200 bash calls this week, top 10 destructive: …")
- v0.4: Codex / Aider / Continue.dev session adapters
- v1.0: stable schema + plugin API for custom session sources
See CONTRIBUTING.md. Issues + PRs welcome. No CLA, MIT license.
If you've reverse-engineered a session format we don't support yet (Codex, Aider, Continue.dev, 通义灵码, Trae, CodeFuse, …), open a PR with a <source>_loader.py and a fixture. The loader API is small (~30 LOC).
MIT — see LICENSE.
