skills

Native session schemas

These pages document the on-disk session transcript formats of the three runtimes this repository reads: Codex CLI, Claude Code, and Cursor. They describe the providers' native formats, not this repository's parsers. For how the repository reads these files, see Shared transcript-core.

Everything here was derived from recorded sessions, not from provider documentation or third-party parsers. None of the three providers publishes a stable schema for these files, and they change between client releases.

How to read these pages

  • Observed, not guaranteed. Each page states its sample, date, and client-version range. "Not observed" means no sampled file contained the shape. It never means the shape does not exist.
  • Versioned where the transcript allows it. Codex and Claude Code record a client version in the transcript, so shapes are tied to version ranges. Cursor records no version, model, or timestamp, so its shapes are tied to the observation date only.
  • Structure only. The pages contain field paths, JSON types, enum vocabulary, and counts. Examples are skeletons with placeholders. No recorded content is reproduced.
  • Evidence strength is explicit. A native id that links two records is strong evidence. A link inferred from turn, order, or position is weaker and is labelled as such. A missing field is never treated as proof of success.

Cross-runtime comparison

QuestionCodexClaude CodeCursor
Client version in transcriptYes (session_meta.payload.cli_version)Yes (version on records)No
TimestampsYesYesNo
File identityFirst session_meta payload.id, equal to the filename uuidsessionId; one per fileThe file path only
Native tool-call idcall_idtool_use.id / tool_result.tool_use_idNone; identity is positional
Tool results recordedYesYesNo
Structured exit codeYes, in the separate item_completed stream onlyNoNo
Per-call failure flagitem.status in the item_completed stream (attributing it to a specific call is an inferred join)is_error: true on the result blockNone; turn-level turn_ended.status only
Subagent transcriptsSeparate rollout file; id != session_idSeparate file under <session-id>/subagents/ plus .meta.jsonSeparate file under <session-id>/subagents/
Parent names its childrenYes, via SubAgentActivity.agent_thread_idYes for directly spawned subagents, via the Agent tool result's agent id and the child's .meta.json toolUseId; workflow-spawned children join by directory onlyPartly; child id appears in the parent in a minority of pairs
Oversized tool outputTruncated in place at fixed byte caps, no markerPersisted to <session-id>/tool-results/; path only in toolUseResult.persistedOutputPathProbably spilled to agent-tools/ files, not attributable to a call
Token usageCumulative and per-turn recordsPer message, repeated on every content-block recordNone
Skill evidenceHistorical experimental read_file.file_path; removed upstream March 2026 and absent locallyTop-level attributionSkill, structured Skill calls, and names-only availability/invocation attachmentsInferred from structured Read/ReadFile paths ending in SKILL.md

Reader requirements that follow from the evidence

  • Split records on the LF byte only. U+2028 and U+2029 occur unescaped inside string values; the abandoned scanner treated them as record boundaries and reported valid records as malformed, while LF-byte splitting parsed the sampled records.
  • Do not assume one header per file (Codex child files can carry an inherited parent header) or one record per logical message (Claude Code writes one assistant record per content block).
  • Do not use a message or item id where a call id is required. In Codex the two differ in almost every call.
  • Treat inherited parent history in Codex child files as context, not as the child's own activity.
  • Keep native skill attribution, recorded invocation, availability, and inferred direct file reads as separate evidence. Do not parse shell commands, prose, or instruction bodies to manufacture a skill load.

None of the three native transcript formats records a skill version. An installed-file or Git revision selected for the transcript timestamp is inferred context, may be unknown, and cannot prove the revision that executed.

The activity reader keeps usage as captured-source metadata. It deduplicates Claude Code by exact session and message.id, keeps Codex cumulative, last-turn, and response-joinable records separate, and labels Codex samples by native ownership without carrying reset state or model joins across ownership boundaries. Response identity uses native thread_id; session_id remains root context. Cursor usage is not-recorded. It never treats a missing counter as zero or converts tokens to money.

Source-level skill-name coverage uses source-skill-names, separate from per-event attribution, invocation, or inferred file-read evidence. Claude Code empty skill_listing.names and invoked_skills.skills arrays are available with zero captured names, absent carriers are not-recorded, available names retain the latest locator per name, and invoked names remain per occurrence. The captured count includes both sets. Optional captured-source skill and usage metadata is reduced before delivered event groups when a report reaches its byte budget; omission counts retain the complete captured-source totals.

Repository parser support

The repository now has tested opt-in activity readers for the three documented transcript surfaces. This implementation status does not strengthen or extend the native-format observations on these pages.

RuntimeTested activity support
Claude CodeRecorded calls/results and native IDs, persisted-output and child references as explicit not-read; referenced sidecars and child trajectories are not read.
CodexResponse/item carriers, exact recorded joins, ownership from native lineage and inherited-history boundaries; unknown ownership remains unknown.
CursorPositional frame/block calls, settled stateful delivery, pending-lifecycle stateless review, results not-recorded, per-call outcome unknown.

Session Observer and Session Export Transcript read each selected source once when activity is enabled. Their reports preserve source/delivery locators, bounded previews, omission counts, unread/unavailable coverage, and extraction diagnostics. See Shared transcript-core for budgets and consumer semantics.

Discovery indexes

Besides transcripts, Claude Code and Codex keep small index files that Session Search reads before opening any transcript. Like the transcripts, they are internal provider files with no published schema and may drift between client releases. The fields below are the ones the repository reads; readers should probe for them and degrade rather than fail when one is missing.

FileRuntimeFields read
~/.claude/history.jsonlClaude CodeOne record per typed prompt: display, project (cwd), sessionId, timestamp (epoch milliseconds). Records also carry pastedContents, which is not read.
~/.codex/history.jsonlCodexOne record per typed prompt: session_id, ts (epoch seconds), text.
~/.codex/session_index.jsonlCodexid, thread_name, updated_at. Covers only some threads.
~/.codex/state_5.sqlite, table threadsCodexid and rollout_path (required), title, first_user_message, cwd, created_at, updated_at, archived, git_origin_url, source.
~/.codex/archived_sessions/rollout-*.jsonlCodexArchived rollout transcripts with the same format as sessions/; a thread's archived flag marks them.

Read the SQLite database read-only (sqlite3 -readonly) and check PRAGMA table_info(threads) before querying. Treat created_at and updated_at as untyped: the repository's reader accepts epoch seconds, epoch milliseconds, or ISO strings. A threads.source value carrying a subagent key marks an agent-authored thread. Cursor keeps no comparable prompt-history or thread index for its agent transcripts.

Keeping these pages current

The evidence behind these pages is a dated snapshot under .oat/repo/reference/research/session-schemas-2026-09-18/, produced with the structure-only inventory.mjs script in that directory. The script emits only human-reviewed vocabulary and ships with synthetic privacy canary tests. When a client update changes a format, run a new inventory, add a new dated snapshot, and update the affected page with the new version range. Do not edit an old snapshot.

Contents

  • Codex session schema — Rollout JSONL: identity and subagent lineage, the two tool-activity streams, outcome evidence, and silent output caps.
  • Claude Code session schema — Project JSONL and sidecar layout: tool blocks and toolUseResult, subagent files, usage duplication, persisted output.
  • Cursor session schema — Agent-transcript frames: calls without ids or results, turn lifecycle, and off-transcript tool output.

On this page