You iterated all afternoon in Cursor’s Agent/Composer, quit, reopened the next morning, and the conversation list is empty. Or only today’s thread shows, yesterday’s deep dive is gone, or every chat is stuck spinning on Loading Chat. Sometimes a single Reload Window triggers it, not even a full quit.
Fastest fix: quit Cursor, then re-open the project from its exact original absolute path via File -> Open Recent. The vast majority of “lost” history is not deleted — it is keyed to a workspace hash that changed when the folder moved, was re-cloned, or got a new creation timestamp. If that does not bring it back, the data is almost always still inside state.vscdb on disk and recoverable with the steps below.
Cursor stores chat history locally in SQLite, not in the cloud. As of June 2026 (Cursor 3.7) there is no built-in cross-device chat sync — it is a long-standing feature request, not a shipped setting. So if a thread is gone from this machine, recovery happens on this machine’s disk, not by “re-syncing.”
Where Cursor actually keeps chat history (as of June 2026)
There are three on-disk locations, and they have shifted across the 3.x line, so check all three:
| Store | Path (macOS) | What lives here |
|---|---|---|
| Global DB | ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb | The bulk of chat/Agent data: composerData:* (thread headers, titles, timestamps) and bubbleId:* (individual messages) |
| Workspace DB | ~/Library/Application Support/Cursor/User/workspaceStorage/<hash>/state.vscdb | Per-workspace links into the global DB; the composer.composerHeaders key that drives the sidebar list |
| Agent transcripts | ~/.cursor/projects/<project-slug>/agent-transcripts/ | Plain per-run transcript files written by recent Agent versions; readable even when the sidebar is empty |
Linux mirrors the first two under ~/.config/Cursor/User/...; Windows under %APPDATA%\Cursor\User\.... The ~/.cursor/projects/ directory is the same on all three platforms (under your home directory).
The agent-transcripts directory is the most important recent change: even when the in-app list shows nothing, your prompts and the agent’s replies often still sit there as readable files. Check it before you assume anything is truly gone.
Common causes
Ordered by hit rate, highest first.
1. The workspace hash changed (folder moved, renamed, re-cloned, or restored)
Cursor keys storage by a workspace hash derived from the folder’s absolute path and, in some cases, its creation timestamp. Move the folder, rename it, re-git clone it, restore it from a backup, or remount a network drive, and Cursor computes a new hash, creates a fresh empty workspace, and the old chats become orphaned under the old hash. Nothing is deleted.
How to judge: File -> Open Recent and pick the original path exactly. If threads reappear, this is it. If the folder genuinely moved, see Step 3 (re-link the old workspace).
2. A version update migrated storage badly
On upgrade, Cursor migrates the SQLite schema. Some 3.x updates left threads showing Chat Too Old - this chat was created in an older version of Cursor and is no longer supported, Conversation has corrupted data, or an infinite Loading Chat spinner. New chats work; old ones do not surface.
How to judge: Cursor -> About (macOS) or Help -> About for the version. If history vanished right after an auto-update and you see any of those exact strings, this is a migration issue, not your fault.
3. The state.vscdb file got corrupted by a hard kill
A force-quit while a thread was mid-write can leave the SQLite WAL in a state Cursor cannot recover. On next launch it falls back to a fresh DB rather than fail to open.
How to judge: with Cursor quit, check for lingering state.vscdb-shm / state.vscdb-wal files, or a state.vscdb.backup / state.vscdb-corrupted sibling, in the workspace or global storage directory.
4. Threads got orphaned with a null workspace
A known failure mode leaves composerData rows intact (correct titles and bodies) but with their workspace association set to null, so nothing surfaces in the sidebar even though the data is right there.
How to judge: run the SQLite query in Step 4. If you see composerData:* keys but the sidebar is empty, the data exists and just is not linked.
5. Someone deleted the global state.vscdb to reclaim disk
globalStorage/state.vscdb can balloon to multiple GB. Community advice to “just delete it” is destructive: it leaves every project stuck on Loading Chat forever, because the workspace DBs still point at thread IDs that no longer exist.
How to judge: did anyone (or a “cleanup” script) recently remove or truncate that file? If yes, restore it from backup; there is no in-app recovery once it is gone.
6. You hit the per-workspace retention behavior
Heavy workspaces accumulate thousands of bubbles. Cursor does not aggressively delete, but very large or very old threads can render as truncated or fail to load while newer ones are fine.
How to judge: if only the oldest, largest threads misbehave and recent ones are intact, this is volume-related rather than total loss.
Before you start
- Do not start a new conversation in the empty window first. New writes can over-write a recoverable backup or bump the active workspace’s state.
- Quit Cursor fully (
Cmd+Q/File -> Exit) before touching any storage file. Editing SQLite while Cursor is open will corrupt your recovery. - Make a backup before you change anything:
cp -r ~/Library/Application\ Support/Cursor/User/globalStorage ~/Desktop/cursor-globalStorage-backup
cp -r ~/.cursor/projects ~/Desktop/cursor-projects-backup
Information to collect
- Cursor version (
Cursor -> About). - OS and the exact storage paths from the table above.
- Today’s workspace path vs the path where the history was created.
- The exact on-screen string, if any (
Chat Too Old,Loading Chat,Conversation has corrupted data). - Sizes of
globalStorage/state.vscdband the relevantworkspaceStorage/<hash>/state.vscdb. - Whether
~/.cursor/projects/<slug>/agent-transcripts/has files.
Step-by-step fix
Step 1: Re-open the original workspace
File -> Open Recent, pick the project at its original absolute path, exactly (case and all). If history returns, you were simply in a different workspace. Bookmark the canonical path going forward. This resolves the single most common cause.
Step 2: Read the agent transcripts directly
If the sidebar is empty but you only need the content, look here first:
ls -la ~/.cursor/projects/
ls -la ~/.cursor/projects/<your-project-slug>/agent-transcripts/
Each file is a readable transcript of one agent run. Even when the in-app list is broken, this is often a complete record of what you and the agent did. Copy what you need before attempting riskier DB surgery.
Step 3: Re-link the old workspace after a folder move
If the folder moved or was re-cloned, the old chats live under the old workspace hash. List the candidates and find the one with the most data (largest state.vscdb):
du -sh ~/Library/Application\ Support/Cursor/User/workspaceStorage/*/state.vscdb | sort -h
The community tool cursor-chat-recovery automates matching the old (populated) workspace to the new (empty) one. With Cursor fully quit:
curl -fsSL https://raw.githubusercontent.com/cpeoples/cursor-chat-recovery/main/cursor-chat-recovery.sh -o cursor-chat-recovery.sh
bash cursor-chat-recovery.sh --list my-project-name
# preview before writing anything
bash cursor-chat-recovery.sh --dry-run --restore <source-index> <target-index> my-project-name
# then run for real
bash cursor-chat-recovery.sh --restore <source-index> <target-index> my-project-name
Afterward, re-open the project from the exact path the recovery targeted. Windows users need Git Bash or WSL; PowerShell/CMD will not run the script.
Step 4: Inspect the SQLite DBs yourself
If you would rather not run a script, check the data by hand. With Cursor quit:
cd ~/Library/Application\ Support/Cursor/User/globalStorage/
sqlite3 state.vscdb "SELECT COUNT(*) FROM cursorDiskKV WHERE key LIKE 'composerData:%';"
sqlite3 state.vscdb "SELECT key FROM cursorDiskKV WHERE key LIKE 'composerData:%' LIMIT 20;"
If older builds stored chat in ItemTable instead, try:
sqlite3 state.vscdb "SELECT key FROM ItemTable WHERE key LIKE '%composer%' OR key LIKE '%chat%';"
Any matching rows mean the data is on disk. You can export a value to inspect it:
sqlite3 state.vscdb "SELECT value FROM cursorDiskKV WHERE key = '<composerData:...>';" > thread.json
If you see populated composerData:* rows but an empty sidebar, you are in the null-workspace orphan case (cause 4): the content is safe even though Cursor will not list it.
Step 5: Restore from a backup file
If you find a state.vscdb.backup or state.vscdb-corrupted sibling, set the current file aside and promote the backup. In the relevant directory (workspace or global):
cp state.vscdb state.vscdb.broken
mv state.vscdb.backup state.vscdb
Restart Cursor and check the sidebar. This is the cleanest fix for cause 3 (corruption) and cause 5 (deleted global DB) when a backup exists.
Step 6: Fix the “Chat Too Old” / “Loading Chat” migration case
For the migration failure (cause 2), the data is usually intact but a single key is wedging the list. Because state.vscdb is SQLite, you can surgically clear the sidebar header key without touching settings, extensions, or the threads themselves. With Cursor quit, in the affected workspaceStorage/<hash>/ directory:
cp state.vscdb state.vscdb.bak
sqlite3 state.vscdb "DELETE FROM ItemTable WHERE key = 'composer.composerHeaders';"
Restart Cursor. It rebuilds the header list from the underlying composerData/bubbleId rows. If it does not help, restore the .bak you just made and move on.
Step 7: Last resort - rebuild and file a ticket
If nothing surfaces the threads, quit Cursor and move the global DB aside to force a clean rebuild (you keep the old one as a backup):
mv ~/Library/Application\ Support/Cursor/User/globalStorage/state.vscdb \
~/Library/Application\ Support/Cursor/User/globalStorage/state.vscdb.bak
Restart; indexing takes several minutes on a large project. Then file a report at the Cursor forum or in-app feedback with your version, the exact error string, the file sizes from your earlier checks, and whether agent-transcripts/ had data. Keep all .bak files until you confirm recovery.
How to confirm it’s fixed
- Open the recovered workspace and confirm thread titles match what you remember.
- Click into an old thread and verify the conversation is intact, not truncated and not stuck on
Loading Chat. - Quit and relaunch Cursor once; confirm history survives the restart.
- Compare the global DB size now vs your backup to confirm you did not silently lose rows.
Long-term prevention
- Quit with
Cmd+Q(macOS) orFile -> Exit; avoid force-kill, which is the usual cause of WAL corruption. - Use stable absolute paths. Do not move, rename, or re-clone a folder that has Composer/Agent history; the workspace hash will change.
- Never delete
globalStorage/state.vscdbto reclaim disk — it bricks every project’s chat list. - For irreplaceable threads, export them: open the thread, three-dot menu,
Exportto Markdown. - Keep the
~/.cursor/projects/.../agent-transcripts/files; they are your most readable safety net. - For true cross-machine continuity (which Cursor still lacks natively as of June 2026), use a community sync CLI such as
cursavesthat pushes transcripts to a private git repo, or back upglobalStorage/and~/.cursor/projects/with Time Machine orrsync.
Common pitfalls
- Starting a new chat in the empty window before checking the workspace path or transcripts. New writes can over-write a recoverable backup.
- Editing
state.vscdbwhile Cursor is open. Always quit first. - Deleting the global
state.vscdbon disk-cleanup advice — this is the single most destructive mistake; it leaves every project onLoading Chat. - Assuming chats are in the cloud. They are local-only; there is no native sync to re-pull from.
- Renaming or moving a project folder mid-project. The hash changes and the active thread vanishes from the sidebar.
- Treating
Reload Windowas harmless. It re-inits state and can surface a stale or empty storage path.
FAQ
- Where exactly does Cursor store chat history? Three places as of 3.7:
globalStorage/state.vscdb(the bulk),workspaceStorage/<hash>/state.vscdb(per-workspace links and thecomposer.composerHeaderslist), and plain transcript files under~/.cursor/projects/<slug>/agent-transcripts/. On macOS the first two are under~/Library/Application Support/Cursor/User/; Linux uses~/.config/Cursor/User/; Windows uses%APPDATA%\Cursor\User\. - Is my chat history synced to my Cursor account? No. As of June 2026 Cursor has no built-in cross-device chat sync; it is a top feature request, not a setting. History is local to each machine, so recover on the machine where it was lost.
- My chats show “Chat Too Old” or are stuck on “Loading Chat” after an update — are they gone? Usually not. That is a migration/header issue. Try Step 6 (clear
composer.composerHeaders); thecomposerData/bubbleIdrows are typically intact. - I deleted globalStorage/state.vscdb to save disk and now everything says “Loading Chat” — can I undo it? Only by restoring that file from a backup (Time Machine,
rsync, or your own copy). Without a backup there is no recovery, which is why deleting it is so risky. - Does opening the same project via a symlink or a re-cloned copy share history? No. The workspace hash differs, so they are separate stores. Re-open from the original path, or re-link with the recovery tool in Step 3.
- Can I export a single conversation? Yes — open the thread, open the three-dot menu, choose
Exportto save Markdown. Do this for anything you cannot afford to lose.