cursor-chat-cleaner 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cursor_chat_cleaner-0.1.0/LICENSE +21 -0
- cursor_chat_cleaner-0.1.0/PKG-INFO +197 -0
- cursor_chat_cleaner-0.1.0/README.md +168 -0
- cursor_chat_cleaner-0.1.0/pyproject.toml +41 -0
- cursor_chat_cleaner-0.1.0/setup.cfg +4 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner/__init__.py +1 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner/__main__.py +4 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner/cli.py +500 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner/schema.py +120 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner/store.py +1295 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner/transcripts.py +118 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner.egg-info/PKG-INFO +197 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner.egg-info/SOURCES.txt +15 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner.egg-info/dependency_links.txt +1 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner.egg-info/entry_points.txt +2 -0
- cursor_chat_cleaner-0.1.0/src/cursor_chat_cleaner.egg-info/top_level.txt +1 -0
- cursor_chat_cleaner-0.1.0/tests/test_cleaner.py +1174 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 João Vilaça
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cursor-chat-cleaner
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Find, back up, and delete Cursor chats on macOS
|
|
5
|
+
Author: João Vilaça
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/vilaca/cursor-chat-cleaner
|
|
8
|
+
Project-URL: Repository, https://github.com/vilaca/cursor-chat-cleaner
|
|
9
|
+
Project-URL: Issues, https://github.com/vilaca/cursor-chat-cleaner/issues
|
|
10
|
+
Project-URL: Security, https://github.com/vilaca/cursor-chat-cleaner/security
|
|
11
|
+
Keywords: chat-history,cleanup,backup,sqlite,macos
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: System :: Archiving :: Backup
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# cursor-chat-cleaner
|
|
31
|
+
|
|
32
|
+
CLI to list, view, back up, and delete Cursor chats on macOS.
|
|
33
|
+
|
|
34
|
+
Requires **macOS** and **Python 3.10+**. No extra packages.
|
|
35
|
+
|
|
36
|
+
Tested with Cursor 3.17.21. Cursor's storage is an internal implementation
|
|
37
|
+
detail and may change between releases; destructive commands fail closed when
|
|
38
|
+
the required schema is not recognized.
|
|
39
|
+
|
|
40
|
+
This is an independent community project. It is not affiliated with or
|
|
41
|
+
endorsed by Anysphere.
|
|
42
|
+
|
|
43
|
+
## Create the environment
|
|
44
|
+
|
|
45
|
+
From the repo root:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python3 -m venv .venv
|
|
49
|
+
source .venv/bin/activate
|
|
50
|
+
python -m pip install -U pip
|
|
51
|
+
python -m pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Check it:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cursor-chat-cleaner --help
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Later sessions:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
source .venv/bin/activate
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
To leave the env: `deactivate`.
|
|
67
|
+
|
|
68
|
+
Without installing, you can run:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
PYTHONPATH=src python3 -m cursor_chat_cleaner --help
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Commands
|
|
75
|
+
|
|
76
|
+
`list` shows **archived** chats unless you pass `--all` or `--id`.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cursor-chat-cleaner list
|
|
80
|
+
cursor-chat-cleaner list --all
|
|
81
|
+
cursor-chat-cleaner list --repo e1f --all
|
|
82
|
+
cursor-chat-cleaner list --id <composer-id>
|
|
83
|
+
cursor-chat-cleaner list --sort size
|
|
84
|
+
cursor-chat-cleaner list --sort title --reverse
|
|
85
|
+
cursor-chat-cleaner list --sort repo
|
|
86
|
+
cursor-chat-cleaner list --older-than 30
|
|
87
|
+
cursor-chat-cleaner --user-dir ~/Library/Application\ Support/Cursor\ Nightly/User list
|
|
88
|
+
cursor-chat-cleaner list --repos
|
|
89
|
+
cursor-chat-cleaner list --repos --all
|
|
90
|
+
cursor-chat-cleaner list --json
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`--sort` accepts `updated` (default, newest first), `created`, `size` (largest first), `title`, `repo`, or `workspace`. `--reverse` flips that default.
|
|
94
|
+
|
|
95
|
+
`stats` totals models, line churn, files, and context tokens (all chats unless `--archived`).
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cursor-chat-cleaner stats
|
|
99
|
+
cursor-chat-cleaner stats --repo e1f
|
|
100
|
+
cursor-chat-cleaner stats --archived
|
|
101
|
+
cursor-chat-cleaner stats --json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`view` prints one chat (user/assistant text and compact tool lines). Thinking is hidden unless `--thinking`.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
cursor-chat-cleaner view <composer-id>
|
|
108
|
+
cursor-chat-cleaner view <composer-id> --thinking
|
|
109
|
+
cursor-chat-cleaner view <composer-id> --json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`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`).
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
cursor-chat-cleaner backup
|
|
116
|
+
cursor-chat-cleaner backup --id <composer-id> --dest ~/Desktop/chat-backup
|
|
117
|
+
cursor-chat-cleaner backup --repo e1f --dest ~/Desktop/e1f-chats
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`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.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
cursor-chat-cleaner delete --dry-run
|
|
124
|
+
cursor-chat-cleaner delete --yes --backup
|
|
125
|
+
cursor-chat-cleaner delete --id <composer-id> --yes --backup ~/Desktop/chat-backup
|
|
126
|
+
cursor-chat-cleaner delete --repo e1f --dry-run
|
|
127
|
+
cursor-chat-cleaner delete --repo e1f --yes --backup
|
|
128
|
+
cursor-chat-cleaner delete --older-than 30 --yes --backup
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`--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`.
|
|
132
|
+
|
|
133
|
+
Backups are archival snapshots for inspection and retention. This project does
|
|
134
|
+
not provide a restore command, and copying backup data into live Cursor storage
|
|
135
|
+
is unsupported.
|
|
136
|
+
|
|
137
|
+
`--vacuum` runs SQLite `VACUUM` after delete so the database file can shrink. That needs roughly as much free disk as the current DB size.
|
|
138
|
+
|
|
139
|
+
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:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
cursor-chat-cleaner cleanup --id <composer-id>
|
|
143
|
+
cursor-chat-cleaner cleanup --id <composer-id> --yes
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Safety
|
|
147
|
+
|
|
148
|
+
- **Quit Cursor** before `--yes`. An open session can rewrite history after you delete.
|
|
149
|
+
- `--yes` is required to change anything. Without it, delete is a dry-run.
|
|
150
|
+
- `--force` deletes while Cursor is still running. History may come back.
|
|
151
|
+
- Cursor's process state is checked again immediately before the database write.
|
|
152
|
+
- Preview first: `list` / `view` / `delete --dry-run`.
|
|
153
|
+
- `delete` refuses to write if `state.vscdb` is missing `composerHeaders` (or its `isArchived` columns) or if `composer.composerHeaders.tableGateEnabled` is not true. App version is not used as the lock.
|
|
154
|
+
|
|
155
|
+
## After a delete: Developer: GC Agent KV Blobs
|
|
156
|
+
|
|
157
|
+
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.
|
|
158
|
+
|
|
159
|
+
This tool cannot safely garbage-collect them. After Cursor is quit and delete finishes:
|
|
160
|
+
|
|
161
|
+
1. Open Cursor.
|
|
162
|
+
2. `Cmd+Shift+P`
|
|
163
|
+
3. Run **Developer: GC Agent KV Blobs**
|
|
164
|
+
|
|
165
|
+
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.
|
|
166
|
+
|
|
167
|
+
## Where chats live
|
|
168
|
+
|
|
169
|
+
| Location | What |
|
|
170
|
+
| --- | --- |
|
|
171
|
+
| `~/Library/Application Support/Cursor/User/globalStorage/state.vscdb` | Chat headers, messages, checkpoints |
|
|
172
|
+
| `~/Library/Application Support/Cursor/User/globalStorage/conversation-search.db` | Search index |
|
|
173
|
+
| `~/Library/Application Support/Cursor/User/workspaceStorage/<id>/workspace.json` | Maps a workspace id to a folder (repo name) |
|
|
174
|
+
| `~/.cursor/projects/*/agent-transcripts/<composer-id>/` | Plain transcript files |
|
|
175
|
+
|
|
176
|
+
Do not delete `state.vscdb` as a file. That can break Cursor history.
|
|
177
|
+
|
|
178
|
+
## Architecture
|
|
179
|
+
|
|
180
|
+
- `cli.py` owns command parsing, confirmation, and output.
|
|
181
|
+
- `store.py` orchestrates chat reads, backups, deletion, cleanup, and statistics.
|
|
182
|
+
- `schema.py` contains the version-sensitive Cursor table and key contract.
|
|
183
|
+
- `transcripts.py` is the containment boundary for transcript discovery, sizing, copying, and deletion.
|
|
184
|
+
|
|
185
|
+
## Tests
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
source .venv/bin/activate
|
|
189
|
+
PYTHONPATH=src python -m unittest discover -s tests -v
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The tests run against sanitized, schema-only snapshots from the documented
|
|
193
|
+
Cursor versions. These fixtures contain no chat content or other user data.
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
Licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# cursor-chat-cleaner
|
|
2
|
+
|
|
3
|
+
CLI to list, view, back up, and delete Cursor chats on macOS.
|
|
4
|
+
|
|
5
|
+
Requires **macOS** and **Python 3.10+**. No extra packages.
|
|
6
|
+
|
|
7
|
+
Tested with Cursor 3.17.21. Cursor's storage is an internal implementation
|
|
8
|
+
detail and may change between releases; destructive commands fail closed when
|
|
9
|
+
the required schema is not recognized.
|
|
10
|
+
|
|
11
|
+
This is an independent community project. It is not affiliated with or
|
|
12
|
+
endorsed by Anysphere.
|
|
13
|
+
|
|
14
|
+
## Create the environment
|
|
15
|
+
|
|
16
|
+
From the repo root:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
python3 -m venv .venv
|
|
20
|
+
source .venv/bin/activate
|
|
21
|
+
python -m pip install -U pip
|
|
22
|
+
python -m pip install -e .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Check it:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cursor-chat-cleaner --help
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Later sessions:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
source .venv/bin/activate
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
To leave the env: `deactivate`.
|
|
38
|
+
|
|
39
|
+
Without installing, you can run:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
PYTHONPATH=src python3 -m cursor_chat_cleaner --help
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Commands
|
|
46
|
+
|
|
47
|
+
`list` shows **archived** chats unless you pass `--all` or `--id`.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cursor-chat-cleaner list
|
|
51
|
+
cursor-chat-cleaner list --all
|
|
52
|
+
cursor-chat-cleaner list --repo e1f --all
|
|
53
|
+
cursor-chat-cleaner list --id <composer-id>
|
|
54
|
+
cursor-chat-cleaner list --sort size
|
|
55
|
+
cursor-chat-cleaner list --sort title --reverse
|
|
56
|
+
cursor-chat-cleaner list --sort repo
|
|
57
|
+
cursor-chat-cleaner list --older-than 30
|
|
58
|
+
cursor-chat-cleaner --user-dir ~/Library/Application\ Support/Cursor\ Nightly/User list
|
|
59
|
+
cursor-chat-cleaner list --repos
|
|
60
|
+
cursor-chat-cleaner list --repos --all
|
|
61
|
+
cursor-chat-cleaner list --json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`--sort` accepts `updated` (default, newest first), `created`, `size` (largest first), `title`, `repo`, or `workspace`. `--reverse` flips that default.
|
|
65
|
+
|
|
66
|
+
`stats` totals models, line churn, files, and context tokens (all chats unless `--archived`).
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cursor-chat-cleaner stats
|
|
70
|
+
cursor-chat-cleaner stats --repo e1f
|
|
71
|
+
cursor-chat-cleaner stats --archived
|
|
72
|
+
cursor-chat-cleaner stats --json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`view` prints one chat (user/assistant text and compact tool lines). Thinking is hidden unless `--thinking`.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
cursor-chat-cleaner view <composer-id>
|
|
79
|
+
cursor-chat-cleaner view <composer-id> --thinking
|
|
80
|
+
cursor-chat-cleaner view <composer-id> --json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`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`).
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cursor-chat-cleaner backup
|
|
87
|
+
cursor-chat-cleaner backup --id <composer-id> --dest ~/Desktop/chat-backup
|
|
88
|
+
cursor-chat-cleaner backup --repo e1f --dest ~/Desktop/e1f-chats
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`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.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
cursor-chat-cleaner delete --dry-run
|
|
95
|
+
cursor-chat-cleaner delete --yes --backup
|
|
96
|
+
cursor-chat-cleaner delete --id <composer-id> --yes --backup ~/Desktop/chat-backup
|
|
97
|
+
cursor-chat-cleaner delete --repo e1f --dry-run
|
|
98
|
+
cursor-chat-cleaner delete --repo e1f --yes --backup
|
|
99
|
+
cursor-chat-cleaner delete --older-than 30 --yes --backup
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`--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`.
|
|
103
|
+
|
|
104
|
+
Backups are archival snapshots for inspection and retention. This project does
|
|
105
|
+
not provide a restore command, and copying backup data into live Cursor storage
|
|
106
|
+
is unsupported.
|
|
107
|
+
|
|
108
|
+
`--vacuum` runs SQLite `VACUUM` after delete so the database file can shrink. That needs roughly as much free disk as the current DB size.
|
|
109
|
+
|
|
110
|
+
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:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
cursor-chat-cleaner cleanup --id <composer-id>
|
|
114
|
+
cursor-chat-cleaner cleanup --id <composer-id> --yes
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Safety
|
|
118
|
+
|
|
119
|
+
- **Quit Cursor** before `--yes`. An open session can rewrite history after you delete.
|
|
120
|
+
- `--yes` is required to change anything. Without it, delete is a dry-run.
|
|
121
|
+
- `--force` deletes while Cursor is still running. History may come back.
|
|
122
|
+
- Cursor's process state is checked again immediately before the database write.
|
|
123
|
+
- Preview first: `list` / `view` / `delete --dry-run`.
|
|
124
|
+
- `delete` refuses to write if `state.vscdb` is missing `composerHeaders` (or its `isArchived` columns) or if `composer.composerHeaders.tableGateEnabled` is not true. App version is not used as the lock.
|
|
125
|
+
|
|
126
|
+
## After a delete: Developer: GC Agent KV Blobs
|
|
127
|
+
|
|
128
|
+
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.
|
|
129
|
+
|
|
130
|
+
This tool cannot safely garbage-collect them. After Cursor is quit and delete finishes:
|
|
131
|
+
|
|
132
|
+
1. Open Cursor.
|
|
133
|
+
2. `Cmd+Shift+P`
|
|
134
|
+
3. Run **Developer: GC Agent KV Blobs**
|
|
135
|
+
|
|
136
|
+
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.
|
|
137
|
+
|
|
138
|
+
## Where chats live
|
|
139
|
+
|
|
140
|
+
| Location | What |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| `~/Library/Application Support/Cursor/User/globalStorage/state.vscdb` | Chat headers, messages, checkpoints |
|
|
143
|
+
| `~/Library/Application Support/Cursor/User/globalStorage/conversation-search.db` | Search index |
|
|
144
|
+
| `~/Library/Application Support/Cursor/User/workspaceStorage/<id>/workspace.json` | Maps a workspace id to a folder (repo name) |
|
|
145
|
+
| `~/.cursor/projects/*/agent-transcripts/<composer-id>/` | Plain transcript files |
|
|
146
|
+
|
|
147
|
+
Do not delete `state.vscdb` as a file. That can break Cursor history.
|
|
148
|
+
|
|
149
|
+
## Architecture
|
|
150
|
+
|
|
151
|
+
- `cli.py` owns command parsing, confirmation, and output.
|
|
152
|
+
- `store.py` orchestrates chat reads, backups, deletion, cleanup, and statistics.
|
|
153
|
+
- `schema.py` contains the version-sensitive Cursor table and key contract.
|
|
154
|
+
- `transcripts.py` is the containment boundary for transcript discovery, sizing, copying, and deletion.
|
|
155
|
+
|
|
156
|
+
## Tests
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
source .venv/bin/activate
|
|
160
|
+
PYTHONPATH=src python -m unittest discover -s tests -v
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The tests run against sanitized, schema-only snapshots from the documented
|
|
164
|
+
Cursor versions. These fixtures contain no chat content or other user data.
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
Licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cursor-chat-cleaner"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Find, back up, and delete Cursor chats on macOS"
|
|
9
|
+
authors = [{ name = "João Vilaça" }]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
license = "MIT"
|
|
13
|
+
license-files = ["LICENSE"]
|
|
14
|
+
keywords = ["chat-history", "cleanup", "backup", "sqlite", "macos"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: MacOS",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Programming Language :: Python :: 3.14",
|
|
27
|
+
"Topic :: System :: Archiving :: Backup",
|
|
28
|
+
"Topic :: Utilities",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.scripts]
|
|
32
|
+
cursor-chat-cleaner = "cursor_chat_cleaner.cli:main"
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/vilaca/cursor-chat-cleaner"
|
|
36
|
+
Repository = "https://github.com/vilaca/cursor-chat-cleaner"
|
|
37
|
+
Issues = "https://github.com/vilaca/cursor-chat-cleaner/issues"
|
|
38
|
+
Security = "https://github.com/vilaca/cursor-chat-cleaner/security"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
where = ["src"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|