Where Claude Code Stores Your Transcripts (and How to Actually Use Them)
Quick answer
Claude Code writes every session to a JSON Lines file under your home directory:
~/.claude/projects/<encoded-project-path>/sessions/<session-id>.jsonl
On macOS and Linux that's ~/.claude/projects/. On Windows it lives at %USERPROFILE%\.claude\projects\. Each file is one Claude Code session. Each line in the file is one event — user message, assistant response, tool call, tool result, or system metadata.
That's the whole answer. The rest of this post explains how to actually do something with it.
The projects/ directory structure
Claude Code keeps one directory per project, named by encoding the absolute path. The encoding replaces / with -:
~/.claude/projects/
├── -Users-you-Documents-GitHub-myrepo/
│ └── sessions/
│ ├── 01J8K3Q5R...jsonl
│ ├── 01J8L2M8N...jsonl
│ └── 01J8M0P1Q...jsonl
├── -Users-you-code-side-project/
│ └── sessions/
│ └── 01J8N2R3S...jsonl
└── -Users-you-Documents-throwaway/
└── sessions/
└── 01J8P5Q6R...jsonl
So if you ran Claude Code in /Users/you/Documents/GitHub/myrepo, the corresponding directory is ~/.claude/projects/-Users-you-Documents-GitHub-myrepo/. The session IDs are ULIDs — lexicographically sortable, so listing sessions/ shows the oldest session first.
# List your most recent Claude Code sessions across all projects
find ~/.claude/projects -name "*.jsonl" -print0 \
| xargs -0 ls -lt \
| head -10
Anatomy of a session JSONL file
Each session file is plain JSON, one record per line. The schema has evolved across Claude Code versions, but the recent format looks roughly like this (real records simplified for readability):
{"type":"user","message":{"role":"user","content":"Why is my test failing?"}}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"Let me look at the test file..."},{"type":"tool_use","name":"Read","input":{"file_path":"test.spec.ts"}}]}}
{"type":"tool_result","tool_use_id":"toolu_01...","content":"...file contents..."}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"The assertion expects 2 but the function returns 3 because..."}]}}
The interesting record types you'll see:
user — what you typed
assistant — Claude's response, including any tool calls it decided to make
tool_use (nested inside an assistant message) — a single tool invocation: Read, Edit, Write, Bash, Grep, Glob, Task, etc.
tool_result — what came back from the tool (file contents, command stdout, error message)
summary — generated by Claude Code when conversations get long enough to compact
Because it's JSONL, every standard Unix text tool works on it. No special parser needed.
Things you can actually do with this data
Find that prompt you half-remember
# Search every session across every project
grep -lr "the bug with the auth middleware" ~/.claude/projects/
This returns the file paths of sessions containing that string. Open the JSONL file in your editor, search for the line, scroll to the surrounding context.
Extract just your user messages
# Pretty-print every user message from a session
jq -r 'select(.type=="user") | .message.content' \
~/.claude/projects/-Users-you-Documents-GitHub-myrepo/sessions/01J8K3Q5R*.jsonl
Useful when you want to see what you asked, separated from Claude's responses.
See every tool call from a session
# All tool invocations, with their inputs
jq -r 'select(.message.content[]?.type == "tool_use")
| .message.content[]
| select(.type=="tool_use")
| "\(.name): \(.input | tostring | .[0:80])"' \
~/.claude/projects/<project>/sessions/<id>.jsonl
Handy for "what files did Claude read?" or "what bash commands did it run?"
Back up your transcript history
# Snapshot ~/.claude/projects into a private git repo
cd ~/.claude/projects
git init && git add -A && git commit -m "snapshot $(date +%F)"
git remote add origin git@github.com:you/claude-archive.git
git push -u origin main
Most developers' Claude Code transcripts are more valuable than most documents on their machine, and they're sitting on a single laptop with no backup. Consider whether you'd want them back if your disk died this week.
Replay a session
There's no official claude --replay command, but you can reconstruct a session by reading the JSONL and feeding the user messages back in. Most teams who want this end up writing a small script or — more commonly — using a tool that mines the transcripts directly (see below).
Privacy: what's in there
Everything you typed and every response Claude gave you is in plain text. That includes:
- API keys you pasted in by mistake
- Server addresses and database connection strings if you discussed deployment
- Customer data you happened to show Claude while debugging
- File contents Claude read with the
Read tool
If you're going to back this directory up, encrypt it. If you're going to commit it to a private repo, make sure the repo really is private. If you're going to share a single session file with a teammate, run a grep -i 'password\|api[_-]key\|secret' over it first.
Claude Code's own privacy posture is that these files stay on your machine — they're not uploaded to Anthropic by default. The transcripts only leave your machine if you decide to send them somewhere.
Beyond grep: turning transcripts into reusable skills
The most valuable thing in your ~/.claude/projects/ directory isn't any single prompt — it's the patterns that show up across many sessions. The same kind of code review you've done 14 times. The same "set up a new feature branch + add a failing test + implement + run lint" dance you do every Monday.
Those patterns are right there in the JSONL files. They just need to be detected and promoted to first-class artifacts.
That's what Prompt Conduit does. The CLI reads your ~/.claude/projects/ directory, finds sequences of prompts and tool calls that you've used multiple times, and writes them to ~/.claude/skills/ as Claude Code skills. From then on you can invoke them with /<skill-name> in any new session.
The skill generation runs fully local — no account, no data leaving your machine:
brew install promptconduit/tap/promptconduit
promptconduit skills generate --local
Add --dry-run to preview what would be written without touching disk. Full docs at /docs/local-skills.
FAQ
Where does Claude Code store conversations on macOS?
~/.claude/projects/<encoded-project-path>/sessions/<session-id>.jsonl. Each session is one file, each line one event.
Where does Claude Code store data on Windows?
%USERPROFILE%\.claude\projects\<encoded-project-path>\sessions\<session-id>.jsonl. Same structure as macOS, Windows path separators.
Can I delete old Claude Code transcripts?
Yes — they're plain files. rm -rf ~/.claude/projects/-Users-you-old-project/ deletes everything for that project. Claude Code does not currently auto-prune them.
How big do transcripts get?
A short session is a few KB. A long one with lots of file reads can be megabytes. After a year of heavy use, expect a few hundred MB total across all projects. Disk usage is rarely a concern.
Are the transcripts the same as what's shown by claude --resume?
claude --resume reads from the same JSONL files. The resume picker shows you the recent sessions across the current working directory's project — those are the entries in ~/.claude/projects/<current-project>/sessions/.
What about MCP server interactions?
MCP tool calls show up as regular tool_use records in the same JSONL files. There's no separate log.
Can I see what context Claude Code loaded for a session?
Loaded CLAUDE.md files appear as system-injected content in the early records of each session. You can find them by searching the JSONL for the file content you remember writing.
Further reading