Back to Blog

Parsing Claude Code's JSONL Format for macOS Dev Tools

Fazm Team··2 min read
claude-codejsonlmacosdev-toolsparsing

Parsing Claude Code's JSONL Format for macOS Dev Tools

Claude Code stores everything locally in ~/.claude/ as JSONL files. If you are building macOS dev tools that need to understand what Claude Code is doing - or has done - you need to parse these files. The format is not officially documented, so here is what we have learned from reading a lot of them.

The File Structure

Conversation logs live in ~/.claude/projects/ organized by project path. Each conversation is a .jsonl file where every line is a JSON object representing one event. Events include user messages, assistant responses, tool calls, and tool results.

The tricky part is that tool calls are nested. A single assistant turn might contain multiple tool uses - a file read, then an edit, then a bash command - each with their own result objects on subsequent lines.

Parsing Strategy

The straightforward approach is to read line by line and build a conversation tree:

import json

def parse_conversation(path):
    events = []
    with open(path) as f:
        for line in f:
            if line.strip():
                events.append(json.loads(line))
    return events

But the real work is interpreting the events. Tool call objects have a type field that tells you what happened - tool_use for when Claude calls a tool, tool_result for the response. File edits show up as tool calls to the Edit or Write tools with the full file path and content.

What Makes This Hard

The format evolves. Fields get added, tool names change, and the nesting structure shifts between versions. If you are building something production-grade, you need to handle missing fields gracefully and version-detect based on what fields are present.

The biggest gotcha is that conversation files can get large - a long coding session might produce a JSONL file that is hundreds of megabytes. Stream-parse instead of loading everything into memory.

For macOS native tools, Swift's JSONSerialization works but you will want to use a streaming JSON parser for the larger files. Read line by line, parse each line independently, and filter for the event types you care about.

Fazm is an open source macOS AI agent. Open source on GitHub.

Related Posts