AgentsSession capture

10 — Agent Session Stores

Five supported runtimes expose capturable local session state; Amp is the exception that requires live structured-stream capture for complete evidence.

Summary

Maps session paths, formats, schemas, access methods, and stability risks across supported coding-agent runtimes. Verification cutoff: 2026-07-03. Evidence combines official docs, upstream source, and live-disk inspection on macOS (versions inspected: Claude Code 2.1.199, codex-cli 0.142.5, opencode 1.17.10, amp 0.0.1783038096, grok 0.2.67, kimi 0.21.1; Gemini via docs/source). Facts observed only on disk are marked [observed]; documented versus reverse-engineered status determines the maintenance-risk rating. jackin's roster gets full records; other agents get summaries at the end.

Question and scope

Where does each supported runtime persist session evidence, and how stable is each capture surface?

Method

The inventory combines official documentation, upstream source, and inspected local layouts for the versions recorded at the verification cutoff.

Findings

Claude Code (Anthropic)

  • Store: ~/.claude/projects/<project-slug>/<session-uuid>.jsonl; subagents under <session>/subagents/; oversized tool outputs under <session>/tool-results/ — paths officially documented (claude-directory). Slug = cwd with / and .- [observed], undocumented. XDG variant ~/.config/claude/projects/** exists on some installs — jackin's usage monitor already watches both (crates/jackin-usage/src/token_monitor/claude.rs). Also: ~/.claude/history.jsonl (prompt history), file-history/<session>/ (pre-edit snapshots), stats-cache.json (cost aggregates).
  • Format: append-only JSONL, one file per session, plaintext incl. tool I/O.
  • Schema: records carry type, uuid/parentUuid (thread tree), sessionId, timestamp, cwd, gitBranch, version, isSidechain; assistant records embed the API-shaped message with model, content blocks (text/tool_use/tool_result/thinking), usage incl. cache-creation/cache-read tokens [observed]. Record schema itself undocumented and evolving (each record self-stamps CLI version).
  • Native features: --continue, --resume <id|name>, --fork-session, /export (plain text), /rewind, /rename. Retention hazard: cleanupPeriodDays default 30 auto-deletes transcripts; --no-session-persistence exists.
  • Observer access: best-in-class — hooks deliver transcript_path push-style on every event (hooks); -p --output-format stream-json; OTel with opt-in content up to raw API bodies (monitoring).
  • Stability: paths documented, schema not; the healthiest capture target of the six regardless — largest ecosystem parses it daily.

Codex CLI (OpenAI)

  • Store: $CODEX_HOME/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl (default ~/.codex), archived sessions to archived_sessions/; source-defined (recorder.rs). Plus history.jsonl (0600) and a rebuildable SQLite metadata index state_5.sqlite [observed] — index name implies 5 schema iterations already.
  • Format: JSONL RolloutLine {timestamp, type, payload}; first line session_meta (id, cwd, cli_version, git info); then response_item (messages, function calls/outputs, reasoning), turn_context, event_msg (token counts), compacted; 2026 additions InterAgentCommunication, WorldState.
  • Native features: codex resume [id|--last], codex exec resume; --ephemeral skips persistence. No export command — the rollout is the export.
  • Observer access: codex exec --json event stream; notify hook; [otel] config (log events; only user prompts opt-in, no assistant bodies).
  • Stability: vendor explicitly treats the format as internal; Apache-2.0 source is the documentation. Déjà Vu's "pair with a vendor-blessed hedge" stance is right.

Amp (Sourcegraph)

  • Store: threads are server-authoritative (Postgres on GCP — security) — but, new finding: a full local materialization exists: ~/.local/share/amp/threads/T-<uuid>.json, one pretty-printed JSON per thread with a v revision counter, plus history.jsonl and session.json [observed, undocumented]. Same XDG path family on macOS as Linux.
  • Schema [observed]: messages[] with role, content blocks (text, thinking incl. provider/signature, tool_use, tool results), per-message usage (model, input/output/cache tokens, credits), usageLedger.
  • Native features: the richest thread CLI of any agent — amp threads list|continue|fork|share|rename|archive|compact and native exports: amp threads markdown|export|raw (manual). Visibility tiers workspace/unlisted/private; public sharing retired 2026-06.
  • Observer access: amp -x --stream-json ("Claude Code-compatible stream JSON"announcement), --stream-json-thinking; plugin event hooks (session.start, tool.call, tool.result); SDK. No OTel.
  • Stability: cloud store durable; local threads/*.json is an undocumented sync surface on near-daily releases. Capture options are better than Déjà Vu assumed (local JSON + native markdown export exist), but all unblessed except stream-json.

Kimi Code (Moonshot)

  • Store: ~/.kimi-code/sessions/<workDirKey>/<sessionId>/ where workDirKey = wd_<slug>_<sha256(cwd)[:12]>officially documented (data-locations), algorithm in MIT source (workdir-key.ts). Per-session: state.json + agents/main/wire.jsonl (+ per-subagent agents/<id>/wire.jsonl); global session_index.jsonl (append-only {sessionId, sessionDir, workDir}). Legacy Python-era ~/.kimi/sessions/<md5>/<uuid>/ still read by jackin's monitor (crates/jackin-usage/src/token_monitor/kimi.rs) — the layouts differ; capture must handle the new one.
  • Format: wire.jsonl = versioned append-only event log (first line {"type":"metadata","protocol_version":"1.4",…} [observed]) that the agent itself replays on resume — "use records, not state.json, when correctness depends on order" (source comment). Event vocabulary (complete, from records/types.ts): turn.prompt/steer/cancel, context.append_message/append_loop_event/clear/apply_compaction/undo, usage.record {model, usage} (per-turn tokens incl. cache read/creation), permission.*, plan_mode.*, full_compaction.*, goal.*, forked. Thinking persists as plaintext think parts. Migration machinery ships in-tree (records/migration/).
  • Native features: --continue, --session [id], /fork, /rename, kimi export [sessionId] (ZIP), /export-md, kimi vis (browser visualizer).
  • Observer access: --print --output-format stream-json; ACP server (kimi acp, ACP 0.23, session/update notifications); kimi server (REST/WS + OpenAPI); hooks (13 events, Beta, [[hooks]] in config.toml — no transcript_path, so the store must be located by recomputing workDirKey). No OTel (vendor analytics only, opt-out).
  • Stability: strongest of the six — documented layout, MIT source, self-versioned protocol with in-tree migrations. Churn risk = the Python→TS transition itself (three doc hosts, layouts coexisting).

OpenCode (sst)

  • Store: single SQLite DB ~/.local/share/opencode/opencode.db since v1.2.0 (2026-02-14, auto-migrated from the earlier per-file JSON storage/ tree) — release notes; Drizzle schema in source; OPENCODE_DB override; opencode db path prints it [observed on 1.17.10].
  • Schema: session rows carry parent_id (forks/subagents), directory, title, share_url, cost (USD!) and token columns (input/output/reasoning/cache read/write), model; message.data/part.data JSON blobs; part kinds text/reasoning/tool/file/patch/snapshot/compaction. The only store of the six with native dollar cost.
  • Native features: --continue, --session <id>, --fork; opencode export [sessionID] (JSON, --sanitize), opencode import <file|share URL>, opencode stats; /share public links, share: manual|auto|disabled.
  • Observer access: opencode serve — HTTP + OpenAPI + SSE GET /event bus (message/part deltas live); plugin events (message.part.updated, tool.execute.before/after, session.*); opencode db [query] SQL shell; typed SDK. Undocumented OTLP trace wiring in source (Effect spans, no transcripts).
  • Stability: CLI/server/plugins documented; DB schema source-only, 38 migrations Jan–Jun 2026. One mutable DB means no per-session file to archive — capture should prefer the server API/plugin events or export command, exactly the "E-ish" path Déjà Vu named.

Grok (xAI "Grok Build")

The blank spot in prior research, now mapped. Official CLI (grok, beta since 2026-05-14, closed source); the npm/GitHub "grok-cli" projects are unaffiliated community wrappers that also write ~/.grok/ — a collision capture must not trip over.

  • Store: officially only "~/.grok/sessions" is documented (headless docs, enterprise). Fine layout [observed 0.2.67] + bundled ~/.grok/README.md: ~/.grok/sessions/<url-encoded-cwd>/<uuidv7-session-id>/ containing chat_history.jsonl (typed records; assistant lines carry model_id, tool_calls; thinking stored encryptedreasoning.encrypted_content with readable summary only), updates.jsonl (ACP session/update stream — agent_thought_chunk here carries readable thinking, tool_call/tool_call_update, message chunks), summary.json (incl. chat_format_version, git root/branch/commit, counts), signals.json (token/latency metrics), rewind_points.jsonl, events.jsonl (undocumented telemetry-grade log), subagents/; per-cwd prompt_history.jsonl; FTS index sessions/session_search.sqlite [observed].
  • Native features: -c/--continue, -r/--resume [id], -s/--session-id, /fork, /rewind, /share (remote URL); grok sessions list|search|delete; grok export <SESSION_ID> — Markdown transcript export, present in 0.2.67 help though absent from docs; grok trace <id> (tarball; uploads remotely by default, --local to keep on disk).
  • Observer access: --output-format streaming-json (NDJSON of the same ACP vocabulary); ACP server grok agent stdio; hooks with GROK_SESSION_ID/GROK_WORKSPACE_ROOT env (Claude-compatible config shape; Grok even auto-reads Claude Code hooks/CLAUDE.md per llms.txt); no OTel.
  • Stability: weakest guarantees — beta, closed source, rapid churn (0.2.59→0.2.73 in June 2026), layout undocumented beyond the top dir; but the format self-declares chat_format_version, and updates.jsonl+ACP give a vendor-shaped event vocabulary. Déjà Vu's open question "verify in a live container" stands, now with a concrete checklist.

Cross-cutting: what a capture layer can watch (host side)

AgentWatch targetKind
Claude Code~/.claude/projects/**/*.jsonlappend-only JSONL; hooks push transcript_path
Codex~/.codex/sessions/**/rollout-*.jsonlappend-only JSONL
Amp~/.local/share/amp/threads/T-*.jsonrewritten JSON (v counter), cloud-authoritative; stream-json is the blessed live path
Kimi~/.kimi-code/sessions/wd_*/<id>/agents/*/wire.jsonlappend-only JSONL, versioned protocol
OpenCode~/.local/share/opencode/opencode.db (WAL)SQLite; prefer SSE /event / plugins / export
Grok~/.grok/sessions/<enc-cwd>/<uuidv7>/{chat_history,updates}.jsonlappend-only JSONL, undocumented, chat_format_version stamped

Retention hazards any archive must beat: Claude auto-deletes after 30 days by default; Gemini (if ever added) keeps 30 days/50 sessions; Amp's local files are a cloud sync surface; OpenCode is one mutable DB; Grok is beta-churning. jackin's own eject/prune is currently the biggest hazard of all — it deletes the restored homes wholesale (30).

OTel reality check (full table in the source survey): only Claude Code, Codex, and Gemini export OTel at all, and only Gemini (prompts on by default, gen_ai.input/output.messages in traces, direct telemetry.outfile sink) plus fully-opted-in Claude carry reconstructable content. For Amp, OpenCode, Kimi, Grok — two-thirds of jackin's roster — OTel does not exist as a capture channel. File/API surfaces are the only fleet-wide answer, confirming Déjà Vu's vector ranking empirically.

Other agents (context, summary records)

AgentStoreStatus
Gemini CLI~/.gemini/tmp/<sha256(project)>/chats/session-*.jsonlConversationRecord + MessageRecord lines with per-message tokens, thoughts, tool calls; /chat share file.md native export; richest OTel of any agent (prompts default-on, telemetry.outfile file sink)docs + source (session-management, telemetry); 30-day/50-session retention
Cursor IDEstate.vscdb SQLite (cursorDiskKV: composerData:*, bubbleId:*) in globalStoragereverse-engineered only; churns with releases (01)
Cursor CLI~/.cursor/chats/<md5(cwd)>/<uuid>/store.db SQLite blob DAGreverse-engineered; SpecStory reads it via topological sort (02)
Copilot (VS Code)workspaceStorage/<hash>/chatSessions/*.json; native Chat: Export Chat... JSONsemi-documented
aider.aider.chat.history.md — native markdown in-repodocumented; oldest native archive
ClineVS Code globalStorage tasks + per-task markdown exportcommunity-documented
Windsurfencrypted protobufsclosed — SpecStory maintainer: "thrown away the key" (#26)

Implications for jackin

Implement provider-specific adapters with explicit evidence and stability labels, plus a structured-stream capture path for Amp.

Limitations and unknowns

Local layouts and undocumented schemas can change between releases; Kimi and Grok paths require in-container verification before relying on them.

Sources

On this page