# 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.

Source: https://groundedby.com/guides/whats-inside-an-agent-session-file (updated 2026-10-29)

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:

```json
{"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`:

```json
{"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](/evaluate).

## Read your own

```bash
# 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

- [Claude Code docs, the .claude directory](https://code.claude.com/docs/en/claude-directory)
- [openai/codex source, rollout storage](https://github.com/openai/codex/tree/main/codex-rs/rollout/src)
