The shared durable ledger
The ledger is the single most important idea in ContextRelay. Two agents that cannot read each other's minds need a place to leave durable, ordered, shared context - and that place is a local append-only JSONL file. Everything else (handoffs, deliberation, task lanes, finality, crash recovery, audit) is built on top of it.
What the ledger is
For each shared session, ContextRelay writes an append-only JSONL log on your own machine. One JSON object per line, never edited in place, only appended.
The file lives under the project's .contextrelay/ directory:
.contextrelay/
|-- config.json # project policy (coordinator, permissions, autonomy)
|-- current # pointer to the active session id
|-- sessions.json # named runtime-session registry
|-- sessions/
| `-- session_<epoch>_<hex>.jsonl # the shared durable ledger (one file per session)
`-- state/
|-- transcript.jsonl # runtime transcript
|-- queue.db # Claude-bound message queue (SQLite)
|-- status.json # latest daemon/session status snapshot
|-- daemon.pid / daemon.lock # daemon process + lock
`-- ... # tokens, ports, logs, pids
Two things are easy to mix up, so to be precise:
.contextrelay/sessions/<sessionId>.jsonlis the ledger - the durable, auditable record of the collaboration..contextrelay/state/is runtime plumbing - pids, locks, tokens, ports, the SQLite delivery queue, a runtime transcript, and status snapshots. It is not the audit record.
Each session id looks like session_<epoch-millis>_<8-hex> (for example
session_1717603200000_a1b2c3d4), and .contextrelay/current records which
session is active.
ContextRelay writes a separate .jsonl file per shared session. When you use
named runtime sessions (for example a side worktree for review), untagged
entries stay visible to every runtime session as shared audit history, while
explicitly tagged entries can be scoped to one runtime session. Treat the ledger
as one shared record per session, not as isolated private logs.
Why it exists
Claude Code and Codex run as two separate processes. Neither can see the other's hidden reasoning - only what is written down. (See Why two agents in one session.) Live messages help in the moment, but they are ephemeral. The ledger is the durable layer that makes the collaboration real:
- Shared context. It is the only place both agents can rely on for goals, plans, decisions, files touched, blockers, and next steps.
- Authority for recovery. If a process crashes or you close a terminal, the
ledger is what
ctxrelay recoverreads to reconstruct where things stood - recent failures, interrupted commands, and a resume prompt. - Authority for finality. Whether work is "done" is decided from ledger evidence (proposals, gate results, blockers), not from an agent's say-so. See Finality and human sign-off.
- Audit. Because it is append-only and local, you get a faithful record of what the agents actually did before you ship - and it never leaves your machine.
What it records
Every collaboration event becomes a ledger entry. Each entry is a small JSON object with a stable shape:
{
"schema": "v1",
"id": "f3c0…",
"timestamp": 1717603200000,
"sessionId": "session_1717603200000_a1b2c3d4",
"type": "handoff",
"source": "claude",
"target": "codex",
"content": "Implement the retry backoff in client.ts"
}
The entry type is one of: session_started, message, handoff,
runtime_event, error, and entries that additionally carry a structured
artifact. So the ledger captures:
- Messages between Claude and Codex (every
reply/send_to_claude). - Handoffs - structured delegations with a reason, an ask, and a target.
- Notes - durable context written with
append_note. - Artifacts - structured evidence written with
record_artifact. - Runtime events and errors - session lifecycle, failures, and recovery signals.
Artifacts the ledger carries
Artifacts are the structured evidence that drives task lanes, release readiness, and finality. The supported artifact kinds are:
patch_summary
release_gate
test_report
command_log
escalation_suggestion
idle_opportunity
idle_action_result
idle_fleet_result
idle_evaluation_result
idle_write_result
Each artifact carries a status so consumers can reason about outcomes:
passed
failed
blocked
unknown
skipped
timed_out
Before an entry is written, its content is redacted and truncated, and the write is taken under a per-session lock and flushed atomically. Entries are never rewritten - corrections are new appends. That is what makes the log trustworthy as an audit trail.
How agents use it
Agents do not touch the .jsonl file directly. The daemon is the single
writer of record - it owns the ledger, serializes appends, and derives state
from it. Both Claude and Codex go through the daemon using the same shared MCP
tools (the Codex names are listed where they differ):
| Tool | What it does against the ledger |
|---|---|
read_context | Returns recent ledger entries plus the latest active handoff - a derived "still-waiting" field - so you can resume without re-reading the whole log. |
append_note | Appends a durable note (goal, plan, decision, blocker, next step). |
record_artifact | Appends a structured artifact (one of the kinds above) with a status. |
task_state | Derives task lanes, policy state, artifacts, and finality blockers from the ledger. |
session_info | Returns a session summary with ledger counts, the active handoff, and policy/autonomy/finality state. |
The "latest active handoff" is computed, not stored as a separate flag: ContextRelay scans the entries, finds the most recent handoff per target, and drops any that a later note or message marked as handled. That is how a peer (or a future recovery) knows what is still owed without parsing the entire file.
Because hidden reasoning is invisible, the single most useful habit in
ContextRelay is to write your goal, current plan, files touched, blockers,
decisions, and next step into messages and the ledger. Do it before handing
off, before a long-running step, and whenever the plan changes - so the peer
agent and ctxrelay recover can pick up exactly where you left off.
Inspect the ledger yourself
You never need to open the raw file, but you can. To see derived state and counts from the command line:
# Daemon, session, connection, ledger, task, autonomy, and finality state
ctxrelay status
# Machine-readable snapshot
ctxrelay status --json
# Reconstruct context after a crash or a closed terminal
ctxrelay recover
You can also open the browser viewer, which renders task lanes, artifacts, policy, and a timeline built from the same ledger:
ctxrelay viewer
The browser viewer is read-only for agent work - it cannot send messages or do the agents' work for them - but it can clear the current shared session history through its authenticated endpoint. Clearing the ledger discards the audit trail for that session, so treat it as a deliberate action, not routine cleanup.
Next steps
- Coordinator and git-write policy - who is allowed to act on what the ledger records.
- Finality and human sign-off - how ledger evidence becomes a "done" decision.
- Handoffs, replies, and deliberation - the events that fill the ledger during a session.
- Troubleshooting and recovery - using the ledger to recover after a crash.