{"slug": "where-six-ai-coding-clis-store-your-session-logs", "title": "Where Six AI Coding CLIs Store Your Session Logs", "summary": "A developer's investigation into six AI coding CLIs found that only two document where session logs are stored, with paths and formats varying widely. The tools examined are Claude Code, Codex CLI, Cursor CLI, Amp CLI, opencode, and pi, each writing conversation data to local files or databases, with retention settings only available for Claude Code and Amp. The findings, verified against real files and cross-checked by four adversarial agents, highlight the lack of standardized documentation and the impact of environment variables like XDG_CONFIG_HOME on default paths.", "body_md": "I have six AI coding CLIs installed on this machine: **Claude Code**, **Codex CLI**, **Cursor CLI**, **Amp CLI**, **opencode**, and **pi**. Each one writes the full conversation somewhere on disk.\n\nOnly two of them document where and a single one has full documentation of the format for storing sessions.\n\nLast month I published [stats from two months of agent-first development](https://allaboutcoding.ghinda.com/stats-from-two-months-agent-first-development-using-backoffs/). Before I could count anything and because I spend almost 100% of my time in terminal, I had to answer a boring question: where does each CLI write its session files?\n\nI expected a short lookup in the docs but it was not so simple. Some agents have their sessions location documented, for some others I had to rely on my own machine and inspect.\n\nHere is what I found for **Claude Code**, **Codex CLI**, **Cursor CLI**, **Amp CLI**, **opencode**, and **pi**: the paths, the file formats, and the settings that control retention where they exists.\n\nAll six tools were installed on my machine when I wrote this, so every path below was checked against real files at the end of last month (July 2026). I double checked on another machine with different profile.\n\nI also ran the findings through an adversarial pass: four separate agents, each told to *refute* rather than confirm, each fetching the primary vendor doc and inspecting the real directories. The corrections from that pass are already folded in.\n\nTwo things came out of it that you should keep in mind while reading:\n\n`XDG_CONFIG_HOME=~/.config`\n\n, which silently moves some of these paths away from their default. I mark those cases so you do not copy my path and wonder why it is empty.Also a note here: I could be wrong about some of the folders shared here because I tried to discover how all this works on my machine. So if you spot an issue please report it to me so I can fix it.\n\n| Session log path | Format | Retention setting | |\n|---|---|---|---|\nClaude Code |\n`~/.claude/projects/<project>/<session>.jsonl` |\nJSONL, plaintext | `cleanupPeriodDays` , default 30 days |\nCodex CLI |\n`~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl` (undocumented) |\nJSONL | none for transcripts |\nCursor CLI |\n`~/.cursor/chats/<id>/<uuid>/store.db` (undocumented) |\nSQLite | none |\nAmp CLI |\nserver, plus `~/.local/share/amp/threads/T-*.json` |\nJSON per thread | server side only |\nopencode |\n`~/.local/share/opencode/opencode.db` |\nSQLite | none |\npi |\n`~/.pi/agent/sessions/--<cwd>--/<ts>_<uuid>.jsonl` |\nJSONL, tree shaped | none |\n\nNow the details.\n\nBase directory is `~/.claude/`\n\n, and you can move it with `CLAUDE_CONFIG_DIR`\n\n([docs](https://code.claude.com/docs/en/claude-directory)).\n\nOne session is one JSONL file:\n\n```\n~/.claude/projects/<project>/<session-id>.jsonl\n```\n\nThe `<project>`\n\npart is your working directory with every non-alphanumeric character replaced by `-`\n\n. You can confirm this yourself with just doing an `ls`\n\ninside `~/claude/projects/`\n\n. For example the directory `/Users/lucianghinda/projects/state_of_mind/til`\n\nbecomes:\n\n```\n~/.claude/projects/-Users-lucianghinda-projects-state-of-mind-til/\n```\n\nNotice that `_`\n\nis replaced too, not only `/`\n\n.\n\nThe file holds [“every message, tool call, and tool result”](https://code.claude.com/docs/en/data-usage). Large tool outputs are spilled into a `tool-results/`\n\nfolder next to it, subagent transcripts go into `subagents/`\n\n, and pre-edit file snapshots go into `file-history/`\n\nso that rewind works.\n\nTwo settings matter here:\n\n`cleanupPeriodDays`\n\n`99999`\n\n, which means “never”, which is why I have transcripts from a year ago.`CLAUDE_CODE_SKIP_PROMPT_HISTORY=1`\n\nThere is also a purge command since v2.1.124:\n\n```\nclaude project purge --dry-run\n```\n\nIt removes a project’s transcripts, its per-session data, the matching lines in `history.jsonl`\n\n, and the project entry in `~/.claude.json`\n\n.\n\nOne line from the docs is worth quoting in full, because it applies to every tool in this article and only Anthropic writes it down:\n\nOS file permissions are the only protection.\n\nThe transcripts are not encrypted at rest so anything that was present in your sessions will be there. THIS IS IMPORTANT TO KNOW!\n\nBase directory is `CODEX_HOME`\n\n, which defaults to `~/.codex`\n\n([docs](https://learn.chatgpt.com/docs/config-file/config-advanced)).\n\nThe full transcripts, which Codex calls **rollouts**, live here:\n\n```\n~/.codex/sessions/YYYY/MM/DD/rollout-<timestamp>-<uuid>.jsonl\n```\n\nLine 1 is a `session_meta`\n\nrecord.\n\nAfter that you get mixed record types: `event_msg`\n\n, `response_item`\n\n, `turn_context`\n\n, `compacted`\n\n, and more.\nOn two machines in July 2026 I also found `world_state`\n\nand `inter_agent_communication_metadata`\n\nrecords, so the set is still growing.\n\nI searched both official config pages for `sessions`\n\n, `rollout`\n\n, and the record type names and could not find anything.\n\nThere is a trap here worth naming. Codex documents a `[history]`\n\nconfig section, and the docs describe its contents as “session transcripts”:\n\n```\n[history]\npersistence = \"none\"\nmax_bytes = 1000000\n```\n\nThat section governs `~/.codex/history.jsonl`\n\nonly. On disk, each line of that file is just the text you typed for one turn (`{session_id, ts, text}`\n\n). Setting `persistence = \"none\"`\n\ndoes **not** stop the rollout files. The full conversation still lands in `sessions/`\n\n.\n\nCodex v0.136 and later ship `archive`\n\n, `unarchive`\n\n, and `delete`\n\nsubcommands, so there is a way to clear sessions.\n\nThere is no documented age-based auto-deletion, so rollouts stay until you remove them. But Codex CLI is [developed open source](https://github.com/openai/codex) so you can monitor that repo for any changes.\n\nCursor documents how to *resume* a session (`--resume`\n\n, `agent ls`\n\n, `--continue`\n\n) and where the config file lives.\n\nIt does not document where the chats are stored or in what format. I checked the CLI docs, the config reference, the parameters reference, and the enterprise privacy page. Maybe I missed something so in that case please tell me and I will correct this article.\n\nFrom disk, the default is:\n\n```\n~/.cursor/chats/<chat-id>/<session-uuid>/store.db\n```\n\nIt is a SQLite database with two tables:\n\n```\nCREATE TABLE blobs (id TEXT PRIMARY KEY, data BLOB);\nCREATE TABLE meta  (key TEXT PRIMARY KEY, value TEXT);\n```\n\nNext to it sits a `meta.json`\n\nwith `schemaVersion`\n\n, `createdAtMs`\n\n, `updatedAtMs`\n\n, and sometimes `cwd`\n\nand `title`\n\n. The `~/.cursor/chats`\n\ndefault is stated by Cursor staff [on the forum](https://forum.cursor.com/t/cursor-cli-past-chats-not-showing-up/152450), not in the docs.\n\nThis is the tool where my `XDG_CONFIG_HOME`\n\ntricked me a bit.\n\nOn my machine the store is actually at `~/.config/cursor/chats/...`\n\n, because Cursor honors `$XDG_CONFIG_HOME/cursor/`\n\nfor the config directory and the chats move along with it. The vanilla default is still `~/.cursor`\n\n.\n\nTwo more things surprised me:\n\n`~/.cursor/acp-sessions/`\n\n.`~/.cursor/projects/<project>/agent-transcripts/`\n\n, and There is no retention setting for chats. The only documented cleanup controls in Cursor are for git worktrees (`cursor.worktreeCleanupIntervalHours`\n\n, `cursor.worktreeMaxCount`\n\n). To clear chat history you delete the directory which is a strategy for all these agents if you want to.\n\nAmp is the one that works differently because threads are stored on Amp’s servers by default and synced across your devices, and you can browse them at [ampcode.com/feed](https://ampcode.com/feed) ([security reference](https://ampcode.com/security)).\n\nLocally you get a mirror:\n\n```\n~/.local/share/amp/threads/T-<uuid>.json\n```\n\nOne JSON file per thread, with `v`\n\n, `id`\n\n, `created`\n\n, `messages[]`\n\n, and on real threads also `title`\n\n, `env`\n\n, and `meta`\n\n.\n\nLogs live under `~/.cache/amp/logs/cli.log`\n\n, with per-thread logs next to them.\n\nOnly one local path is documented by Amp: `~/.local/share/amp/secrets.json`\n\n, which holds your access token.\nEverything else in that directory I found by looking.\n\nA second machine with a newer Amp had `threads/`\n\n, `secrets.json`\n\n, `history.jsonl`\n\n, and `cli.log`\n\n, but was missing `session.json`\n\n, `device-id.json`\n\n, the per-thread logs, and the traces directory entirely. That is a good argument for not building anything on top of these files.\n\nBecause the server is the source of truth, the retention controls are there too. Deleted thread data is “removed within 30 days of thread deletion” for everyone, zero data retention is an Enterprise feature. There is no local cleanup at all, so the mirror grows forever unless you manually delete it. Or maybe it has an auto cleanup but I am not sure.\n\nopencode documents its data directory, `~/.local/share/opencode/`\n\n, on the [troubleshooting page](https://opencode.ai/docs/troubleshooting/). That page still lists a `project/`\n\ndirectory for “session and message data”, which no longer matches a current install.\n\nSince v1.2.0 (February 2026), sessions live in a single SQLite database. The [release notes](https://github.com/anomalyco/opencode/releases/tag/v1.2.0) say the first run “will migrate all flat files in data directory to a single sqlite database”.\n\nThe docs never state the path of that database. The supported way to find it is a command:\n\n```\nopencode db path\n```\n\nInside, on my install, the database runs in WAL mode and holds `project`\n\n, `session`\n\n, `message`\n\n, `part`\n\n, `session_share`\n\n, `todo`\n\n, and `permission`\n\ntables. Message and part payloads are stored as JSON text in a `data`\n\ncolumn. None of this schema is documented.\n\nThe old JSON tree is still sitting on disk after the migration, unreferenced, last written on 2026-04-30.\n\nTwo practical notes:\n\n`/share`\n\nis opt-in, the default mode is `\"manual\"`\n\n, and a shared conversation stays reachable until you `/unshare`\n\nit. No expiry is documented.For cleanup there is `opencode session delete <id>`\n\nand `opencode export --sanitize`\n\n. There is no TTL. The documented full reset is `rm -rf ~/.local/share/opencode`\n\n.\n\nI find the idea to use SQLite for this great as it is a DB, it is local and fast and it can be queries like a DB instead of traversing the file system and grepping files.\n\npi is the smallest tool (but with a lot of addons) in this list and the best documented one. It publishes the path, the deletion flow, **and** the complete on-disk format, in the repo and at [pi.dev/docs](https://pi.dev/docs).\n\n```\n~/.pi/agent/sessions/--<cwd>--/<timestamp>_<uuid>.jsonl\n```\n\nThe `<cwd>`\n\nis your working directory with `/`\n\nreplaced by `-`\n\n, wrapped in `--...--`\n\n. Same idea as Claude Code.\n\nThe [format doc](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/session-format.md) is the part I liked. Line 1 is a header, and every following line is a typed entry carrying an 8 character hex `id`\n\nand a `parentId`\n\n:\n\n```\n{\"type\":\"session\",\"version\":3,\"id\":\"uuid\",\"timestamp\":\"...\",\"cwd\":\"/path/to/project\"}\n{\"type\":\"message\",\"id\":\"a1b2c3d4\",\"parentId\":null,\"message\":{\"role\":\"user\",\"content\":\"Hello\"}}\n{\"type\":\"message\",\"id\":\"b2c3d4e5\",\"parentId\":\"a1b2c3d4\",\"message\":{\"role\":\"assistant\",\"content\":[]}}\n{\"type\":\"branch_summary\",\"id\":\"g7h8i9j0\",\"parentId\":\"a1b2c3d4\",\"summary\":\"Branch explored approach A\"}\n```\n\nBecause entries point at a parent, one file holds a **tree, not a list**. pi branches the conversation in place instead of forking a new file. Old format versions migrate automatically on load.\n\nOne disk-verified detail that confused me for a while: pi creates the per-project directory when it starts, but writes the `.jsonl`\n\nonly after an exchange finishes. Empty directories are normal, so do not read them as a bug.\n\nThere is no retention setting. Sessions accumulate until you delete them, from `/resume`\n\nwith `Ctrl+D`\n\n, or by removing the files. When the `trash`\n\nCLI is available, pi uses it instead of deleting permanently.\n\nRelocation is documented at three levels: `PI_CODING_AGENT_DIR`\n\nfor the whole directory, `PI_CODING_AGENT_SESSION_DIR`\n\nand `--session-dir`\n\nfor just the sessions, and a `sessionDir`\n\nsetting in `~/.pi/agent/settings.json`\n\n. And `--no-session`\n\ngives you an ephemeral run that saves nothing.\n\npi’s `/share`\n\nis also the odd one out in a good way. There is no vendor server. It exports the session to HTML and uploads it as a **secret GitHub gist** in your own account, viewable at `https://pi.dev/session/#<gist-id>`\n\n.\n\n**Assume the transcripts are plaintext and readable by anything running as you**, because that is what they are. Claude Code says it directly, and the others behave the same. If an agent ever printed a `.env`\n\nfile, that value is now sitting in a log file in your home directory.\n\n**Only Claude Code deletes old sessions for you**, because it is the only tool with an age-based retention setting. Everything else grows until you intervene, and nobody warns you. My 2.6 GB opencode log file is what a missing size cap looks like after a few months.\n\n**Do not build tooling on the undocumented paths without expecting breakage**, because Codex’s rollout tree, Cursor’s `store.db`\n\n, and opencode’s schema were never promised to anyone. opencode already moved from thousands of JSON files to one SQLite database in a single minor release, and that migration [had rough edges](https://github.com/anomalyco/opencode/issues/13654).\n\n**Check your environment variables before you trust a path**, because several of these directories move silently. `XDG_CONFIG_HOME`\n\nrelocated my whole Cursor chat store, and `CLAUDE_CONFIG_DIR`\n\n, `CODEX_HOME`\n\n, and `PI_CODING_AGENT_DIR`\n\ndo it on purpose.\n\n**Local does not mean private and remote does not mean lost**, because the interesting question is who can delete the data. Amp keeps the real copy on its servers and gives you a 30 day deletion window. pi uploads a shared session to a secret gist in your own GitHub account, so no vendor ever holds it. Those are two honest designs with different trade-offs.\n\nAs now [all my agents are writing Ruby scripts when needed](https://allaboutcoding.ghinda.com/write-agent-scripts-in-ruby/) I have a small Ruby script that walks all six locations, checks every claim in this article against the real files, and reports the size of what it finds. It uses only the standard library, and I run it again after each tool updates. That is cheaper than trusting a path I confirmed weeks ago.\n\nThe other check takes one minute and is worth doing today: look at whether these directories fall inside anything you sync or back up. Dropbox, iCloud, and Time Machine will happily copy plaintext transcripts of every session you have ever run, and nothing in the setup asks you first.\n\nI ran this through an adversarial fact-check and still expect some of it to age badly, because four of the six tools never promised these paths in the first place. Both pi and opencode also changed their GitHub organization recently, so links rot faster than usual here. If you find something that has moved, I would be glad to hear about it.", "url": "https://wpnews.pro/news/where-six-ai-coding-clis-store-your-session-logs", "canonical_source": "https://allaboutcoding.ghinda.com/where-ai-coding-clis-store-session-logs/", "published_at": "2026-08-06 07:58:55+00:00", "updated_at": "2026-08-21 20:44:33.257547+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools"], "entities": ["Claude Code", "Codex CLI", "Cursor CLI", "Amp CLI", "opencode", "pi"], "alternates": {"html": "https://wpnews.pro/news/where-six-ai-coding-clis-store-your-session-logs", "markdown": "https://wpnews.pro/news/where-six-ai-coding-clis-store-your-session-logs.md", "text": "https://wpnews.pro/news/where-six-ai-coding-clis-store-your-session-logs.txt", "jsonld": "https://wpnews.pro/news/where-six-ai-coding-clis-store-your-session-logs.jsonld"}}