Expand description
Natively load — and continue — real Claude Code and Codex sessions.
Both tools persist their conversations as JSONL on disk:
- Claude Code:
~/.claude/projects/<encoded-cwd>/<session-id>.jsonl, one line per event in the Anthropic message format, linked byuuid/parentUuid. - Codex:
~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl, where each line is a{timestamp, type, payload}envelope and theresponse_itemlines form the canonical conversation.
Session::load auto-detects the format and normalizes either one into a
provider-neutral Vec<ChatMessage> that can be handed straight back to a
model (via OpenRouter or any OpenAI-compatible endpoint) to continue.
Provider-internal artifacts that don’t replay across vendors — Anthropic
thinking blocks, Codex reasoning items — are dropped during
normalization.
§Where this sits in supercode’s priorities
This module is the home of feature 1 (translate between session formats)
and half of feature 2 (emulate-to-continue) — the load/emit surface for
each harness (SessionFormat, from_*_str loaders, to_*_jsonl
emitters). See AGENTS.md for the three ranked
feature-priorities and the glue-tool positioning; the top priority is
feature 3 (continue losslessly with massive token reduction), which
this fidelity work exists to make trustworthy. opencode + pi loaders
are built against the frozen docs/interop/opencode-pi-spec.md contract
— OpenCode additionally reads its native SQLite store (opencode*.db,
PARITY-3/PARITY-16) via rusqlite, reconstructing the same envelope form
Session::from_opencode_str already parses for the JSON-tree surfaces.
Structs§
- Open
Code Sqlite Store Stats - Cheap store-level counts —
COUNT(*)only, no row hydration — forinspect’s “reports the audited real store’s sessions, messages, and parts” summary (PARITY-3 AC01). - Session
- A normalized, replayable conversation loaded from a tool’s session log.
- Session
Meta - Metadata recovered from a session log.
Enums§
- Open
Code Storage Surface - Which on-disk OpenCode storage surface is present under a data root
(
docs/interop/opencode-pi-spec.md§1.2/S9a): SQLiteopencode*.db(or$OPENCODE_DB), legacy JSON tree generation B, or legacy JSON tree generation A. This is a filesystem classifier only — it answers “which generation is this?” for a corpus-discovery tool; it does not itself read/parse the surface. SeeSession::from_opencode_str’s docs for the envelope form any of these three surfaces synthesizes into, andSession::from_opencode_sqlite(PARITY-3/PARITY-16) for therusqlitereader that reconstructs that same envelope form fromSqlite’s rows —JsonTreeA/JsonTreeBremain classifier-only (theirsession_diffround-trips via the JSON store per upstream’s own behavior even on a SQLite install, so nothing is silently lost by not reading the legacy trees directly). - Session
Format - An on-disk session format supercode can both read and write.
- Session
Source - Which tool produced a session log.
Constants§
- OPENCODE_
COMPACTED_ TOOL_ PLACEHOLDER - The placeholder opencode’s own replay substitutes for a
toolpart’s output oncestate.completed.time.compactedis set (message-v2.ts:293-296 @fd9ee43) — the REAL output is never actually erased from the record (S1); it survives inrawand in this loader’smetadata["oc_tool_output_compacted"].
Functions§
- detect_
opencode_ storage_ surface - Probe
data_root(e.g.~/.local/share/opencode) for the OpenCode storage surface present, per the discovery rules frozen indocs/interop/opencode-pi-spec.md§1.2/S9a:$OPENCODE_DBwins outright; otherwise globopencode*.db(not justopencode.db— dev/beta channels suffix the filename,database.ts:43-55); otherwise look for the JSON tree generation-B marker (storage/migration); otherwise generation-A’sproject/subtree. ReturnsNoneif nothing is found. - looks_
like_ sqlite - Whether
pathshould be routed to the OpenCode SQLite loader instead of the UTF-8 text path (PARITY-16): true when the file’s first 16 bytes are the SQLite magic, OR its extension is.db— the latter so a corrupted/truncatedopencode*.dbstill getsrusqlite’s own “not a database” diagnostic (PARITY-3 AC03) instead of a confusing UTF-8 error. A non-existent path is NOT considered SQLite here — the missing-file diagnostic in that case comes from the normal load path (with_contextat the CLI call sites), which already names the path clearly. - opencode_
sqlite_ corpus_ envelope_ text - Combined envelope text spanning every session in
db_path(or up tolimit_sessions) — for corpus-style scanning (the OpenCode SQLite corpus-audit path, PARITY-4). Safe to concatenate multiple sessions’ records into one text even thoughSession::from_opencode_stritself only keeps the LASTsessionline (single-session semantics) — the audit line-classifier (audit_opencode_line) scores each line independently and doesn’t care about session boundaries. UseSession::from_opencode_sqliteto load one session as a realSession. - opencode_
sqlite_ primary_ id - D6: the same “most-recently-updated top-level session” selection
Session::load/Session::from_opencode_sqlitemake by default when no explicit session id is given — exposed so a CLI-level warning can name which one was chosen. - opencode_
sqlite_ session_ ids - D6: list every session id in an OpenCode SQLite store (oldest first) —
exposed so CLI callers (
convert,inspect) can detect a multi-session store and warn beforeSession::load/Session::from_opencode_sqlitesilently picks just the primary one. Previously nothing surfaced this:convert opencode.db --to Xconverted 1-of-N sessions with no warning and no way to name a different one. - opencode_
sqlite_ store_ stats - Count sessions/messages/parts/todos in a real OpenCode SQLite store without loading any of them (PARITY-3 AC01).
- resolve_
opencode_ parent_ tool_ use_ ids - Resolve each opencode subagent (
task) child session’smeta.parent_tool_use_idfrom its parent’s owntasktool partcallID(docs/interop/opencode-pi-spec.md§2.1 — the analogue of Claude Code’sagentId/parent_tool_use_idlinkage,opencode-fields.mdtask.ts:145,171-176).