chat-recall

Cursor chat history: where it lives and how to read it

Cursor stores your chats in SQLite, in two unrelated places, under a schema it has changed three times. That is why every guide you find contradicts the last one.

Two surfaces, two databases

Cursor IDE (desktop)~/.config/Cursor/User/globalStorage/state.vscdb. On macOS, under ~/Library/Application Support/Cursor/ instead.
cursor-agent (CLI)~/.cursor/chats/<md5 of the working directory>/<chatId>/store.db, one database per chat.

Note the capital C. On Linux, ~/.config/cursor in lowercase is the CLI auth directory and contains no chats at all. Both directories exist, and looking in the wrong one is the most common reason people conclude their history is missing.

The schema has moved three times

An install upgraded in place keeps its older rows, so all four of these are still out there. Verified against a live Cursor 3.17.8 install, in the order a reader should try them:

composerHeaders tableCurrent, seen on 3.15.6 and later.
composer.composerHeadersAn ItemTable key in the global database. Cursor 3.0.
composer.composerDataAn ItemTable key in each per-workspace database. Roughly 0.45 through 2.x.
The pre-0.45 chatdata keysSelf-contained, and they encode the speaker differently: the bubble type is the string user or ai, where every later era uses the number 1 or 2.

The first three all keep message content the same way, as composerData:<id> and bubbleId:<composerId>:<bubbleId> rows in the global cursorDiskKV table. Only the index moved, which is why a query copied from a year-old blog post returns nothing on a current install and nobody can tell you why.

Two rules before you open it

Both of these come from reported data loss, not from caution.

Open it read-only. Cursor keeps a live write-ahead log while it is running, and the forums carry cases of histories destroyed by an outside process writing to the database underneath it. Close Cursor, or open the file read-only, or copy it first.

Bound every read. One reported state.vscdb had grown to 30 GB of bubbleId and agentKv rows. An unbounded SELECT against that is not slow, it is an out-of-memory kill.

Exporting a chat

read-only, on a copy
$ cp ~/.config/Cursor/User/globalStorage/state.vscdb /tmp/cursor-copy.db

$ sqlite3 -readonly /tmp/cursor-copy.db "SELECT composerId, createdAt
    FROM composerHeaders ORDER BY lastUpdatedAt DESC LIMIT 20;"

If that table does not exist, the install predates it and you are in era two or three above.

Why tailing the file loses data

The CLI rewrites its transcript on every resume rather than appending to it. Measured on one chat, a five-line file came back as a nine-line file with the original terminator gone. Any tool that remembers a byte offset and reads forward from it silently loses the rewritten portion, which is why Cursor needs a full read every time while the JSONL tools can be read incrementally.

Reading it alongside everything else

Both Cursor surfaces are one source: the CLI emits an agent id and the IDE a composer id, both UUIDs, so they share a namespace and land in one history with your other tools. CHAT_RECALL_CURSOR_HOME and CHAT_RECALL_CURSOR_IDE_HOME override the two paths for a non-standard install. Using several tools without losing the thread covers the rest of the set.

Index your Cursor history Every tool, every path

Questions

Where is Cursor chat history stored?In two places. The desktop IDE uses ~/.config/Cursor/User/globalStorage/state.vscdb, which on macOS lives under ~/Library/Application Support/Cursor/. The cursor-agent CLI uses ~/.cursor/chats/ with one SQLite database per chat, grouped by an md5 of the working directory.
Why can I not find my Cursor chats in ~/.config/cursor?Because that lowercase directory is the CLI auth directory and holds no chats. The IDE data is under ~/.config/Cursor with a capital C. Both exist on Linux, which is what makes this so easy to get wrong.
How do I export Cursor chat history?Copy state.vscdb first, then query the copy with sqlite3 -readonly. On a current install the chat index is the composerHeaders table; on older installs it is a composer.composerHeaders or composer.composerData key inside ItemTable.
Why does the SQL query I found online return nothing?Cursor has moved the chat index three times and an install upgraded in place keeps its older rows. A query written for one era returns nothing on another, even though the data is there.
Is it safe to open the Cursor database while Cursor is running?Open it read-only or work on a copy. Cursor keeps a live write-ahead log, and there are reported cases of chat histories destroyed by an outside process writing to the file underneath it. Also bound your queries: one reported state.vscdb had reached 30 GB.
Why did my Cursor chat history disappear after resuming?The CLI rewrites its transcript on resume rather than appending. A tool that reads forward from a remembered byte offset loses the rewritten part, so anything reading Cursor has to re-read the whole chat each time.

More notes

The three kinds of MCP memory serverKnowledge-graph stores, note-takers and session indexes are three different products wearing one label. Which one you need depends on a single question.
Compacting conversation: what Claude Code keeps and dropsWhat auto-compact does to a long session, why the assistant starts contradicting itself afterwards, and how to get the lost detail back instead of retyping it.
You pasted an API key into a coding session. Now what?Deleting the chat does not remove it. Where the key actually lives, how to find every session that contains one, and what to do in what order.