The root
Sessions live under ~/.claude/projects. One subdirectory per project, one file per session inside it.
Claude Code guide: session storage
Claude Code keeps every conversation on your own machine as a line-delimited JSON file. Nothing is needed to turn that on and nothing uploads it. Knowing the layout is what lets you back a session up, move it to another machine, or read it with a script.
Anthropic
Sessions live under ~/.claude/projects. One subdirectory per project, one file per session inside it.
The subdirectory name is the working directory with every character that is not a letter or a digit replaced by a hyphen. So C:\Work\Ai\tmp\termdeck-test becomes C--Work-Ai-tmp-termdeck-test, and a POSIX path like /home/you/app becomes -home-you-app.
Each session is <sessionId>.jsonl: one JSON object per line, appended as the turn runs. The file is complete after every line, so you can tail it while the agent is still working.
Because the slug is a pure function of the project path, you can compute the directory yourself. That is the property Codex does not have, and it is why a Claude session is the easiest of the three to locate by hand.
Copying ~/.claude/projects copies your entire history. It is plain text, so it is also the part of your machine most worth reading before you share it.
Compare
| Claude Code | Codex CLI | Grok CLI | |
|---|---|---|---|
| Root directory | ~/.claude/projects | $CODEX_HOME/sessions | $GROK_HOME/sessions |
| One session is | One .jsonl file | One .jsonl rollout file | A directory of files |
| Grouped by | Slugged project path | Date, as YYYY/MM/DD | Slugged project path |
| Path from project + id | Derivable | Not derivable, resolve by id | Derivable |
| Old sessions | Left as plain .jsonl | Compressed to .jsonl.zst | Left as plain files |
| Built-in index | None, scan the tree | session_index.jsonl | summary.json per session |
Termdeck drives all three from one console, so the differences above stop being three separate habits to remember.
FAQ
Yes. Each line is a standalone JSON object, so any JSONL reader works. Termdeck parses the same files rather than keeping its own copy, which is why a session started in the terminal shows up in the browser with no import step.
Yes, permanently. There is no server-side copy to restore from, because the transcript never left your machine in the first place.
The directory name is the working directory path with every non-alphanumeric character replaced by a hyphen. Slashes, colons and dots all collapse to the same character, which is why the name looks mangled but is still unique per path.
They should not. Two writers appending to one transcript will fork it. Termdeck locks a session that is already attached to a running CLI and keeps the composer read-only until that process lets go.
Claude Code, Codex and Grok in one browser console