Skip to content
groundedby
Waitlist

Format

What is inside an AI agent session file

A field-by-field look at Claude Code and Codex session files - records, messages, tool calls, results and token usage - and what each reveals about how the work went.

Updated October 29, 2026 // Markdown

A session file is the full record of a person and an agent working together. Both Claude Code and Codex write JSON Lines: one JSON object per line, appended as the session runs. Here is how to read one.

Claude Code

Each line is a record. The ones that matter:

{"type":"user","timestamp":"2026-10-29T09:14:02.511Z","sessionId":"7f3c...","uuid":"a1...","parentUuid":null,"cwd":"/Users/you/dev/app","gitBranch":"main","version":"2.1.312","message":{"role":"user","content":"Add a waitlist form to the homepage"}}
{"type":"assistant","timestamp":"2026-10-29T09:14:09.002Z","message":{"role":"assistant","model":"...","content":[{"type":"text","text":"I'll look at the homepage first."},{"type":"tool_use","id":"toolu_01...","name":"Read","input":{"file_path":"app/page.tsx"}}],"usage":{"input_tokens":1200,"output_tokens":85}}}
{"type":"user","timestamp":"2026-10-29T09:14:09.120Z","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_01...","content":"..."}]},"toolUseResult":{}}

What to notice:

  • Turns. A person's message is a user record whose content is text. A tool result is also a user record, with tool_result content. Only the first kind is a turn.
  • Tool calls are tool_use blocks in assistant content: Bash, Read, Edit, Write, Grep, web tools, and MCP tools named mcp__<server>__<tool>.
  • The chain. uuid and parentUuid link records, so branches and retries can be rebuilt.
  • Cost. message.usage holds token counts per reply.
  • Context. cwd, gitBranch and version say where and with what it ran.

Subagents write their own transcripts under the session's subagents folder, and large tool outputs are stored apart in tool-results.

Codex CLI

Each line has a type, a timestamp and a payload:

{"timestamp":"2026-10-29T09:14:02.511Z","type":"session_meta","payload":{"id":"...","cwd":"/Users/you/dev/app","cli_version":"0.166.0"}}
{"timestamp":"2026-10-29T09:14:03.020Z","type":"response_item","payload":{"type":"message","role":"user","content":[{"type":"input_text","text":"Add a waitlist form"}]}}
{"timestamp":"2026-10-29T09:14:08.700Z","type":"response_item","payload":{"type":"function_call","name":"shell","arguments":"{\"command\":[\"bash\",\"-lc\",\"ls app\"]}"}}
{"timestamp":"2026-10-29T09:14:09.100Z","type":"event_msg","payload":{"type":"token_count"}}
  • Turns are response_item messages with role user.
  • Tool calls are function_call items; shell commands carry the command in arguments.
  • Events (event_msg) mark task start and end and token counts.
  • Older files are compressed to .jsonl.zst. Read them with zstd -dc.

What a session reveals

Read in order, a session file shows things no other record does:

  • How long the work really took, from the gaps between timestamps.
  • Where the agent got stuck: repeated tool calls, errors in results, a person stepping in.
  • Which tools and products it reached for, and in what order.
  • How the person steered: corrections, approvals, changes of plan.

That is why these files are useful for learning about your own work, and why buyers pay for them. Count yours with the evaluator.

Read your own

# The ten tools Claude Code used most in one session
jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' ~/.claude/projects/*/<session>.jsonl | sort | uniq -c | sort -rn | head

# Turns typed by a person
jq -r 'select(.type=="user" and (.message.content|type)=="string") | .timestamp' <session>.jsonl | wc -l

Questions

Are session file formats documented?+

Partly. Anthropic describes Claude Code's transcript format as internal and subject to change. Codex's format is visible in its open-source code. Treat field names as a snapshot and check them against your own files.

How do I count tool calls in a Claude Code session?+

Count tool_use blocks inside the content of assistant records. With jq - jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' session.jsonl | sort | uniq -c

Sources

  1. Claude Code docs, the .claude directory
  2. openai/codex source, rollout storage

Waitlist

Your sessions, your call.

We are building an opt-in marketplace where developers license redacted sessions they pick, one by one. Join to hear first.

Your email and the side you picked. Nothing else. Privacy