cursor-history 0.6.0 → 0.9.1

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 (101) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +371 -9
  3. package/dist/cli/commands/backup.d.ts +9 -0
  4. package/dist/cli/commands/backup.d.ts.map +1 -0
  5. package/dist/cli/commands/backup.js +168 -0
  6. package/dist/cli/commands/backup.js.map +1 -0
  7. package/dist/cli/commands/export.d.ts.map +1 -1
  8. package/dist/cli/commands/export.js +38 -6
  9. package/dist/cli/commands/export.js.map +1 -1
  10. package/dist/cli/commands/list-backups.d.ts +9 -0
  11. package/dist/cli/commands/list-backups.d.ts.map +1 -0
  12. package/dist/cli/commands/list-backups.js +166 -0
  13. package/dist/cli/commands/list-backups.js.map +1 -0
  14. package/dist/cli/commands/list.d.ts.map +1 -1
  15. package/dist/cli/commands/list.js +44 -9
  16. package/dist/cli/commands/list.js.map +1 -1
  17. package/dist/cli/commands/migrate-session.d.ts +12 -0
  18. package/dist/cli/commands/migrate-session.d.ts.map +1 -0
  19. package/dist/cli/commands/migrate-session.js +125 -0
  20. package/dist/cli/commands/migrate-session.js.map +1 -0
  21. package/dist/cli/commands/migrate.d.ts +13 -0
  22. package/dist/cli/commands/migrate.d.ts.map +1 -0
  23. package/dist/cli/commands/migrate.js +122 -0
  24. package/dist/cli/commands/migrate.js.map +1 -0
  25. package/dist/cli/commands/restore.d.ts +9 -0
  26. package/dist/cli/commands/restore.d.ts.map +1 -0
  27. package/dist/cli/commands/restore.js +192 -0
  28. package/dist/cli/commands/restore.js.map +1 -0
  29. package/dist/cli/commands/search.d.ts.map +1 -1
  30. package/dist/cli/commands/search.js +30 -2
  31. package/dist/cli/commands/search.js.map +1 -1
  32. package/dist/cli/commands/show.d.ts.map +1 -1
  33. package/dist/cli/commands/show.js +31 -3
  34. package/dist/cli/commands/show.js.map +1 -1
  35. package/dist/cli/index.js +10 -0
  36. package/dist/cli/index.js.map +1 -1
  37. package/dist/core/backup.d.ts +86 -0
  38. package/dist/core/backup.d.ts.map +1 -0
  39. package/dist/core/backup.js +727 -0
  40. package/dist/core/backup.js.map +1 -0
  41. package/dist/core/database/debug.d.ts +12 -0
  42. package/dist/core/database/debug.d.ts.map +1 -0
  43. package/dist/core/database/debug.js +16 -0
  44. package/dist/core/database/debug.js.map +1 -0
  45. package/dist/core/database/drivers/better-sqlite3.d.ts +11 -0
  46. package/dist/core/database/drivers/better-sqlite3.d.ts.map +1 -0
  47. package/dist/core/database/drivers/better-sqlite3.js +93 -0
  48. package/dist/core/database/drivers/better-sqlite3.js.map +1 -0
  49. package/dist/core/database/drivers/node-sqlite.d.ts +15 -0
  50. package/dist/core/database/drivers/node-sqlite.d.ts.map +1 -0
  51. package/dist/core/database/drivers/node-sqlite.js +135 -0
  52. package/dist/core/database/drivers/node-sqlite.js.map +1 -0
  53. package/dist/core/database/errors.d.ts +24 -0
  54. package/dist/core/database/errors.d.ts.map +1 -0
  55. package/dist/core/database/errors.js +38 -0
  56. package/dist/core/database/errors.js.map +1 -0
  57. package/dist/core/database/index.d.ts +98 -0
  58. package/dist/core/database/index.d.ts.map +1 -0
  59. package/dist/core/database/index.js +125 -0
  60. package/dist/core/database/index.js.map +1 -0
  61. package/dist/core/database/registry.d.ts +81 -0
  62. package/dist/core/database/registry.d.ts.map +1 -0
  63. package/dist/core/database/registry.js +171 -0
  64. package/dist/core/database/registry.js.map +1 -0
  65. package/dist/core/database/types.d.ts +115 -0
  66. package/dist/core/database/types.d.ts.map +1 -0
  67. package/dist/core/database/types.js +8 -0
  68. package/dist/core/database/types.js.map +1 -0
  69. package/dist/core/migrate.d.ts +40 -0
  70. package/dist/core/migrate.d.ts.map +1 -0
  71. package/dist/core/migrate.js +586 -0
  72. package/dist/core/migrate.js.map +1 -0
  73. package/dist/core/storage.d.ts +84 -10
  74. package/dist/core/storage.d.ts.map +1 -1
  75. package/dist/core/storage.js +319 -33
  76. package/dist/core/storage.js.map +1 -1
  77. package/dist/core/types.d.ts +252 -0
  78. package/dist/core/types.d.ts.map +1 -1
  79. package/dist/lib/backup.d.ts +98 -0
  80. package/dist/lib/backup.d.ts.map +1 -0
  81. package/dist/lib/backup.js +108 -0
  82. package/dist/lib/backup.js.map +1 -0
  83. package/dist/lib/config.d.ts +3 -1
  84. package/dist/lib/config.d.ts.map +1 -1
  85. package/dist/lib/config.js +10 -0
  86. package/dist/lib/config.js.map +1 -1
  87. package/dist/lib/errors.d.ts +229 -0
  88. package/dist/lib/errors.d.ts.map +1 -1
  89. package/dist/lib/errors.js +361 -0
  90. package/dist/lib/errors.js.map +1 -1
  91. package/dist/lib/index.d.ts +133 -24
  92. package/dist/lib/index.d.ts.map +1 -1
  93. package/dist/lib/index.js +212 -49
  94. package/dist/lib/index.js.map +1 -1
  95. package/dist/lib/platform.d.ts +11 -0
  96. package/dist/lib/platform.d.ts.map +1 -1
  97. package/dist/lib/platform.js +32 -0
  98. package/dist/lib/platform.js.map +1 -1
  99. package/dist/lib/types.d.ts +267 -0
  100. package/dist/lib/types.d.ts.map +1 -1
  101. package/package.json +23 -3
