cursor-chat-recovery 0.2.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.
Files changed (46) hide show
  1. cursor_chat_recovery-0.2.0/.github/workflows/ci.yml +16 -0
  2. cursor_chat_recovery-0.2.0/.gitignore +13 -0
  3. cursor_chat_recovery-0.2.0/LICENSE +21 -0
  4. cursor_chat_recovery-0.2.0/PKG-INFO +124 -0
  5. cursor_chat_recovery-0.2.0/README.md +114 -0
  6. cursor_chat_recovery-0.2.0/docs/superpowers/plans/2026-05-27-cursor-chat-tool.md +2989 -0
  7. cursor_chat_recovery-0.2.0/docs/superpowers/plans/2026-06-11-tui-performance-ux.md +1488 -0
  8. cursor_chat_recovery-0.2.0/docs/superpowers/specs/2026-05-27-cursor-chat-tool-design.md +381 -0
  9. cursor_chat_recovery-0.2.0/docs/superpowers/specs/2026-06-11-tui-performance-ux-design.md +159 -0
  10. cursor_chat_recovery-0.2.0/pyproject.toml +45 -0
  11. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/__init__.py +0 -0
  12. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/cli.py +150 -0
  13. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/model.py +85 -0
  14. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/operations.py +326 -0
  15. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/paths.py +61 -0
  16. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/schema.py +99 -0
  17. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/storage.py +192 -0
  18. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/__init__.py +0 -0
  19. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/actions.py +54 -0
  20. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/app.py +342 -0
  21. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/dialogs.py +369 -0
  22. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/filtering.py +40 -0
  23. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/loading.py +56 -0
  24. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/screen_chats.py +184 -0
  25. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/screen_messages.py +138 -0
  26. cursor_chat_recovery-0.2.0/src/cursor_chat_recovery/tui/screen_workspaces.py +211 -0
  27. cursor_chat_recovery-0.2.0/tests/__init__.py +0 -0
  28. cursor_chat_recovery-0.2.0/tests/conftest.py +25 -0
  29. cursor_chat_recovery-0.2.0/tests/fixtures/__init__.py +0 -0
  30. cursor_chat_recovery-0.2.0/tests/fixtures/globalStorage_corrupt.vscdb +0 -0
  31. cursor_chat_recovery-0.2.0/tests/fixtures/globalStorage_minimal.vscdb +0 -0
  32. cursor_chat_recovery-0.2.0/tests/fixtures/globalStorage_schema_drift.vscdb +0 -0
  33. cursor_chat_recovery-0.2.0/tests/fixtures/make_fixture.py +158 -0
  34. cursor_chat_recovery-0.2.0/tests/fixtures/workspaceStorage/ws-alpha/state.vscdb +0 -0
  35. cursor_chat_recovery-0.2.0/tests/fixtures/workspaceStorage/ws-beta/obsolete +0 -0
  36. cursor_chat_recovery-0.2.0/tests/fixtures/workspaceStorage/ws-beta/state.vscdb +0 -0
  37. cursor_chat_recovery-0.2.0/tests/fixtures/workspaceStorage/ws-delta/state.vscdb +0 -0
  38. cursor_chat_recovery-0.2.0/tests/fixtures/workspaceStorage/ws-epsilon/state.vscdb +0 -0
  39. cursor_chat_recovery-0.2.0/tests/fixtures/workspaceStorage/ws-remote/state.vscdb +0 -0
  40. cursor_chat_recovery-0.2.0/tests/test_cli.py +56 -0
  41. cursor_chat_recovery-0.2.0/tests/test_operations.py +199 -0
  42. cursor_chat_recovery-0.2.0/tests/test_paths.py +37 -0
  43. cursor_chat_recovery-0.2.0/tests/test_schema.py +38 -0
  44. cursor_chat_recovery-0.2.0/tests/test_storage.py +166 -0
  45. cursor_chat_recovery-0.2.0/tests/test_tui_smoke.py +553 -0
  46. cursor_chat_recovery-0.2.0/uv.lock +432 -0
