claude-render-transcripts

Renders a Claude Code session .jsonl transcript into readable plain text.

Claude Code stores every session as newline-delimited JSON. Headless runs (claude -p ..., entrypoint: sdk-cli) are written to disk but filtered out of the VS Code /resume picker, so this tool is how you read them back.

Usage

uv run claude-render-transcripts.py <transcript.jsonl> [more.jsonl ...] > out.txt

Takes one or more .jsonl paths as arguments and writes to stdout. Pure standard library — uv just handles the Python version; there are no third-party dependencies.

In practice you rarely invoke it by hand: start a fresh Claude Code session in the repo and ask it to, for example, "use claude-render-transcripts to render the transcripts from the job that ran overnight", and it finds the session files and runs the tool for you.

Where the transcripts live

Under ~/.claude/projects/<slugified-cwd>/, where the slug is the working directory with / turned into - (so a cwd of /home/you/dev/tools becomes -home-you-dev-tools):

<session-id>.jsonl                       # the main (orchestrator) session
<session-id>/subagents/agent-*.jsonl     # one file per spawned subagent
<session-id>/subagents/agent-*.meta.json # {agentType, description, model, ...}

Each subagent's .meta.json gives its description and model — handy for naming the rendered output.

Output

For every user / assistant message it prints a header (ROLE HH:MM:SS) followed by the body. Block types are flattened as:

tool_use inputs and tool_result bodies are truncated at 2000 chars (... [truncated]). Queue operations, attachments, ai-title, and API-error records are skipped.

Convention in this folder

Rendered transcripts are grouped one directory per night (transcripts/YYYY-MM-DD/), with the orchestrator as 00-main.txt and each subagent named <description> [<model>].txt. The whole transcripts/ folder is gitignored.

Contents

📄claude-render-transcripts.py1.4 KB
📄README.md2.1 KB