agent-replay-journal
Canonical session-journal format, replay engine, and diff tool for AI agent coding transcripts. Zero runtime dependencies in both Python and Node.js.
Mandatory Rule
agent-replay-journal ships zero runtime dependencies in both Python (pyproject.toml declares dependencies = []) and Node.js (package.json carries no dependencies key). All imports are stdlib only.
tests_passing: true — verified by npm test and python3 -m pytest tests/ (160 tests across both runtimes: 102 Python + 58 Node, as of v0.1.1).
"I want to replay a session exactly as it happened — same tool calls, same order, same results — against my own codebase to verify the same bug is fixed."
Quick Start
# Python
pip install agent-replay-journal
# Node.js
npm install agent-replay-journal
from agent_replay_journal import Journal, Journalify, diff_journals
# Import a session into canonical journal format
journal = Journalify.from_hermes("/root/.hermes/sessions/session-xyz.jsonl")
# List all tool calls
for tc in journal.tool_calls:
print(f" {tc['id']}: {tc['tool']}({tc['args']}) -> {tc['status']}")
# Resume from a named checkpoint (session branching)
resumed = journal.resumeFrom("cp_001")
# Diff two journal runs
delta = diff_journals(run_a, run_b)
print(delta.summary()) # e.g. "3 entries differ, 1 new, 2 missing"
Why agent-replay-journal?
Existing agent session exporters lock you into one agent's format. Claude Code sessions stay in Claude Code. Cursor sessions stay in Cursor. Switching agents means losing your history.
agent-replay-journal solves this by defining a vendor-neutral canonical format that any agent can emit, and providing replay and diff tools to verify session behavior across agents and code versions.
Trade-off: live replay is a stub (it detects what would be replayed without calling real tools). Use dry-run mode to compare execution paths without modifying your filesystem.
Key Features
- Canonical journal format — Schema-versioned JSON with typed tool-call and model-response entries
- Checkpoint-based branching — Mark a position in tool_calls and fork a new exploration branch via
resumeFrom(cp_id) - Journalify — Import sessions from Claude Code, Cursor, Codex, and Hermes into canonical format
- Replay engine — Dry-run or live (stub) replay of journal sessions
- Diff tool — Side-by-side and JSON diff of two journal runs
- Dual runtime — Ships as a zero-dependency Python package and zero-dependency Node.js package with identical APIs
- TypeScript declarations — Full
.d.tstype coverage for Node.js consumers
CLI Reference
journalify
Convert native agent session formats into the canonical journal.
# Import a Claude Code session
journalify --source claude-code --path ~/.claude/history/sessions/abc123 \
--output session.json
# Import a Cursor session
journalify --source cursor --path ~/.cursor/sessions/xyz789.db \
--output session.json
# Import a Codex session
journalify --source codex --path ~/.codex/sessions/session.json \
--output session.json
# Import a Hermes JSONL session
journalify --source hermes --path ~/.hermes/sessions/session-xyz.jsonl \
--output session.json
| Flag | Required | Description |
|---|---|---|
--source |
yes | Agent source: claude-code, cursor, codex, hermes |
--path |
yes | Path to the session file or directory |
--output |
yes | Path to write the canonical journal JSON |
replay
Replay a canonical journal against a target agent.
# Dry-run: show what would be replayed without executing
replay --journal session.json --dry-run \
--agent claude-code --model sonnet-4
# Live replay (stub): detect errors without calling real tools
replay --journal session.json --live \
--agent claude-code --target-dir /workspace/project
# Resume from a checkpoint
replay --journal session.json --dry-run --from-checkpoint cp_001 \
--agent claude-code --model sonnet-4
| Flag | Required | Description |
|---|---|---|
--journal |
yes | Path to the canonical journal JSON |
--dry-run |
one of | Show replay plan without executing tools |
--live |
one of | Execute tools against target directory (stub) |
--agent |
no | Target agent name (e.g. claude-code) |
--model |
no | Model name for the replay |
--target-dir |
no | Working directory for live replay |
--from-checkpoint |
no | Resume from a named checkpoint (cp_001) |
diff-journals
Compare two canonical journals.
# Human-readable side-by-side diff
diff-journals run-a.json run-b.json --format side-by-side
# Machine-readable JSON diff
diff-journals run-a.json run-b.json --format json
# Shortcut: diff identical runs
diff-journals session.json session.json --format json
| Flag | Required | Description |
|---|---|---|
<journal_a> |
yes | First journal file |
<journal_b> |
yes | Second journal file |
--format |
no | side-by-side (default) or json |
Python API
from agent_replay_journal import Journal, Journalify, diff_journals
# Journal class
j = Journal.from_json(open("session.json").read())
j = Journal.from_dict({"version": "1.0", "agent": "test@1.0", "tool_calls": []})
j.add_tool_call("read_file", {"path": "a.py"}, "file contents", "success", 12)
j.add_model_response("Done.", "tc_001")
j.add_checkpoint("tc_001", "before-fix")
resumed = j.resumeFrom("cp_001")
errors = j.validate() # list of validation error strings
is_valid = j.is_valid() # True if no errors
text = j.to_json() # serialise to JSON string
data = j.to_dict() # serialise to plain dict
repr(j) # human-readable string
# Journalify factory
j = Journalify.fromClaudeCode("~/.claude/history/sessions/abc123")
j = Journalify.fromCursor("~/.cursor/sessions/xyz.db")
j = Journalify.fromCodex("~/.codex/sessions/session.json")
j = Journalify.from_hermes("~/.hermes/sessions/session-xyz.jsonl")
# diff_journals
delta = diff_journals(j_a, j_b)
delta.summary() # e.g. "3 differ, 1 new, 2 missing"
delta.changed # list of changed entries
delta.added # list of added entries
delta.removed # list of removed entries
delta.to_dict() # machine-readable dict
Node.js API
const { Journal, Journalify, diff_journals } = require('agent-replay-journal');
// Journal class
const j = Journal.fromJSON(fs.readFileSync('session.json', 'utf8'));
const j = new Journal({ version: '1.0', agent: 'test@1.0', tool_calls: [] });
j.addToolCall('read_file', { path: 'a.py' }, 'contents', 'success', 12);
j.addModelResponse('Done.', 'tc_001');
j.addCheckpoint('tc_001', 'before-fix');
const resumed = j.resumeFrom('cp_001');
j.validate() // []
j.isValid() // true
j.toJSON() // plain object
j.toString() // JSON string
j.toolCalls // accessor for tool_calls array
// Journalify factory
const j = Journalify.fromClaudeCode('./claude-session');
const j = Journalify.fromCursor('./cursor-session.db');
const j = Journalify.fromCodex('./codex-session.json');
const j = Journalify.fromHermes('./hermes-session.jsonl');
// diff_journals
const delta = diff_journals(j_a, j_b);
delta.summary() // string
delta.changed // array
delta.added // array
delta.removed // array
delta.toDict() // plain object
Canonical Journal Schema (v1.0)
{
"version": "1.0",
"agent": "claude-code@1.0",
"model": "claude-sonnet-4",
"task": "Fix authentication bug in auth.py",
"started_at": "2026-08-09T14:23:11Z",
"ended_at": "2026-08-09T14:31:45Z",
"tool_calls": [
{
"id": "tc_001",
"type": "tool_call",
"tool": "read_file",
"args": { "path": "auth.py" },
"result": "file contents",
"status": "success",
"elapsed_ms": 12
},
{
"id": "msg_002",
"type": "model_response",
"content": "I found the issue...",
"tool_call_id": "tc_001"
}
],
"checkpoints": [
{ "id": "cp_001", "after_id": "tc_001", "label": "before-fix-attempt" }
]
}
Full schema reference: rules/journal-schema.md
Limitations
- Live replay is a stub — it detects execution errors without calling real tools. Use
--dry-runfor cross-version comparison. - Import adapters (
fromClaudeCode,fromCursor,fromCodex,from_hermes) handle the documented native formats; non-standard session files may require pre-processing. - Replay parallelism (
--parallel) is not yet implemented in the Node.js CLI. - Session files larger than 100 MB may cause memory pressure during full journalification.
Non-Goals
- Not a general-purpose diff tool for arbitrary JSON files — only canonical journals are supported.
- Not a session recorder or middleware — this library operates on exported session files, not live agent streams.
- Not a cloud service — all replay and diff happens locally.
- Not a replacement for pytest or node --test test runners — journal replay is for session verification, not unit testing.
License
MIT License — Copyright (c) 2026 prasad-a-abhishek
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 agent_replay_journal-0.1.1.tar.gz.
File metadata
- Download URL: agent_replay_journal-0.1.1.tar.gz
- Upload date:
- Size: 24.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c4b9b85d8dfaa2784bb3acbe89632d08230d0f071b897c38e231a9e8aebd917
|
|
| MD5 |
683d62706473372c4107f9a46dd5a557
|
|
| BLAKE2b-256 |
90e310d72f7e3c128c3fff9751eb4b88488738e816b3fc99e336cd3bfdafcf2a
|
File details
Details for the file agent_replay_journal-0.1.1-py3-none-any.whl.
File metadata
- Download URL: agent_replay_journal-0.1.1-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81a1563d990cacafe01db1e01b72f17ae8b8ddff2c6f5aff247052e4c8c281a9
|
|
| MD5 |
7c4173b6b639af42a30fc8fe745df7fe
|
|
| BLAKE2b-256 |
86d4a34fe5d9be02de2d3843b003a1ee96bfbb8fe4cba571f6cc55fb83333bba
|