Where every AI coding tool stores your sessions on disk
Every one of these tools writes your whole conversation to your own disk as it goes. The paths are below, one per tool, so you can grep them, back them up, or check exactly what a pasted credential is sitting inside.
The six locations
These are the default paths. Each one can be overridden, and the environment variable that does it is in the last column, since a machine running two profiles ends up with two of these trees instead of one.
| Tool | Where the transcript lives | Format | Override |
|---|---|---|---|
| Claude Code | ~/.claude/projects/<project>/<uuid>.jsonl | JSONL, one event per line | CHAT_RECALL_CLAUDE_HOME |
| Codex | ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl | JSONL "rollouts", filed by date | CHAT_RECALL_CODEX_HOME |
| OpenCode | ~/.local/share/opencode/opencode.db | SQLite: tables session and message | CHAT_RECALL_OPENCODE_DB |
| Antigravity | ~/.gemini/antigravity-cli/brain/<uuid>/.system_generated/logs/ | JSONL: read transcript_full.jsonl, not transcript.jsonl | CHAT_RECALL_AGY_HOME |
| Cursor (CLI) | ~/.cursor/chats/<md5 of cwd>/<chatId>/store.db | SQLite, one file per chat | CHAT_RECALL_CURSOR_HOME |
| Cursor (desktop) | ~/.config/Cursor/User/globalStorage/state.vscdb | SQLite. On macOS: ~/Library/Application Support/Cursor/ | CHAT_RECALL_CURSOR_IDE_HOME |
Four things that catch people out
| Claude Code deletes them after 30 days | Anthropic's own documentation is explicit about it: transcripts are kept "for 30 days by default to enable session resumption," and cleanupPeriodDays sets that period. So the archive you assume you have is really a rolling window, and the oldest end of it is being trimmed away while you read this. |
| They're stored in plaintext | Also Anthropic's own wording. Anything you pasted is readable by anything that can read your home directory at all: a backup agent, a sync client, another account on a shared machine. |
| A second profile means a second tree | CLAUDE_CONFIG_DIR creates a whole parallel root, so work done under ~/.claude-work is invisible to anything only looking at ~/.claude. The same holds for a second OpenCode database. |
| Two of them aren't append-only | Cursor's CLI rewrites its own transcript every time you resume a chat, and both Cursor surfaces and OpenCode keep their data in SQLite. A simple tail-the-file approach works fine for the JSONL tools and quietly loses data on these two. |
What else Claude Code keeps besides the transcript
- ~/.claude/history.jsonl: the prompts you actually typed
- ~/.claude/plans/: plan documents, flat, one file per plan
- ~/.claude/todos/ and ~/.claude/tasks/<session-uuid>/: task lists, one set per session
- ~/.claude/paste-cache/: long pastes, filed away by content hash
- ~/.claude/projects/<project>/memory/: auto memory, which is excluded from the 30-day sweep
Grepping them by hand
For one string in one tool, this is honestly all you need:
$ grep -rl "pgbouncer" ~/.claude/projects/ gives you filenames; the content is JSONL, so reading it means piping each hit through jq
It stops being enough by the third tool, because two of the six store data in SQLite and one of those rewrites itself constantly. That's the actual work an index does: read all six formats, normalize them into one shape, and let the assistant query it directly. See how it works.
If you'd rather they weren't there at all
Deleting a transcript wipes out the work along with the credential, which is usually the wrong trade: rotate first, then decide. If a whole project must never be read by anything, exclude it at the source instead of cleaning up after the fact:
$ chat-recall exclude project ~/work/client-project $ chat-recall exclude tool cursor
Questions
| Where does Claude Code store session history? | In ~/.claude/projects/ as one JSONL file per session, named by the session UUID, with one event per line. CHAT_RECALL_CLAUDE_HOME overrides the root. |
| Where is Cursor chat history stored? | Cursor has two surfaces. The CLI keeps ~/.cursor/chats/ with one SQLite store per chat, filed under an md5 of the working directory. The desktop app uses ~/.config/Cursor/User/globalStorage/state.vscdb, which on macOS lives under ~/Library/Application Support/Cursor/. |
| How long does Claude Code keep transcripts? | 30 days by default, set by cleanupPeriodDays. Anthropic's documentation describes the retention as being there to enable session resumption, so the archive you assume you have is a rolling window with its oldest end being trimmed. |
| Why has my session history disappeared? | Two common causes. The 30-day sweep removed it, or you are looking in the wrong tree: CLAUDE_CONFIG_DIR creates a whole parallel root, so work done under a second profile is invisible to anything reading only ~/.claude. |
| Are the transcripts encrypted? | No. They are plaintext, in Anthropic's own wording, so anything that can read your home directory can read them, including a backup agent, a sync client or another account on a shared machine. |
| Can I just grep them? | For one string in one tool, yes. grep -rl finds the files and the content is JSONL, so reading a hit means piping it through jq. It stops working by the third tool, because two of the six store data in SQLite and Cursor's CLI rewrites its transcript every time you resume a chat. |
More notes
| Does Claude Code remember previous sessions? | Partly, and the part it forgets is the expensive one. What CLAUDE.md, auto memory and --continue each carry across, and what none of them carry. |
| Claude Code has auto memory. Where it stops. | Auto memory writes notes about your preferences per repository, on one machine. What it is good at, the four boundaries it does not cross, and what to pair it with. |
| Context left until auto-compact: what the number counts | The percentage in the status line, what makes it fall, how to move the threshold, and what actually happens to your conversation when it reaches zero. |