claude-devtools

Claude Code JSONL transcript format explained

Claude Code stores every session as a JSONL file — one JSON object per line — under ~/.claude/projects/. Field-by-field reference for reading or processing transcripts directly with jq, Python, or any JSONL-aware tool.

Short answer. Claude Code session transcripts are JSONL files — one JSON object per line — stored under ~/.claude/projects/<encoded-project-path>/<session-id>.jsonl. Each line is a self-contained event: a user turn, an assistant response, a tool call, a tool result, or a system event.

This page is a practical reference for reading those files directly — useful if you're writing custom tooling, scripting an audit, or just curious about what's in there. claude-devtools is one consumer of this format; you can write others.

File layout

  • One file per session. The filename is the session UUID.
  • Append-only — Claude Code writes new lines as the session progresses; nothing is rewritten or deleted.
  • One JSON object per line. Lines are not pretty-printed.
  • The project path is URL-encoded into the parent folder name (for example /Users/you/code/my-app-Users-you-code-my-app).

For where these files live on disk, see Claude Code log locations.

Common top-level fields

Every entry has at least:

  • type — discriminator for which kind of event this is (user, assistant, system, etc.)
  • uuid — unique id for the event
  • parentUuid — id of the prior event in the conversation tree
  • timestamp — ISO 8601 string
  • sessionId — the session UUID
  • cwd — the working directory the session was started in
  • gitBranch — current branch at the time of the event (if applicable)
  • version — Claude Code version that wrote the line

type: "user" entries

User turns. The interesting payload is under message.content, which can be a string (plain prompt) or an array of content blocks (when tool results are returned to the model). Tool results appear here as tool_result blocks referencing the tool_use_id they answer.

type: "assistant" entries

Assistant responses. message.content is an array of content blocks — text, thinking, and tool_use blocks intermixed. message.usage contains the token accounting fields (input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens).

tool_use blocks

Each tool invocation has a unique id, a name (Read, Edit, Bash, Grep, Task, etc.), and an input object whose shape depends on the tool. The matching tool_result arrives in a later type: "user" entry with the same id.

thinking blocks

Extended thinking content from the model, when enabled. Plain text — no special escaping.

System and meta events

You'll also see entries for compaction boundaries, summary insertions, hook output, file snapshots, and team / subagent coordination. The exact type values evolve with Claude Code versions; check the recent lines in your own files to see what's currently emitted.

Reading the file directly

A minimal one-liner to scan a session's tool calls with jq:

jq -c 'select(.type=="assistant") | .message.content[] | select(.type=="tool_use") | {name, input}' \
  ~/.claude/projects/<encoded-path>/<session-id>.jsonl

Token usage per assistant turn:

jq -c 'select(.type=="assistant") | .message.usage' \
  ~/.claude/projects/<encoded-path>/<session-id>.jsonl

claude-devtools does the same kind of thing with a UI on top — token attribution across 7 categories, tool-call inspection, subagent execution trees, and cross-session search. If you want the full structured viewer instead of building one yourself, see installation.

Frequently asked questions

What format does Claude Code use for session logs?+

Claude Code session logs are JSONL files — one JSON object per line. Each file represents one session and lives at ~/.claude/projects/<encoded-project-path>/<session-id>.jsonl. The format is append-only; new events are written as new lines.

How do I parse Claude Code transcripts?+

Any JSONL parser works — `jq` for shell, `json.loads()` line-by-line in Python, or a streaming reader in Node. Each line has a `type` discriminator (user, assistant, system) plus `message.content`, `message.usage`, and metadata fields like `uuid`, `parentUuid`, `timestamp`, `sessionId`, `cwd`, `gitBranch`.

What is the structure of a Claude Code JSONL line?+

Top-level fields include type, uuid, parentUuid, timestamp, sessionId, cwd, gitBranch, version. Inside message.content you'll find content blocks: text, thinking, tool_use (with id, name, input), and tool_result (referencing tool_use_id). Token accounting is in message.usage with input_tokens, output_tokens, cache_creation_input_tokens, and cache_read_input_tokens.

Where can I find the Claude Code transcript files?+

Under ~/.claude/projects/ on macOS and Linux, or %USERPROFILE%\.claude\projects\ on Windows. Each project has its own subfolder; each session is a separate JSONL file named with the session UUID.

Star on GitHub

On this page