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 eventparentUuid— id of the prior event in the conversation treetimestamp— ISO 8601 stringsessionId— the session UUIDcwd— the working directory the session was started ingitBranch— 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>.jsonlToken usage per assistant turn:
jq -c 'select(.type=="assistant") | .message.usage' \
~/.claude/projects/<encoded-path>/<session-id>.jsonlclaude-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.
Related
- Where are Claude Code logs stored?
- Reading Claude Code session transcripts
- claude --verbose vs claude-devtools
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.