cursor-chat-cleaner
CLI to list, view, back up, and delete Cursor chats on macOS.
Requires macOS and Python 3.10+. No extra packages.
Tested with Cursor 3.17.21. Cursor's storage is an internal implementation detail and may change between releases; destructive commands fail closed when the required schema is not recognized.
This is an independent community project. It is not affiliated with or endorsed by Anysphere.
Create the environment
From the repo root:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e .
Check it:
cursor-chat-cleaner --help
Later sessions:
source .venv/bin/activate
To leave the env: deactivate.
Without installing, you can run:
PYTHONPATH=src python3 -m cursor_chat_cleaner --help
Commands
list shows archived chats unless you pass --all or --id.
cursor-chat-cleaner list
cursor-chat-cleaner list --all
cursor-chat-cleaner list --repo e1f --all
cursor-chat-cleaner list --id <composer-id>
cursor-chat-cleaner list --sort size
cursor-chat-cleaner list --sort title --reverse
cursor-chat-cleaner list --sort repo
cursor-chat-cleaner list --older-than 30
cursor-chat-cleaner --user-dir ~/Library/Application\ Support/Cursor\ Nightly/User list
cursor-chat-cleaner list --repos
cursor-chat-cleaner list --repos --all
cursor-chat-cleaner list --json
--sort accepts updated (default, newest first), created, size (largest first), title, repo, or workspace. --reverse flips that default.
stats totals models, line churn, files, and context tokens (all chats unless --archived).
cursor-chat-cleaner stats
cursor-chat-cleaner stats --repo e1f
cursor-chat-cleaner stats --archived
cursor-chat-cleaner stats --json
view prints one chat (user/assistant text and compact tool lines). Thinking is hidden unless --thinking.
cursor-chat-cleaner view <composer-id>
cursor-chat-cleaner view <composer-id> --thinking
cursor-chat-cleaner view <composer-id> --json
backup writes a copy and leaves the original in place. It copies archived chats only, unless you pass --id, --repo, or --all (--repo includes active chats, same as delete --repo).
cursor-chat-cleaner backup
cursor-chat-cleaner backup --id <composer-id> --dest ~/Desktop/chat-backup
cursor-chat-cleaner backup --repo e1f --dest ~/Desktop/e1f-chats
delete removes archived chats only, unless you pass --id or --repo (those include active chats in the match). If the selection includes active chats, delete prints a warning before the dry-run or --yes step.
cursor-chat-cleaner delete --dry-run
cursor-chat-cleaner delete --yes --backup
cursor-chat-cleaner delete --id <composer-id> --yes --backup ~/Desktop/chat-backup
cursor-chat-cleaner delete --repo e1f --dry-run
cursor-chat-cleaner delete --repo e1f --yes --backup
cursor-chat-cleaner delete --older-than 30 --yes --backup
--backup without a path uses ~/cursor-chat-cleaner-backups/<timestamp>. Each backup has manifest.json, chats.sqlite, optional search.json, and copied transcripts. Backup directories are restricted to the current user (0700); data files are written as 0600.
Backups are archival snapshots for inspection and retention. This project does not provide a restore command, and copying backup data into live Cursor storage is unsupported.
--vacuum runs SQLite VACUUM after delete so the database file can shrink. That needs roughly as much free disk as the current DB size.
If the main delete succeeds but search-index or transcript cleanup fails, the error prints the pending chat IDs. Cleanup is idempotent, so it is safe to retry:
cursor-chat-cleaner cleanup --id <composer-id>
cursor-chat-cleaner cleanup --id <composer-id> --yes
Safety
- Quit Cursor before
--yes. An open session can rewrite history after you delete. --yesis required to change anything. Without it, delete is a dry-run.--forcedeletes while Cursor is still running. History may come back.- Cursor's process state is checked again immediately before the database write.
- Preview first:
list/view/delete --dry-run. deleterefuses to write ifstate.vscdbis missingcomposerHeaders(or itsisArchivedcolumns) or ifcomposer.composerHeaders.tableGateEnabledis not true. App version is not used as the lock.
After a delete: Developer: GC Agent KV Blobs
Deleting a chat does not remove leftover hash-keyed rows in state.vscdb: agentKv:blob:<hash>, composer.content.<hash>, and inlineDiff:<workspace>:<id>. Those hold tool results, diffs, and other payloads keyed by hash, not by chat id, so they become orphans.
This tool cannot safely garbage-collect them. After Cursor is quit and delete finishes:
- Open Cursor.
Cmd+Shift+P- Run Developer: GC Agent KV Blobs
That command does not remove chats from the sidebar. It drops unreferenced agentKv blobs so state.vscdb can shrink. composer.content and inlineDiff rows may still remain.
Where chats live
| Location | What |
|---|---|
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb |
Chat headers, messages, checkpoints |
~/Library/Application Support/Cursor/User/globalStorage/conversation-search.db |
Search index |
~/Library/Application Support/Cursor/User/workspaceStorage/<id>/workspace.json |
Maps a workspace id to a folder (repo name) |
~/.cursor/projects/*/agent-transcripts/<composer-id>/ |
Plain transcript files |
Do not delete state.vscdb as a file. That can break Cursor history.
Architecture
cli.pyowns command parsing, confirmation, and output.store.pyorchestrates chat reads, backups, deletion, cleanup, and statistics.schema.pycontains the version-sensitive Cursor table and key contract.transcripts.pyis the containment boundary for transcript discovery, sizing, copying, and deletion.
Tests
source .venv/bin/activate
PYTHONPATH=src python -m unittest discover -s tests -v
The tests run against sanitized, schema-only snapshots from the documented Cursor versions. These fixtures contain no chat content or other user data.
License
Licensed under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cursor_chat_cleaner-0.1.0.tar.gz.
File metadata
- Download URL: cursor_chat_cleaner-0.1.0.tar.gz
- Upload date:
- Size: 30.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ce89ab0bbb462449d20d74327c6e39e6963cb3370a0d00b53152ad161c0305f
|
|
| MD5 |
2b92cb7b5bce6bb34b1eabaad45e91a4
|
|
| BLAKE2b-256 |
301db38b385ef1982d00072bdc75a2f03bd1fcd41c515b96392daa092228082e
|
Provenance
The following attestation bundles were made for cursor_chat_cleaner-0.1.0.tar.gz:
Publisher:
release.yml on vilaca/cursor-chat-cleaner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cursor_chat_cleaner-0.1.0.tar.gz -
Subject digest:
1ce89ab0bbb462449d20d74327c6e39e6963cb3370a0d00b53152ad161c0305f - Sigstore transparency entry: 2632781172
- Sigstore integration time:
-
Permalink:
vilaca/cursor-chat-cleaner@9eb4dae550cac198e490e80c716230700dbc2802 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/vilaca
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9eb4dae550cac198e490e80c716230700dbc2802 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cursor_chat_cleaner-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cursor_chat_cleaner-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5d1c5864449a2346071806bb755fc8cf7f7d55abdf16a74ce050cd0e8cd43ba
|
|
| MD5 |
7bbf746fe33892916aaa5a4fb344a550
|
|
| BLAKE2b-256 |
5b37619a96f74517fd1fee7bc91bf5fb0472d46e7ba522881cceb7133dd8db77
|
Provenance
The following attestation bundles were made for cursor_chat_cleaner-0.1.0-py3-none-any.whl:
Publisher:
release.yml on vilaca/cursor-chat-cleaner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cursor_chat_cleaner-0.1.0-py3-none-any.whl -
Subject digest:
f5d1c5864449a2346071806bb755fc8cf7f7d55abdf16a74ce050cd0e8cd43ba - Sigstore transparency entry: 2632781248
- Sigstore integration time:
-
Permalink:
vilaca/cursor-chat-cleaner@9eb4dae550cac198e490e80c716230700dbc2802 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/vilaca
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9eb4dae550cac198e490e80c716230700dbc2802 -
Trigger Event:
push
-
Statement type: