ccmv 1.0.0

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.
package/CLAUDE.md ADDED
@@ -0,0 +1,159 @@
1
+ # ccmv - Project Guidelines
2
+
3
+ ## Overview
4
+
5
+ `ccmv` is a Node.js CLI tool that migrates project directories, updating all Claude Code and/or Cursor references when a project is moved to a new location.
6
+
7
+ **Supported configurations:**
8
+ - Claude Code + Cursor (both)
9
+ - Claude Code only
10
+ - Cursor only
11
+
12
+ ## Project Structure
13
+
14
+ ```
15
+ ccmv/
16
+ ├── package.json # npm package config with bin entry
17
+ ├── bin/
18
+ │ └── ccmv.js # CLI entry point
19
+ ├── lib/
20
+ │ ├── index.js # Main orchestration logic
21
+ │ ├── logger.js # Colored console output
22
+ │ ├── utils.js # Path encoding, file URIs, hashing
23
+ │ ├── claude.js # Claude Code operations
24
+ │ └── cursor.js # Cursor editor operations
25
+ ├── README.md # User documentation
26
+ └── CLAUDE.md # This file
27
+ ```
28
+
29
+ ## Technical Details
30
+
31
+ ### Claude Code Data Locations
32
+
33
+ - `~/.claude/projects/{encoded-path}/` - Project-specific session data
34
+ - `~/.claude/history.jsonl` - Global history file
35
+ - Path encoding: `/`, `:`, spaces → `-`
36
+
37
+ ### Cursor Data Locations
38
+
39
+ ```
40
+ ~/Library/Application Support/Cursor/User/
41
+ ├── globalStorage/
42
+ │ ├── storage.json # profileAssociations.workspaces (path list)
43
+ │ └── state.vscdb # SQLite ItemTable: history.recentlyOpenedPathsList, repositoryTracker.paths
44
+ └── workspaceStorage/
45
+ └── {hash}/
46
+ ├── workspace.json # {"folder": "file://..."} or {"workspace": "file://..."}
47
+ └── state.vscdb # Workspace-specific SQLite (ItemTable + cursorDiskKV)
48
+ ```
49
+
50
+ - **Path format**: `file:///Users/foo/my%20project` (URL encoded)
51
+ - **SQLite update**: Uses `better-sqlite3` for database operations
52
+
53
+ ### Cursor Workspace Hash (Critical)
54
+
55
+ Cursor/VSCode uses MD5 hash of `path + birthtime_ms` for workspaceStorage directory names:
56
+
57
+ ```javascript
58
+ import { createHash } from 'node:crypto';
59
+ import { statSync } from 'node:fs';
60
+
61
+ const stat = statSync(path);
62
+ const hash = createHash('md5')
63
+ .update(path)
64
+ .update(String(stat.birthtime.getTime()))
65
+ .digest('hex');
66
+ ```
67
+
68
+ **Key Points:**
69
+ - Uses Node.js native `fs.statSync().birthtime.getTime()` for consistent millisecond precision
70
+ - `mv` command preserves birthtime on same volume, so new path hash is predictable
71
+ - When project moves, ccmv renames workspace directory to match new hash
72
+ - Chat history is stored in `workspaceStorage/{hash}/state.vscdb` (cursorDiskKV table)
73
+
74
+ **Duplicate Workspace Handling:**
75
+ - Multiple workspace directories can point to the same path (from failed migrations or Cursor quirks)
76
+ - `mergeDuplicateWorkspaces()` finds all workspaces pointing to new path
77
+ - Keeps the workspace with the **larger** `state.vscdb` (contains more chat history)
78
+
79
+ ### Key Modules
80
+
81
+ | Module | Purpose |
82
+ |--------|---------|
83
+ | `lib/index.js` | CLI parsing, orchestration, rollback handling |
84
+ | `lib/logger.js` | Colored log output functions |
85
+ | `lib/utils.js` | `encodePath`, `pathToFileUri`, `getWorkspaceHash`, `resolvePath` |
86
+ | `lib/claude.js` | Backup, rename, update, verify Claude data |
87
+ | `lib/cursor.js` | Detect, backup, update Cursor storage.json and SQLite DBs |
88
+
89
+ ### Error Handling
90
+
91
+ - Validates all paths before making changes
92
+ - Requires at least one of Claude Code or Cursor data (fails if neither exists)
93
+ - Creates backups before any modifications
94
+ - Auto-rollback on any error during migration
95
+ - Cursor must not be running (checked before migration)
96
+
97
+ ## Development
98
+
99
+ ### Setup
100
+
101
+ ```bash
102
+ npm install
103
+ ```
104
+
105
+ ### Testing
106
+
107
+ ```bash
108
+ # Create test project
109
+ mkdir -p /tmp/test-proj-a
110
+ mkdir -p ~/.claude/projects/-tmp-test-proj-a
111
+ echo '{"cwd":"/tmp/test-proj-a"}' > ~/.claude/projects/-tmp-test-proj-a/test.jsonl
112
+
113
+ # Test dry-run
114
+ node bin/ccmv.js --dry-run /tmp/test-proj-a /tmp/test-proj-b
115
+
116
+ # Test with npx (from package directory)
117
+ npx . --dry-run /tmp/test-proj-a /tmp/test-proj-b
118
+
119
+ # Cleanup
120
+ rm -rf /tmp/test-proj-* ~/.claude/projects/-tmp-test-proj-*
121
+ ```
122
+
123
+ ### Local Development
124
+
125
+ ```bash
126
+ # Run directly
127
+ node bin/ccmv.js --help
128
+
129
+ # Or link globally for testing
130
+ npm link
131
+ ccmv --help
132
+ ```
133
+
134
+ ### Known Issues
135
+
136
+ - Cursor must be closed during migration (enforced by `checkCursorNotRunning`)
137
+ - **Cross-volume moves**: `mv` to different volume may not preserve birthtime, potentially breaking hash prediction (untested)
138
+ - On Linux, Cursor data is at `~/.config/Cursor/User/` instead of `~/Library/Application Support/`
139
+
140
+ ### Troubleshooting Cursor Chat History Loss
141
+
142
+ If chat history is lost after migration:
143
+
144
+ 1. **Check workspace directories**: Look at `~/Library/Application Support/Cursor/User/workspaceStorage/*/workspace.json` for entries pointing to your path
145
+ 2. **Compare state.vscdb sizes**: Larger file usually has more chat data
146
+ 3. **Calculate expected hash**:
147
+ ```javascript
148
+ import { createHash } from 'node:crypto';
149
+ import { statSync } from 'node:fs';
150
+
151
+ const path = '/your/project/path';
152
+ const stat = statSync(path);
153
+ const hash = createHash('md5')
154
+ .update(path)
155
+ .update(String(stat.birthtime.getTime()))
156
+ .digest('hex');
157
+ console.log(hash);
158
+ ```
159
+ 4. **Check cursorDiskKV table**: Chat data is in `state.vscdb` under key `composer.composerData`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Saqoosha
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.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # ccmv
2
+
3
+ Claude Code project directory migration tool.
4
+
5
+ ## Problem
6
+
7
+ When you move a project directory, Claude Code loses track of your conversation history because it's stored in `~/.claude/projects/` using path-encoded directory names.
8
+
9
+ ## Solution
10
+
11
+ `ccmv` moves your project and updates all Claude Code and/or Cursor references automatically. Works with:
12
+ - Projects with both Claude Code and Cursor data
13
+ - Claude Code-only projects (no Cursor)
14
+ - Cursor-only projects (no Claude Code history)
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ # Using npm (recommended)
20
+ npm install -g ccmv
21
+
22
+ # Or using npx (no installation required)
23
+ npx ccmv --help
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ```
29
+ ccmv [OPTIONS] <old-path> <new-path>
30
+
31
+ Options:
32
+ --refs-only Only update references (don't move directory)
33
+ --dry-run Preview changes without executing
34
+ --keep-backup Keep backup after successful migration
35
+ --no-cursor Skip Cursor editor data updates
36
+ --quiet Suppress detailed output
37
+ --help Show help
38
+ ```
39
+
40
+ ## Examples
41
+
42
+ ```bash
43
+ # Move project to new location
44
+ ccmv ~/projects/myapp ~/work/myapp
45
+
46
+ # Or using npx
47
+ npx ccmv ~/projects/myapp ~/work/myapp
48
+
49
+ # Preview what would happen
50
+ ccmv --dry-run ~/old-project ~/new-project
51
+
52
+ # Already moved? Just update refs
53
+ ccmv --refs-only /old/path /new/path
54
+ ```
55
+
56
+ ## What It Does
57
+
58
+ 1. Detects Claude Code and/or Cursor data for the project
59
+ 2. Creates backup of existing data
60
+ 3. Moves project directory (unless `--refs-only`)
61
+ 4. Updates Claude Code data (if exists):
62
+ - Renames `~/.claude/projects/{encoded-path}/`
63
+ - Updates `cwd` field in all JSONL files
64
+ - Updates `~/.claude/history.jsonl`
65
+ 5. Updates Cursor workspace data (if exists):
66
+ - Renames `workspaceStorage/{hash}/` directory
67
+ - Updates `storage.json` (profile associations)
68
+ - Updates `state.vscdb` (global SQLite database)
69
+ - Updates `workspaceStorage/*/workspace.json`
70
+ - Updates `workspaceStorage/*/state.vscdb`
71
+ 6. Verifies migration success
72
+ 7. Auto-rollback on any failure
73
+
74
+ **Note:** Migration requires at least one of Claude Code or Cursor data to exist. If neither exists, use regular `mv` command.
75
+
76
+ ## How Claude Code Stores Data
77
+
78
+ ```
79
+ ~/.claude/
80
+ ├── projects/
81
+ │ └── -Users-jane-myproject/ # Encoded from /Users/jane/myproject
82
+ │ ├── session-abc.jsonl # Contains "cwd":"/Users/jane/myproject"
83
+ │ └── subagents/
84
+ │ └── agent-xyz.jsonl
85
+ └── history.jsonl # Global history with cwd fields
86
+ ```
87
+
88
+ Path encoding: `/Users/jane/foo bar` → `-Users-jane-foo-bar`
89
+
90
+ ## Cursor Data (Auto-detected)
91
+
92
+ If Cursor is installed, `ccmv` also updates:
93
+
94
+ ```
95
+ ~/Library/Application Support/Cursor/User/
96
+ ├── globalStorage/
97
+ │ ├── storage.json # Profile workspace associations
98
+ │ └── state.vscdb # SQLite: history, repository paths
99
+ └── workspaceStorage/
100
+ └── {hash}/
101
+ ├── workspace.json # Workspace folder URI
102
+ └── state.vscdb # Workspace-specific data
103
+ ```
104
+
105
+ **Note:** Cursor must be closed during migration to prevent data corruption.
106
+
107
+ ## Requirements
108
+
109
+ - Node.js 18.0.0 or later
110
+ - macOS or Linux
111
+
112
+ ## License
113
+
114
+ MIT
package/bin/ccmv.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { main } from '../lib/index.js';
4
+
5
+ main(process.argv.slice(2));