@@ -0,0 +1,122 @@
1
+ /**
2
+ * CLI command for migrating all sessions between workspaces
3
+ *
4
+ * Usage:
5
+ * cursor-history migrate <source> <destination>
6
+ * cursor-history migrate /old/project /new/project
7
+ * cursor-history migrate --copy /project /backup/project
8
+ * cursor-history migrate --dry-run /old/path /new/path
9
+ * cursor-history migrate --force /old/path /existing/path
10
+ */
11
+ import pc from 'picocolors';
12
+ import { migrateWorkspace } from '../../core/migrate.js';
13
+ import { expandPath } from '../../lib/platform.js';
14
+ import { isWorkspaceNotFoundError, isSameWorkspaceError, isNoSessionsFoundError, isDestinationHasSessionsError, isNestedPathError, } from '../../lib/errors.js';
15
+ export function registerMigrateCommand(program) {
16
+ program
17
+ .command('migrate')
18
+ .description('Move or copy all sessions from one workspace to another')
19
+ .argument('<source>', 'Source workspace path')
20
+ .argument('<destination>', 'Destination workspace path')
21
+ .option('--dry-run', 'Preview migration without making changes')
22
+ .option('--copy', 'Copy sessions instead of moving (keeps originals)')
23
+ .option('-f, --force', 'Proceed even if destination has existing sessions')
24
+ .option('--debug', 'Show detailed path transformation logs')
25
+ .action(async (sourceArg, destinationArg, options) => {
26
+ const globalOptions = program.opts();
27
+ const dataPath = globalOptions.dataPath;
28
+ const jsonOutput = globalOptions.json || options.json;
29
+ try {
30
+ // Expand ~ in paths
31
+ const source = expandPath(sourceArg);
32
+ const destination = expandPath(destinationArg);
33
+ // Determine mode
34
+ const mode = options.copy ? 'copy' : 'move';
35
+ // Perform migration
36
+ const result = await migrateWorkspace({
37
+ source,
38
+ destination,
39
+ mode,
40
+ dryRun: options.dryRun ?? false,
41
+ force: options.force ?? false,
42
+ dataPath,
43
+ debug: options.debug ?? false,
44
+ });
45
+ // Output results
46
+ if (jsonOutput) {
47
+ console.log(JSON.stringify(result, null, 2));
48
+ }
49
+ else {
50
+ outputResult(result);
51
+ }
52
+ // Exit with error code if any failures
53
+ if (!result.success) {
54
+ process.exit(1);
55
+ }
56
+ }
57
+ catch (error) {
58
+ if (jsonOutput) {
59
+ console.log(JSON.stringify({ error: formatError(error) }, null, 2));
60
+ }
61
+ else {
62
+ console.error(pc.red(formatError(error)));
63
+ }
64
+ process.exit(1);
65
+ }
66
+ });
67
+ }
68
+ function outputResult(result) {
69
+ if (result.dryRun) {
70
+ console.log(pc.yellow('Dry run - no changes made\n'));
71
+ }
72
+ const action = result.dryRun ? 'Would migrate' : 'Migrated';
73
+ const modeLabel = result.mode === 'copy' ? 'copied' : 'moved';
74
+ console.log(`${action} ${pc.bold(result.totalSessions)} session(s) from:`);
75
+ console.log(` ${pc.cyan(result.source)}`);
76
+ console.log(`to:`);
77
+ console.log(` ${pc.cyan(result.destination)}\n`);
78
+ if (result.successCount > 0) {
79
+ const actionLabel = result.dryRun ? `would be ${modeLabel}` : modeLabel;
80
+ console.log(pc.green(`✓ ${result.successCount} session(s) ${actionLabel} successfully`));
81
+ }
82
+ if (result.failureCount > 0) {
83
+ console.log(pc.red(`✗ ${result.failureCount} session(s) failed to migrate:\n`));
84
+ for (const r of result.results.filter((r) => !r.success)) {
85
+ console.log(` ${pc.red('✗')} ${pc.cyan(r.sessionId.slice(0, 8))}...`);
86
+ console.log(` ${pc.red(r.error ?? 'Unknown error')}\n`);
87
+ }
88
+ }
89
+ // Overall status
90
+ if (result.success) {
91
+ console.log(pc.green('\n✓ Migration completed successfully'));
92
+ }
93
+ else {
94
+ console.log(pc.red('\n✗ Migration completed with errors'));
95
+ }
96
+ }
97
+ function formatError(error) {
98
+ if (isWorkspaceNotFoundError(error)) {
99
+ return `Workspace not found: ${error.path}\nPlease open the project in Cursor first to create the workspace.`;
100
+ }
101
+ if (isSameWorkspaceError(error)) {
102
+ return `Source and destination are the same: ${error.path}\nSpecify different source and destination paths.`;
103
+ }
104
+ if (isNoSessionsFoundError(error)) {
105
+ return `No sessions found for workspace: ${error.path}\nRun 'cursor-history list --workspace "${error.path}"' to verify.`;
106
+ }
107
+ if (isDestinationHasSessionsError(error)) {
108
+ return `Destination already has ${error.sessionCount} session(s): ${error.path}\nUse --force to proceed (will add sessions alongside existing ones).`;
109
+ }
110
+ if (isNestedPathError(error)) {
111
+ return `Destination is nested within source: ${error.destination} is inside ${error.source}\nThis would cause infinite path replacement loops. Choose a different destination.`;
112
+ }
113
+ if (error instanceof Error) {
114
+ // Check for database lock error
115
+ if (error.message.includes('SQLITE_BUSY') || error.message.includes('database is locked')) {
116
+ return 'Database is locked. Please close Cursor and try again.';
117
+ }
118
+ return error.message;
119
+ }
120
+ return String(error);
121
+ }
122
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Restore command - restore chat history from a backup file
3
+ */
4
+ import type { Command } from 'commander';
5
+ /**
6
+ * Register the restore command
7
+ */
8
+ export declare function registerRestoreCommand(program: Command): void;
9
+ //# sourceMappingURL=restore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/restore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqGzC;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiH7D"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Restore command - restore chat history from a backup file
3
+ */
4
+ import pc from 'picocolors';
5
+ import { existsSync } from 'node:fs';
6
+ import { restoreBackup, validateBackup } from '../../core/backup.js';
7
+ import { handleError, ExitCode } from '../errors.js';
8
+ import { expandPath, contractPath } from '../../lib/platform.js';
9
+ /**
10
+ * Format duration for display
11
+ */
12
+ function formatDuration(ms) {
13
+ if (ms < 1000) {
14
+ return `${ms}ms`;
15
+ }
16
+ return `${(ms / 1000).toFixed(1)}s`;
17
+ }
18
+ /**
19
+ * T050: Progress display for restore command
20
+ */
21
+ function displayProgress(progress) {
22
+ const phases = {
23
+ validating: '🔍 Validating backup integrity...',
24
+ extracting: '📦 Extracting files...',
25
+ finalizing: '✨ Finalizing restore...',
26
+ };
27
+ const phaseText = phases[progress.phase];
28
+ const fileProgress = progress.totalFiles > 0
29
+ ? ` [${progress.filesCompleted}/${progress.totalFiles}]`
30
+ : '';
31
+ const currentFile = progress.currentFile ? ` ${pc.dim(progress.currentFile)}` : '';
32
+ // Show integrity status during validation
33
+ const integrityText = progress.phase === 'validating' && progress.integrityStatus === 'warnings'
34
+ ? pc.yellow(' (some files have warnings)')
35
+ : '';
36
+ // Clear line and print progress
37
+ process.stdout.write(`\r${phaseText}${fileProgress}${currentFile}${integrityText}`.padEnd(80));
38
+ }
39
+ /**
40
+ * Format restore result for JSON output
41
+ */
42
+ function formatRestoreResultJson(result) {
43
+ return JSON.stringify({
44
+ success: result.success,
45
+ targetPath: result.targetPath,
46
+ filesRestored: result.filesRestored,
47
+ durationMs: result.durationMs,
48
+ ...(result.warnings.length > 0 && { warnings: result.warnings }),
49
+ ...(result.error && { error: result.error }),
50
+ }, null, 2);
51
+ }
52
+ /**
53
+ * Format restore result for human-readable output
54
+ */
55
+ function formatRestoreResult(result) {
56
+ const lines = [];
57
+ if (result.success) {
58
+ lines.push(pc.green('✓ Backup restored successfully!'));
59
+ lines.push('');
60
+ lines.push(` ${pc.bold('Target:')} ${contractPath(result.targetPath)}`);
61
+ lines.push(` ${pc.bold('Files restored:')} ${result.filesRestored}`);
62
+ lines.push(` ${pc.bold('Duration:')} ${formatDuration(result.durationMs)}`);
63
+ if (result.warnings.length > 0) {
64
+ lines.push('');
65
+ lines.push(pc.yellow(' Warnings:'));
66
+ for (const warning of result.warnings) {
67
+ lines.push(` ${pc.dim('•')} ${warning}`);
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ lines.push(pc.red('✗ Restore failed'));
73
+ lines.push('');
74
+ if (result.error) {
75
+ lines.push(` ${pc.bold('Error:')} ${result.error}`);
76
+ }
77
+ }
78
+ return lines.join('\n');
79
+ }
80
+ /**
81
+ * Register the restore command
82
+ */
83
+ export function registerRestoreCommand(program) {
84
+ program
85
+ .command('restore <backup>')
86
+ .description('Restore chat history from a backup file')
87
+ .option('-t, --target <path>', 'Target Cursor data path (default: platform-specific Cursor data directory)')
88
+ .option('-f, --force', 'Overwrite existing data without prompting')
89
+ .action(async (backupArg, options, command) => {
90
+ const globalOptions = command.parent?.opts();
91
+ const useJson = options.json ?? globalOptions?.json ?? false;
92
+ const customPath = options.dataPath ?? globalOptions?.dataPath;
93
+ // Resolve backup path
94
+ const backupPath = expandPath(backupArg);
95
+ try {
96
+ // T051: Check if backup file exists
97
+ if (!existsSync(backupPath)) {
98
+ if (useJson) {
99
+ console.log(JSON.stringify({ error: 'Backup file not found', path: backupPath }));
100
+ }
101
+ else {
102
+ console.error(pc.red('Backup file not found:'));
103
+ console.error(pc.dim(` ${backupPath}`));
104
+ }
105
+ process.exit(ExitCode.USAGE_ERROR);
106
+ }
107
+ // T052: Validate backup before attempting restore
108
+ const validation = validateBackup(backupPath);
109
+ if (validation.status === 'invalid') {
110
+ if (useJson) {
111
+ console.log(JSON.stringify({
112
+ error: 'Invalid or corrupted backup',
113
+ errors: validation.errors
114
+ }));
115
+ }
116
+ else {
117
+ console.error(pc.red('Invalid or corrupted backup file:'));
118
+ for (const err of validation.errors) {
119
+ console.error(pc.dim(` ${err}`));
120
+ }
121
+ }
122
+ process.exit(ExitCode.NOT_FOUND);
123
+ }
124
+ // Show warning for backups with integrity issues
125
+ if (validation.status === 'warnings' && !useJson) {
126
+ console.log(pc.yellow(`Warning: Backup has ${validation.corruptedFiles.length} file(s) with checksum mismatches.`));
127
+ console.log(pc.dim('These files will be restored but may be corrupted.\n'));
128
+ }
129
+ // Resolve target path if provided
130
+ const targetPath = options.target
131
+ ? expandPath(options.target)
132
+ : (customPath ? expandPath(customPath) : undefined);
133
+ // Show progress if not JSON mode
134
+ const onProgress = useJson ? undefined : displayProgress;
135
+ // Perform restore
136
+ const result = restoreBackup({
137
+ backupPath,
138
+ targetPath,
139
+ force: options.force ?? false,
140
+ onProgress,
141
+ });
142
+ // Clear progress line
143
+ if (!useJson) {
144
+ process.stdout.write('\r'.padEnd(80) + '\r');
145
+ }
146
+ // Handle different error cases with appropriate exit codes
147
+ if (!result.success) {
148
+ // T053: Target exists without --force
149
+ if (result.error?.includes('already has Cursor data')) {
150
+ if (useJson) {
151
+ console.log(formatRestoreResultJson(result));
152
+ }
153
+ else {
154
+ console.error(pc.red('Target directory already has Cursor data.'));
155
+ console.error(pc.dim('Use --force to overwrite existing data.'));
156
+ }
157
+ process.exit(ExitCode.IO_ERROR);
158
+ }
159
+ // T054: Integrity check failures
160
+ if (result.error?.includes('integrity') || result.error?.includes('checksum')) {
161
+ if (useJson) {
162
+ console.log(formatRestoreResultJson(result));
163
+ }
164
+ else {
165
+ console.error(pc.red('Backup integrity check failed.'));
166
+ console.error(pc.dim(result.error));
167
+ }
168
+ process.exit(5); // Special exit code for integrity failures
169
+ }
170
+ // Generic error
171
+ if (useJson) {
172
+ console.log(formatRestoreResultJson(result));
173
+ }
174
+ else {
175
+ console.error(formatRestoreResult(result));
176
+ }
177
+ process.exit(ExitCode.GENERAL_ERROR);
178
+ }
179
+ // Success
180
+ if (useJson) {
181
+ console.log(formatRestoreResultJson(result));
182
+ }
183
+ else {
184
+ console.log(formatRestoreResult(result));
185
+ }
186
+ }
187
+ catch (error) {
188
+ handleError(error);
189
+ }
190
+ });
191
+ }
192
+ //# sourceMappingURL=restore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore.js","sourceRoot":"","sources":["../../../src/cli/commands/restore.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4C5D"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBzC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwE5D"}
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * Search command - search across chat sessions
3
3
  */
4
+ import pc from 'picocolors';
4
5
  import { searchSessions } from '../../core/storage.js';
6
+ import { validateBackup } from '../../core/backup.js';
5
7
  import { formatSearchResultsTable, formatSearchResultsJson } from '../formatters/index.js';
6
8
  import { NoSearchResultsError, handleError } from '../errors.js';
7
- import { expandPath } from '../../lib/platform.js';
9
+ import { expandPath, contractPath } from '../../lib/platform.js';
8
10
  /**
9
11
  * Register the search command
10
12
  */
@@ -14,15 +16,37 @@ export function registerSearchCommand(program) {
14
16
  .description('Search chat history for a keyword')
15
17
  .option('-n, --limit <number>', 'Maximum results to show', '10')
16
18
  .option('-c, --context <chars>', 'Context characters around match', '50')
19
+ .option('-b, --backup <path>', 'Search in backup file instead of live data')
17
20
  .action(async (query, options, command) => {
18
21
  const globalOptions = command.parent?.opts();
19
22
  const useJson = options.json ?? globalOptions?.json ?? false;
20
23
  const customPath = options.dataPath ?? globalOptions?.dataPath;
21
24
  const workspaceFilter = options.workspace ?? globalOptions?.workspace;
25
+ const backupPath = options.backup ? expandPath(options.backup) : undefined;
22
26
  const limit = parseInt(options.limit ?? '10', 10);
23
27
  const contextChars = parseInt(options.context ?? '50', 10);
28
+ // T036: Validate backup if searching from backup
29
+ if (backupPath) {
30
+ const validation = validateBackup(backupPath);
31
+ if (validation.status === 'invalid') {
32
+ if (useJson) {
33
+ console.log(JSON.stringify({ error: 'Invalid backup', errors: validation.errors }));
34
+ }
35
+ else {
36
+ console.error(pc.red('Invalid backup file:'));
37
+ for (const err of validation.errors) {
38
+ console.error(pc.dim(` ${err}`));
39
+ }
40
+ }
41
+ process.exit(3);
42
+ }
43
+ if (validation.status === 'warnings' && !useJson) {
44
+ console.error(pc.yellow(`Warning: Backup has integrity issues (${validation.corruptedFiles.length} corrupted files)`));
45
+ console.error(pc.dim('Continuing with intact files...\n'));
46
+ }
47
+ }
24
48
  try {
25
- const results = searchSessions(query, { limit, contextChars, workspacePath: workspaceFilter }, customPath ? expandPath(customPath) : undefined);
49
+ const results = await searchSessions(query, { limit, contextChars, workspacePath: workspaceFilter }, customPath ? expandPath(customPath) : undefined, backupPath);
26
50
  if (results.length === 0) {
27
51
  if (useJson) {
28
52
  console.log(JSON.stringify({ query, count: 0, totalMatches: 0, results: [] }));
@@ -32,6 +56,10 @@ export function registerSearchCommand(program) {
32
56
  }
33
57
  return;
34
58
  }
59
+ // Show backup source indicator if searching from backup
60
+ if (backupPath && !useJson) {
61
+ console.log(pc.dim(`Searching in backup: ${contractPath(backupPath)}\n`));
62
+ }
35
63
  if (useJson) {
36
64
  console.log(formatSearchResultsJson(results, query));
37
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAUnD;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,gBAAgB,CAAC;SACzB,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,EAAE,IAAI,CAAC;SAC/D,MAAM,CAAC,uBAAuB,EAAE,iCAAiC,EAAE,IAAI,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,OAA6B,EAAE,OAAgB,EAAE,EAAE;QAC/E,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,EAIzC,CAAC;QACF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,aAAa,EAAE,IAAI,IAAI,KAAK,CAAC;QAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,IAAI,aAAa,EAAE,QAAQ,CAAC;QAC/D,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,IAAI,aAAa,EAAE,SAAS,CAAC;QAEtE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QAE3D,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,cAAc,CAC5B,KAAK,EACL,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,EACvD,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAChD,CAAC;YAEF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;gBACjF,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC;gBACxC,CAAC;gBACD,OAAO;YACT,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/show.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+C1D"}
1
+ {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/show.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBzC;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+E1D"}
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * Show command - display a single chat session in detail
3
3
  */
4
+ import pc from 'picocolors';
4
5
  import { getSession, listSessions } from '../../core/storage.js';
6
+ import { validateBackup } from '../../core/backup.js';
5
7
  import { formatSessionDetail, formatSessionJson } from '../formatters/index.js';
6
8
  import { SessionNotFoundError, handleError } from '../errors.js';
7
- import { expandPath } from '../../lib/platform.js';
9
+ import { expandPath, contractPath } from '../../lib/platform.js';
8
10
  /**
9
11
  * Register the show command
10
12
  */
@@ -16,21 +18,47 @@ export function registerShowCommand(program) {
16
18
  .option('-t, --think', 'Show full thinking/reasoning text')
17
19
  .option('--tool', 'Show full tool call details (commands, content, results)')
18
20
  .option('-e, --error', 'Show full error messages (default: truncated)')
21
+ .option('-b, --backup <path>', 'Read from backup file instead of live data')
19
22
  .action(async (indexArg, options, command) => {
20
23
  const globalOptions = command.parent?.opts();
21
24
  const useJson = options.json ?? globalOptions?.json ?? false;
22
25
  const customPath = options.dataPath ?? globalOptions?.dataPath;
26
+ const backupPath = options.backup ? expandPath(options.backup) : undefined;
23
27
  const index = parseInt(indexArg, 10);
24
28
  if (isNaN(index) || index < 1) {
25
29
  handleError(new Error(`Invalid index: ${indexArg}. Must be a positive number.`));
26
30
  }
31
+ // T035: Validate backup if reading from backup
32
+ if (backupPath) {
33
+ const validation = validateBackup(backupPath);
34
+ if (validation.status === 'invalid') {
35
+ if (useJson) {
36
+ console.log(JSON.stringify({ error: 'Invalid backup', errors: validation.errors }));
37
+ }
38
+ else {
39
+ console.error(pc.red('Invalid backup file:'));
40
+ for (const err of validation.errors) {
41
+ console.error(pc.dim(` ${err}`));
42
+ }
43
+ }
44
+ process.exit(3);
45
+ }
46
+ if (validation.status === 'warnings' && !useJson) {
47
+ console.error(pc.yellow(`Warning: Backup has integrity issues (${validation.corruptedFiles.length} corrupted files)`));
48
+ console.error(pc.dim('Continuing with intact files...\n'));
49
+ }
50
+ }
27
51
  try {
28
- const session = getSession(index, customPath ? expandPath(customPath) : undefined);
52
+ const session = await getSession(index, customPath ? expandPath(customPath) : undefined, backupPath);
29
53
  if (!session) {
30
54
  // Get max index for error message
31
- const sessions = listSessions({ limit: 0, all: true }, customPath ? expandPath(customPath) : undefined);
55
+ const sessions = await listSessions({ limit: 0, all: true }, customPath ? expandPath(customPath) : undefined, backupPath);
32
56
  throw new SessionNotFoundError(index, sessions.length);
33
57
  }
58
+ // Show backup source indicator if reading from backup
59
+ if (backupPath && !useJson) {
60
+ console.log(pc.dim(`Reading from backup: ${contractPath(backupPath)}\n`));
61
+ }
34
62
  if (useJson) {
35
63
  console.log(formatSessionJson(session, session.workspacePath));
36
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"show.js","sourceRoot":"","sources":["../../../src/cli/commands/show.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAWnD;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,aAAa,EAAE,sCAAsC,CAAC;SAC7D,MAAM,CAAC,aAAa,EAAE,mCAAmC,CAAC;SAC1D,MAAM,CAAC,QAAQ,EAAE,0DAA0D,CAAC;SAC5E,MAAM,CAAC,aAAa,EAAE,+CAA+C,CAAC;SACtE,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAA2B,EAAE,OAAgB,EAAE,EAAE;QAChF,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,EAA2C,CAAC;QACtF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,aAAa,EAAE,IAAI,IAAI,KAAK,CAAC;QAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,IAAI,aAAa,EAAE,QAAQ,CAAC;QAE/D,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAErC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YAC9B,WAAW,CAAC,IAAI,KAAK,CAAC,kBAAkB,QAAQ,8BAA8B,CAAC,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAEnF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,kCAAkC;gBAClC,MAAM,QAAQ,GAAG,YAAY,CAC3B,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EACvB,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAChD,CAAC;gBACF,MAAM,IAAI,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YACzD,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CACT,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE;oBAClD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;oBAC7B,YAAY,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;oBACpC,QAAQ,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK;oBAC/B,SAAS,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;iBAClC,CAAC,CACH,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../../src/cli/commands/show.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -25,10 +25,20 @@ async function loadCommands() {
25
25
  const { registerShowCommand } = await import('./commands/show.js');
26
26
  const { registerSearchCommand } = await import('./commands/search.js');
27
27
  const { registerExportCommand } = await import('./commands/export.js');
28
+ const { registerMigrateSessionCommand } = await import('./commands/migrate-session.js');
29
+ const { registerMigrateCommand } = await import('./commands/migrate.js');
30
+ const { registerBackupCommand } = await import('./commands/backup.js');
31
+ const { registerRestoreCommand } = await import('./commands/restore.js');
32
+ const { registerListBackupsCommand } = await import('./commands/list-backups.js');
28
33
  registerListCommand(program);
29
34
  registerShowCommand(program);
30
35
  registerSearchCommand(program);
31
36
  registerExportCommand(program);
37
+ registerMigrateSessionCommand(program);
38
+ registerMigrateCommand(program);
39
+ registerBackupCommand(program);
40
+ registerRestoreCommand(program);
41
+ registerListBackupsCommand(program);
32
42
  }
33
43
  // Main execution
34
44
  async function main() {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEpD,iCAAiC;AACjC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAE1F,CAAC;AAEF,sBAAsB;AACtB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CAAC,yCAAyC,CAAC;KACtD,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,qBAAqB,CAAC;KACpE,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;KACzC,MAAM,CAAC,oBAAoB,EAAE,8BAA8B,CAAC;KAC5D,MAAM,CAAC,wBAAwB,EAAE,0BAA0B,CAAC,CAAC;AAEhE,oDAAoD;AACpD,KAAK,UAAU,YAAY;IACzB,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACnE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACnE,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACvE,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAEvE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,iBAAiB;AACjB,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,YAAY,EAAE,CAAC;QAErB,6BAA6B;QAC7B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;QAED,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,WAAW,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Core backup and restore functionality
3
+ *
4
+ * This module provides low-level backup operations:
5
+ * - SQLite database backup using pluggable driver system
6
+ * - Zip creation/extraction using adm-zip
7
+ * - Manifest generation with checksums
8
+ * - Integrity validation
9
+ */
10
+ import type { Database as DatabaseInterface } from './database/types.js';
11
+ import type { BackupManifest, BackupFileEntry, BackupStats, BackupConfig, BackupResult, RestoreConfig, RestoreResult, BackupValidation, BackupInfo } from './types.js';
12
+ /**
13
+ * T005: Get the default backup directory path
14
+ * Returns ~/cursor-history-backups/
15
+ */
16
+ export declare function getDefaultBackupDir(): string;
17
+ /**
18
+ * T006: Compute SHA-256 checksum of a buffer
19
+ */
20
+ export declare function computeChecksum(buffer: Buffer): string;
21
+ /**
22
+ * T007: Generate a timestamped backup filename
23
+ * Format: cursor_history_backup_YYYY-MM-DD_HHMMSS.zip
24
+ */
25
+ export declare function generateBackupFilename(): string;
26
+ /**
27
+ * Information about a discovered database file
28
+ */
29
+ export interface DatabaseFileInfo {
30
+ /** Absolute path to the database file */
31
+ absolutePath: string;
32
+ /** Path relative to the Cursor data directory (for zip storage) */
33
+ relativePath: string;
34
+ /** File size in bytes */
35
+ size: number;
36
+ /** File type */
37
+ type: 'global-db' | 'workspace-db' | 'workspace-json';
38
+ /** Workspace ID (for workspace DBs) */
39
+ workspaceId?: string;
40
+ }
41
+ /**
42
+ * T008: Scan for all database files in the Cursor data directory
43
+ * Discovers globalStorage/state.vscdb and workspaceStorage/{id}/state.vscdb
44
+ */
45
+ export declare function scanDatabaseFiles(dataPath: string): DatabaseFileInfo[];
46
+ /**
47
+ * T009: Create a manifest object from file entries and stats
48
+ */
49
+ export declare function createManifest(files: BackupFileEntry[], stats: BackupStats): BackupManifest;
50
+ /**
51
+ * T013: Check if there's enough disk space for the backup
52
+ * Returns { available, required, sufficient }
53
+ */
54
+ export declare function checkDiskSpace(outputPath: string, requiredBytes: number): {
55
+ available: number;
56
+ required: number;
57
+ sufficient: boolean;
58
+ };
59
+ /**
60
+ * T012-T016: Create a full backup of all Cursor chat history
61
+ */
62
+ export declare function createBackup(config?: BackupConfig): Promise<BackupResult>;
63
+ /**
64
+ * T025: Open a database from a backup zip file
65
+ * Uses the pluggable driver system to open the database.
66
+ * Extracts to a temp file since SQLite needs file access.
67
+ * Returns a Database interface compatible with the pluggable driver system.
68
+ */
69
+ export declare function openBackupDatabase(backupPath: string, dbPath: string): DatabaseInterface;
70
+ /**
71
+ * Read manifest from a backup file
72
+ */
73
+ export declare function readBackupManifest(backupPath: string): BackupManifest | null;
74
+ /**
75
+ * T026: Validate backup integrity
76
+ */
77
+ export declare function validateBackup(backupPath: string): BackupValidation;
78
+ /**
79
+ * T040-T045: Restore backup to Cursor data directory
80
+ */
81
+ export declare function restoreBackup(config: RestoreConfig): RestoreResult;
82
+ /**
83
+ * T055-T057: List all backup files in a directory
84
+ */
85
+ export declare function listBackups(directory?: string): BackupInfo[];
86
+ //# sourceMappingURL=backup.d.ts.map