@@ -0,0 +1,16 @@
1
+ name: CI
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ python: ["3.10", "3.11", "3.12"]
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: astral-sh/setup-uv@v3
12
+ - run: uv python install ${{ matrix.python }}
13
+ - run: uv sync --dev
14
+ - run: uv run pytest
15
+ - run: uv run ruff check
16
+ - run: uv run mypy src/
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ .mypy_cache/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .venv/
10
+
11
+ # harness-local
12
+ .claude/
13
+ LAUNCH.md
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kuba Kwiecien
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,124 @@
1
+ Metadata-Version: 2.4
2
+ Name: cursor-chat-recovery
3
+ Version: 0.2.0
4
+ Summary: Inventory, view, reassign, and export Cursor chats
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: prompt-toolkit>=3.0.43
9
+ Description-Content-Type: text/markdown
10
+
11
+ # cursor-chat-recovery
12
+
13
+ [![CI](https://github.com/kwiscion/cursor-chat-recovery/actions/workflows/ci.yml/badge.svg)](https://github.com/kwiscion/cursor-chat-recovery/actions/workflows/ci.yml)
14
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
15
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
16
+
17
+ Did your Cursor chats disappear after you moved, renamed, or re-opened a project? They're not gone. This is an interactive terminal UI to **recover, browse, move, and export Cursor AI chat history** — across all your projects.
18
+
19
+ ## Why chats "disappear"
20
+
21
+ Cursor identifies each workspace by a hash of its identifier URI. Reopening a project from a different path, or saving an Untitled multi-folder workspace as a `.code-workspace` file, mints a new workspace identity and detaches all prior chats from the sidebar. The conversations are still in `globalStorage/state.vscdb` keyed by `composerId` — they just need their `workspaceIdentifier` rewritten to point at the new workspace. That's what this tool does, with backups at every step.
22
+
23
+ It's also useful when nothing is broken: browse every chat you've ever had in any project, move chats between workspaces, and export conversations to Markdown.
24
+
25
+ ## Install
26
+
27
+ Requires Python 3.10+. With [uv](https://docs.astral.sh/uv/):
28
+
29
+ uv tool install git+https://github.com/kwiscion/cursor-chat-recovery
30
+
31
+ or with pipx:
32
+
33
+ pipx install git+https://github.com/kwiscion/cursor-chat-recovery
34
+
35
+ Both install the `cursor-chat-recovery` executable (and a short alias, `ccr`).
36
+ After `uv tool install`, ensure `~/.local/bin` is on your PATH (run `uv tool update-shell` once if needed).
37
+
38
+ To run from a clone without installing: `uv run cursor-chat-recovery`.
39
+
40
+ ## Use
41
+
42
+ cursor-chat-recovery # interactive TUI (or: ccr)
43
+ cursor-chat-recovery --readonly # TUI with mutations disabled
44
+ cursor-chat-recovery --list # workspaces table to stdout
45
+ cursor-chat-recovery --list --json
46
+ cursor-chat-recovery --export <COMPOSER_ID> --format markdown -o chat.md
47
+ cursor-chat-recovery --reassign <COMPOSER_IDS,COMMA,SEP> <TARGET_WS_ID> --yes
48
+ cursor-chat-recovery --merge <SRC_WS_ID> <TARGET_WS_ID> --yes
49
+
50
+ Close Cursor before any mutation. The tool refuses to write while Cursor is running.
51
+
52
+ ## Keys
53
+
54
+ ### Global
55
+
56
+ | Key | Action |
57
+ |-----|--------|
58
+ | `?` | Open help screen |
59
+ | `q` | Quit |
60
+ | `esc` | Back / cancel (clears an active filter first) |
61
+ | `ctrl-c` | Force quit |
62
+
63
+ ### Workspaces (project list)
64
+
65
+ | Key | Action |
66
+ |-----|--------|
67
+ | `up` / `down` | Move selection |
68
+ | `pgup` / `pgdn` | Page up / down |
69
+ | `home` / `end` | Jump to first / last |
70
+ | `enter` | Open workspace's chats |
71
+ | `s` | Cycle sort order (last activity → chat count → name → health) |
72
+ | `/` | Filter by name or path (`enter` keeps filter, `esc` clears) |
73
+
74
+ ### Chats (within a workspace)
75
+
76
+ | Key | Action |
77
+ |-----|--------|
78
+ | `up` / `down` | Move selection |
79
+ | `pgup` / `pgdn` | Page up / down |
80
+ | `enter` | View messages |
81
+ | `space` | Select / deselect chat for bulk actions |
82
+ | `a` | Select all chats |
83
+ | `A` | Deselect all chats |
84
+ | `m` | Move selected (or highlighted) chats to another workspace (`r` is a legacy alias) |
85
+ | `e` | Export selected (or highlighted) chats to Markdown files |
86
+
87
+ ### Messages (within a chat)
88
+
89
+ | Key | Action |
90
+ |-----|--------|
91
+ | `up` / `down`, `pgup` / `pgdn`, `home` / `end` | Scroll |
92
+ | `e` | Export this chat |
93
+
94
+ ### Moving chats
95
+
96
+ Press `m` on the chats screen to open the move-target picker. Workspaces are
97
+ identified by name, path, chat count, and last activity so ambiguous short
98
+ names are distinguishable. Type `/` to filter the list; the current workspace
99
+ is marked and cannot be selected as a target. After you confirm, a timestamped
100
+ backup is written to `~/.cursor-chat-recovery/backups/` before any data is
101
+ touched. Cursor must be closed before the move is attempted; the tool refuses
102
+ to write while Cursor is running.
103
+
104
+ ## Safety
105
+
106
+ - Per-session full DB backup written next to `state.vscdb` on first mutation.
107
+ - Per-op headers backup under `~/.cursor-chat-recovery/backups/`.
108
+ - Read-only mode auto-engages on schema mismatch or detected Cursor-running.
109
+ - Reassign is reversible: the per-op backup restores the prior `composer.composerHeaders`.
110
+
111
+ ## Schema drift
112
+
113
+ When Cursor changes its schema, the tool detects the mismatch on startup and shows a copy-pastable prompt you can paste into a coding agent to adapt the tool. The agent prompt names the affected files and what to change.
114
+
115
+ ## Development
116
+
117
+ uv sync --dev
118
+ uv run pytest
119
+ uv run ruff check
120
+ uv run mypy src/
121
+
122
+ ## License
123
+
124
+ [MIT](LICENSE)
@@ -0,0 +1,114 @@
1
+ # cursor-chat-recovery
2
+
3
+ [![CI](https://github.com/kwiscion/cursor-chat-recovery/actions/workflows/ci.yml/badge.svg)](https://github.com/kwiscion/cursor-chat-recovery/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
6
+
7
+ Did your Cursor chats disappear after you moved, renamed, or re-opened a project? They're not gone. This is an interactive terminal UI to **recover, browse, move, and export Cursor AI chat history** — across all your projects.
8
+
9
+ ## Why chats "disappear"
10
+
11
+ Cursor identifies each workspace by a hash of its identifier URI. Reopening a project from a different path, or saving an Untitled multi-folder workspace as a `.code-workspace` file, mints a new workspace identity and detaches all prior chats from the sidebar. The conversations are still in `globalStorage/state.vscdb` keyed by `composerId` — they just need their `workspaceIdentifier` rewritten to point at the new workspace. That's what this tool does, with backups at every step.
12
+
13
+ It's also useful when nothing is broken: browse every chat you've ever had in any project, move chats between workspaces, and export conversations to Markdown.
14
+
15
+ ## Install
16
+
17
+ Requires Python 3.10+. With [uv](https://docs.astral.sh/uv/):
18
+
19
+ uv tool install git+https://github.com/kwiscion/cursor-chat-recovery
20
+
21
+ or with pipx:
22
+
23
+ pipx install git+https://github.com/kwiscion/cursor-chat-recovery
24
+
25
+ Both install the `cursor-chat-recovery` executable (and a short alias, `ccr`).
26
+ After `uv tool install`, ensure `~/.local/bin` is on your PATH (run `uv tool update-shell` once if needed).
27
+
28
+ To run from a clone without installing: `uv run cursor-chat-recovery`.
29
+
30
+ ## Use
31
+
32
+ cursor-chat-recovery # interactive TUI (or: ccr)
33
+ cursor-chat-recovery --readonly # TUI with mutations disabled
34
+ cursor-chat-recovery --list # workspaces table to stdout
35
+ cursor-chat-recovery --list --json
36
+ cursor-chat-recovery --export <COMPOSER_ID> --format markdown -o chat.md
37
+ cursor-chat-recovery --reassign <COMPOSER_IDS,COMMA,SEP> <TARGET_WS_ID> --yes
38
+ cursor-chat-recovery --merge <SRC_WS_ID> <TARGET_WS_ID> --yes
39
+
40
+ Close Cursor before any mutation. The tool refuses to write while Cursor is running.
41
+
42
+ ## Keys
43
+
44
+ ### Global
45
+
46
+ | Key | Action |
47
+ |-----|--------|
48
+ | `?` | Open help screen |
49
+ | `q` | Quit |
50
+ | `esc` | Back / cancel (clears an active filter first) |
51
+ | `ctrl-c` | Force quit |
52
+
53
+ ### Workspaces (project list)
54
+
55
+ | Key | Action |
56
+ |-----|--------|
57
+ | `up` / `down` | Move selection |
58
+ | `pgup` / `pgdn` | Page up / down |
59
+ | `home` / `end` | Jump to first / last |
60
+ | `enter` | Open workspace's chats |
61
+ | `s` | Cycle sort order (last activity → chat count → name → health) |
62
+ | `/` | Filter by name or path (`enter` keeps filter, `esc` clears) |
63
+
64
+ ### Chats (within a workspace)
65
+
66
+ | Key | Action |
67
+ |-----|--------|
68
+ | `up` / `down` | Move selection |
69
+ | `pgup` / `pgdn` | Page up / down |
70
+ | `enter` | View messages |
71
+ | `space` | Select / deselect chat for bulk actions |
72
+ | `a` | Select all chats |
73
+ | `A` | Deselect all chats |
74
+ | `m` | Move selected (or highlighted) chats to another workspace (`r` is a legacy alias) |
75
+ | `e` | Export selected (or highlighted) chats to Markdown files |
76
+
77
+ ### Messages (within a chat)
78
+
79
+ | Key | Action |
80
+ |-----|--------|
81
+ | `up` / `down`, `pgup` / `pgdn`, `home` / `end` | Scroll |
82
+ | `e` | Export this chat |
83
+
84
+ ### Moving chats
85
+
86
+ Press `m` on the chats screen to open the move-target picker. Workspaces are
87
+ identified by name, path, chat count, and last activity so ambiguous short
88
+ names are distinguishable. Type `/` to filter the list; the current workspace
89
+ is marked and cannot be selected as a target. After you confirm, a timestamped
90
+ backup is written to `~/.cursor-chat-recovery/backups/` before any data is
91
+ touched. Cursor must be closed before the move is attempted; the tool refuses
92
+ to write while Cursor is running.
93
+
94
+ ## Safety
95
+
96
+ - Per-session full DB backup written next to `state.vscdb` on first mutation.
97
+ - Per-op headers backup under `~/.cursor-chat-recovery/backups/`.
98
+ - Read-only mode auto-engages on schema mismatch or detected Cursor-running.
99
+ - Reassign is reversible: the per-op backup restores the prior `composer.composerHeaders`.
100
+
101
+ ## Schema drift
102
+
103
+ When Cursor changes its schema, the tool detects the mismatch on startup and shows a copy-pastable prompt you can paste into a coding agent to adapt the tool. The agent prompt names the affected files and what to change.
104
+
105
+ ## Development
106
+
107
+ uv sync --dev
108
+ uv run pytest
109
+ uv run ruff check
110
+ uv run mypy src/
111
+
112
+ ## License
113
+
114
+ [MIT](LICENSE)