Share session data from any coding agent.
About
·
Installation
·
Session Format
·
Supported Agents
·
Documentation
Capture AI agent sessions from any agentic coding tool as part of your repository's history and reference them during code review.
- Global hooks are initialized in each agent's config directory.
- As the agent works, every event (prompts, tool calls, responses) is captured to a central store outside your repo.
- At each turn boundary, that turn's events are written into
.sessions/as a new JSONL file — one per turn, inside a per-session directory. Files already written are never rewritten, so capture only ever adds to your working tree. - A repo gets nothing until the agent changes a file in it, and a session spanning several repos is written into each one it touched.
Note
Right now, only MacOS/Linux operating systems are supported.
Native Install (Recommended):
curl https://assert.dev/install -fsS | bashHomebrew:
brew install assert-labs/tap/assertNPM:
npm install -g @assertlabs/cliFrom Source:
git clone https://github.com/Assert-Labs/cli.git
cd cli
pnpm install
pnpm build
npm install -g .# Initialize hooks for all supported agents
assert initRestart your agent (or reload its plugins) after assert init so it picks up
the newly installed hooks.
Install order doesn't matter. assert init pre-installs the hook for every
supported agent — including ones you haven't installed yet — into that agent's
standard plugin directory. An agent you install later auto-discovers the hook
on its first run, no re-init required. You can still re-run assert init any
time to refresh hooks (e.g. after upgrading assert, or to pick up an agent's
version-specific features), or assert init <agent> to (re)install just one.
- macOS or Linux, x64 or arm64 (no Windows or Alpine/musl build yet)
gitavailable on your PATH — the CLI shells out to git at runtime- If installing via NPM or from source:
Node.js 18 or later
Sessions are JSONL: one JSON event per line, in one schema regardless of which
agent produced them. Every event carries a type, a sessionId, and an ISO
timestamp.
Agents disagree about everything else — Claude Code reads a file with
Read {file_path}, OpenCode with read {filePath}, Pi with read {path}, and
Codex edits by passing a whole patch blob under command. Each agent's adapter
resolves that at capture time, so every tool_call carries a canonical
action alongside the tool's own name:
action.kind is one of read, edit, write, delete, search, web,
command, task, todo, or other, with paths, command, query, and
url carrying the details. A tool the adapter doesn't recognize (a new
built-in, an MCP tool) is reported as other rather than guessed at.
Read action; treat toolName as a display label and input as debugging
detail. @assertlabs/cli/core exposes parseSession(), which returns this
model with linked turns and prompts (and fills in action for captures written
before it existed).
- Codex support requires the modern Codex CLI (the Rust build with hooks); the legacy
@openai/codex(0.1.x) has no hook support, andassert initwarns when it finds only that version. - If you would like support to be added for a particular agent, take a look at CONTRIBUTING.md and look to see if that agent will be added soon in open issues and pull requests.
assert init [agent] # Initialize hooks globally (all agents if none specified)
assert sessions # List sessions in current directory (--all for central storage)
assert show <session-id> # Show session details
assert blame <file> # Show line-by-line agent attribution (like git blame)
# [--json | --ndjson] [--range <start>:<end>]
assert blame --diff <a>..<b> # Attribute only a diff's added lines (PR review)
assert trace [ref] # Export agent-trace attribution for a revision (default HEAD)
assert status # Show current status
assert private # Keep capturing, but stop writing sessions into this repo
assert public # Resume writing sessions into this repo (default)
assert sync # Publish local-only sessions into the repo + rebuild blame index
assert cleanup # Mark stale still-open sessions ended (default idle > 24h; --hours <n>)
assert redact <target> # Redact current-turn, last-tool-input, or last-tool-output
assert disable # Pause capture (hooks stay installed)
assert enable # Resume capture
assert help # Show helpSession data is written into a repo's .sessions/ as the agent works, so it
shows up in git status like any other file — you stage and commit it yourself.
- Skip files: add a
.assertignoreto the repo root (gitignore-style patterns, e.g.dist/,*.log). Changes that only touch ignored paths won't trigger capture or appear in session data. - Turn off persistently:
assert disablepauses capture (hooks stay installed) until you runassert enable.assert statusshows the current state. - Turn off for one session: set
ASSERT_DISABLE=1in the environment your agent runs in. - Keep sessions local:
assert privatekeeps capturing to the central store but stops writing into this repo's.sessions/;assert public(the default) resumes.assert syncpublishes any local-only sessions into the repo and rebuilds the blame index — handy after switching branches or going public.
Captured sessions can be exported as Agent Trace
records — an open standard for AI code attribution
(spec & reference). assert trace
derives a conformant TraceRecord for a revision from your committed session
data (attributing lines to the contributing model), so any tool can consume the
attribution:
assert trace # agent-trace record for HEAD
assert trace <ref> # for a specific commitThis repository is licensed under the MIT License

{ "type": "tool_call", "timestamp": "2026-07-20T10:00:03.000Z", "sessionId": "…", "turnId": "…", "toolCallId": "…", "toolName": "apply_patch", // the agent's name for the tool "action": { // the canonical, cross-agent view "kind": "edit", "paths": ["src/a.ts"], // repo-relative, POSIX }, "input": { "command": "*** Begin Patch…" }, // the agent's raw payload }