@asifkibria/claude-code-toolkit 1.0.2 → 1.2.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.
Files changed (69) hide show
  1. package/README.md +165 -214
  2. package/dist/CLAUDE.md +7 -0
  3. package/dist/__tests__/dashboard.test.d.ts +2 -0
  4. package/dist/__tests__/dashboard.test.d.ts.map +1 -0
  5. package/dist/__tests__/dashboard.test.js +606 -0
  6. package/dist/__tests__/dashboard.test.js.map +1 -0
  7. package/dist/__tests__/mcp-validator.test.d.ts +2 -0
  8. package/dist/__tests__/mcp-validator.test.d.ts.map +1 -0
  9. package/dist/__tests__/mcp-validator.test.js +217 -0
  10. package/dist/__tests__/mcp-validator.test.js.map +1 -0
  11. package/dist/__tests__/scanner.test.js +350 -1
  12. package/dist/__tests__/scanner.test.js.map +1 -1
  13. package/dist/__tests__/security.test.d.ts +2 -0
  14. package/dist/__tests__/security.test.d.ts.map +1 -0
  15. package/dist/__tests__/security.test.js +375 -0
  16. package/dist/__tests__/security.test.js.map +1 -0
  17. package/dist/__tests__/session-recovery.test.d.ts +2 -0
  18. package/dist/__tests__/session-recovery.test.d.ts.map +1 -0
  19. package/dist/__tests__/session-recovery.test.js +230 -0
  20. package/dist/__tests__/session-recovery.test.js.map +1 -0
  21. package/dist/__tests__/storage.test.d.ts +2 -0
  22. package/dist/__tests__/storage.test.d.ts.map +1 -0
  23. package/dist/__tests__/storage.test.js +241 -0
  24. package/dist/__tests__/storage.test.js.map +1 -0
  25. package/dist/__tests__/trace.test.d.ts +2 -0
  26. package/dist/__tests__/trace.test.d.ts.map +1 -0
  27. package/dist/__tests__/trace.test.js +376 -0
  28. package/dist/__tests__/trace.test.js.map +1 -0
  29. package/dist/cli.js +501 -20
  30. package/dist/cli.js.map +1 -1
  31. package/dist/index.js +950 -3
  32. package/dist/index.js.map +1 -1
  33. package/dist/lib/dashboard-ui.d.ts +2 -0
  34. package/dist/lib/dashboard-ui.d.ts.map +1 -0
  35. package/dist/lib/dashboard-ui.js +2075 -0
  36. package/dist/lib/dashboard-ui.js.map +1 -0
  37. package/dist/lib/dashboard.d.ts +15 -0
  38. package/dist/lib/dashboard.d.ts.map +1 -0
  39. package/dist/lib/dashboard.js +1422 -0
  40. package/dist/lib/dashboard.js.map +1 -0
  41. package/dist/lib/logs.d.ts +42 -0
  42. package/dist/lib/logs.d.ts.map +1 -0
  43. package/dist/lib/logs.js +166 -0
  44. package/dist/lib/logs.js.map +1 -0
  45. package/dist/lib/mcp-validator.d.ts +86 -0
  46. package/dist/lib/mcp-validator.d.ts.map +1 -0
  47. package/dist/lib/mcp-validator.js +463 -0
  48. package/dist/lib/mcp-validator.js.map +1 -0
  49. package/dist/lib/scanner.d.ts +187 -2
  50. package/dist/lib/scanner.d.ts.map +1 -1
  51. package/dist/lib/scanner.js +1224 -14
  52. package/dist/lib/scanner.js.map +1 -1
  53. package/dist/lib/security.d.ts +57 -0
  54. package/dist/lib/security.d.ts.map +1 -0
  55. package/dist/lib/security.js +423 -0
  56. package/dist/lib/security.js.map +1 -0
  57. package/dist/lib/session-recovery.d.ts +60 -0
  58. package/dist/lib/session-recovery.d.ts.map +1 -0
  59. package/dist/lib/session-recovery.js +433 -0
  60. package/dist/lib/session-recovery.js.map +1 -0
  61. package/dist/lib/storage.d.ts +68 -0
  62. package/dist/lib/storage.d.ts.map +1 -0
  63. package/dist/lib/storage.js +500 -0
  64. package/dist/lib/storage.js.map +1 -0
  65. package/dist/lib/trace.d.ts +119 -0
  66. package/dist/lib/trace.d.ts.map +1 -0
  67. package/dist/lib/trace.js +649 -0
  68. package/dist/lib/trace.js.map +1 -0
  69. package/package.json +11 -3
package/dist/cli.js CHANGED
@@ -6,7 +6,13 @@
6
6
  import * as fs from "fs";
7
7
  import * as path from "path";
8
8
  import * as os from "os";
9
- import { findAllJsonlFiles, findBackupFiles, scanFile, fixFile, getConversationStats, restoreFromBackup, deleteOldBackups, } from "./lib/scanner.js";
9
+ import { findAllJsonlFiles, findBackupFiles, scanFile, fixFile, getConversationStats, restoreFromBackup, deleteOldBackups, exportConversationToFile, estimateContextSize, formatContextEstimate, generateUsageAnalytics, formatUsageAnalytics, findDuplicates, formatDuplicateReport, findArchiveCandidates, archiveConversations, formatArchiveReport, runMaintenance, formatMaintenanceReport, generateCronSchedule, generateLaunchdPlist, } from "./lib/scanner.js";
10
+ import { analyzeClaudeStorage, cleanClaudeDirectory, findCleanupTargets, formatStorageReport, formatCleanupReport, } from "./lib/storage.js";
11
+ import { diagnoseMcpServers, formatMcpDiagnosticReport, } from "./lib/mcp-validator.js";
12
+ import { listSessions, diagnoseSession, repairSession, extractSessionContent, formatSessionReport, formatSessionDiagnosticReport, } from "./lib/session-recovery.js";
13
+ import { scanForSecrets, auditSession, enforceRetention, formatSecretsScanReport, formatAuditReport, formatRetentionReport, } from "./lib/security.js";
14
+ import { inventoryTraces, cleanTraces, wipeAllTraces, generateTraceGuardHooks, formatTraceInventory, formatTraceCleanReport, formatTraceGuardConfig, } from "./lib/trace.js";
15
+ import { startDashboard, stopDashboard, isDashboardRunning } from "./lib/dashboard.js";
10
16
  function formatContentType(type) {
11
17
  switch (type) {
12
18
  case "image": return "🖼️ image";
@@ -30,41 +36,83 @@ function formatDate(date) {
30
36
  }
31
37
  function printHelp() {
32
38
  console.log(`
33
- Claude Code Toolkit v1.0.2
34
- Maintain, optimize, and troubleshoot your Claude Code installation.
35
- Fixes oversized images, PDFs, documents, and large text content.
39
+ Claude Code Toolkit v1.2.0
40
+ Maintain, optimize, secure, and troubleshoot your Claude Code installation.
36
41
 
37
42
  USAGE:
38
43
  cct <command> [options]
39
44
  claude-code-toolkit <command> [options]
40
45
 
41
46
  COMMANDS:
42
- health Quick health check (start here!)
43
- stats Show conversation statistics
44
- scan Scan for issues (dry run)
45
- fix Fix all detected issues
46
- backups List backup files
47
- restore <path> Restore from a backup file
48
- cleanup Delete old backup files
47
+ health Quick health check (start here!)
48
+ stats Show conversation statistics
49
+ context Estimate context/token usage
50
+ analytics Usage analytics dashboard
51
+ duplicates Find duplicate content and conversations
52
+ archive Archive old/inactive conversations
53
+ maintenance Run maintenance checks and actions
54
+ scan Scan for issues (dry run)
55
+ fix Fix all detected issues
56
+ export Export conversation to markdown or JSON
57
+ backups List backup files
58
+ restore <path> Restore from a backup file
59
+ cleanup Delete old backup files
60
+ clean Analyze and clean .claude directory
61
+ mcp-validate Validate MCP server configurations
62
+ sessions List all sessions with health status
63
+ recover <id> Diagnose/repair/extract from a session
64
+ security-scan Scan conversations for leaked secrets
65
+ audit <id> Audit a session's actions (files, commands, etc.)
66
+ retention Enforce data retention policy
67
+ dashboard Open web dashboard in browser
68
+ dashboard --daemon Run dashboard as background process
69
+ dashboard --stop Stop background dashboard
70
+ trace Show full trace inventory
71
+ trace clean Selective trace cleanup
72
+ trace wipe Secure wipe all traces (requires --confirm)
73
+ trace guard Generate trace prevention hooks
49
74
 
50
75
  OPTIONS:
51
76
  -f, --file <path> Target a specific file
77
+ -o, --output <path> Output file path (for export)
78
+ --format <type> Export format: markdown or json (default: markdown)
79
+ --with-tools Include tool results in export
52
80
  -d, --dry-run Show what would be done without making changes
53
81
  --no-backup Skip creating backups when fixing (not recommended)
54
- --days <n> For cleanup: delete backups older than n days (default: 7)
82
+ --days <n> For cleanup/archive/retention: days threshold (default: 7/30)
55
83
  --limit <n> For stats: limit results (default: 10)
56
84
  --sort <field> For stats: sort by size|messages|images|modified
85
+ --auto For maintenance: run automatically without prompts
86
+ --schedule For maintenance: show cron/launchd setup
87
+ --category <type> For clean: target specific category
88
+ --test For mcp-validate: test server connectivity
89
+ --extract For recover: extract salvageable content
90
+ --repair For recover: attempt repair
91
+ --confirm For trace wipe: confirm destructive operation
92
+ --keep-settings For trace wipe: preserve settings.json
93
+ --mode <mode> For trace guard: paranoid|moderate|minimal
94
+ --install For trace guard: auto-install hooks
95
+ --categories <list> For trace clean: comma-separated categories
96
+ --port <n> For dashboard: port number (default: 1405)
97
+ --daemon For dashboard: run as background process
98
+ --stop For dashboard: stop background process
99
+ --project <path> Filter by project path
57
100
  -h, --help Show this help message
58
101
  -v, --version Show version
59
102
 
60
103
  EXAMPLES:
61
104
  cct health # Quick health check
62
- cct stats --limit 5 --sort size # Top 5 largest conversations
63
- cct scan # Scan for issues
64
- cct fix # Fix all issues
65
- cct fix -f /path/to/file # Fix specific file
66
- cct cleanup --days 30 --dry-run # Preview old backups to delete
67
- cct cleanup --days 30 # Delete old backups
105
+ cct clean --dry-run # Preview .claude directory cleanup
106
+ cct mcp-validate --test # Validate and test MCP servers
107
+ cct sessions # List all sessions
108
+ cct recover abc-123 --repair # Repair a corrupted session
109
+ cct security-scan # Scan for leaked secrets
110
+ cct audit abc-123 # Audit session actions
111
+ cct retention --days 60 --dry-run # Preview retention policy
112
+ cct trace # Show trace inventory
113
+ cct trace clean --days 7 # Clean old traces
114
+ cct trace wipe --confirm # Secure wipe all traces
115
+ cct trace guard --mode moderate # Generate trace prevention hooks
68
116
 
69
117
  For more info: https://github.com/asifkibria/claude-code-toolkit
70
118
  `);
@@ -72,12 +120,31 @@ For more info: https://github.com/asifkibria/claude-code-toolkit
72
120
  function parseArgs(args) {
73
121
  const result = {
74
122
  command: "",
123
+ subcommand: undefined,
75
124
  file: undefined,
125
+ output: undefined,
126
+ format: "markdown",
127
+ withTools: false,
76
128
  dryRun: false,
77
129
  noBackup: false,
78
130
  days: 7,
79
131
  limit: 10,
80
132
  sort: "size",
133
+ auto: false,
134
+ schedule: false,
135
+ category: undefined,
136
+ test: false,
137
+ extract: false,
138
+ repair: false,
139
+ confirm: false,
140
+ keepSettings: false,
141
+ mode: "moderate",
142
+ install: false,
143
+ categories: undefined,
144
+ project: undefined,
145
+ port: 1405,
146
+ daemon: false,
147
+ stop: false,
81
148
  };
82
149
  for (let i = 0; i < args.length; i++) {
83
150
  const arg = args[i];
@@ -86,13 +153,28 @@ function parseArgs(args) {
86
153
  process.exit(0);
87
154
  }
88
155
  if (arg === "-v" || arg === "--version") {
89
- console.log("1.0.2");
156
+ console.log("1.2.0");
90
157
  process.exit(0);
91
158
  }
92
159
  if (arg === "-f" || arg === "--file") {
93
160
  result.file = args[++i];
94
161
  continue;
95
162
  }
163
+ if (arg === "-o" || arg === "--output") {
164
+ result.output = args[++i];
165
+ continue;
166
+ }
167
+ if (arg === "--format") {
168
+ const fmt = args[++i];
169
+ if (fmt === "json" || fmt === "markdown") {
170
+ result.format = fmt;
171
+ }
172
+ continue;
173
+ }
174
+ if (arg === "--with-tools") {
175
+ result.withTools = true;
176
+ continue;
177
+ }
96
178
  if (arg === "-d" || arg === "--dry-run") {
97
179
  result.dryRun = true;
98
180
  continue;
@@ -113,12 +195,77 @@ function parseArgs(args) {
113
195
  result.sort = args[++i];
114
196
  continue;
115
197
  }
198
+ if (arg === "--auto") {
199
+ result.auto = true;
200
+ continue;
201
+ }
202
+ if (arg === "--schedule") {
203
+ result.schedule = true;
204
+ continue;
205
+ }
206
+ if (arg === "--category") {
207
+ result.category = args[++i];
208
+ continue;
209
+ }
210
+ if (arg === "--test") {
211
+ result.test = true;
212
+ continue;
213
+ }
214
+ if (arg === "--extract") {
215
+ result.extract = true;
216
+ continue;
217
+ }
218
+ if (arg === "--repair") {
219
+ result.repair = true;
220
+ continue;
221
+ }
222
+ if (arg === "--confirm") {
223
+ result.confirm = true;
224
+ continue;
225
+ }
226
+ if (arg === "--keep-settings") {
227
+ result.keepSettings = true;
228
+ continue;
229
+ }
230
+ if (arg === "--mode") {
231
+ result.mode = args[++i];
232
+ continue;
233
+ }
234
+ if (arg === "--install") {
235
+ result.install = true;
236
+ continue;
237
+ }
238
+ if (arg === "--categories") {
239
+ result.categories = args[++i];
240
+ continue;
241
+ }
242
+ if (arg === "--port") {
243
+ result.port = parseInt(args[++i], 10);
244
+ continue;
245
+ }
246
+ if (arg === "--daemon") {
247
+ result.daemon = true;
248
+ continue;
249
+ }
250
+ if (arg === "--stop") {
251
+ result.stop = true;
252
+ continue;
253
+ }
254
+ if (arg === "--project") {
255
+ result.project = args[++i];
256
+ continue;
257
+ }
116
258
  if (!arg.startsWith("-") && !result.command) {
117
259
  result.command = arg;
118
260
  continue;
119
261
  }
120
- if (!arg.startsWith("-") && result.command === "restore") {
262
+ if (!arg.startsWith("-") && (result.command === "restore" || result.command === "recover" || result.command === "audit")) {
121
263
  result.file = arg;
264
+ continue;
265
+ }
266
+ if (!arg.startsWith("-") && result.command === "trace" && !result.subcommand) {
267
+ result.subcommand = arg;
268
+ continue;
122
269
  }
123
270
  }
124
271
  return result;
@@ -322,6 +469,269 @@ async function cmdCleanup(days, dryRun) {
322
469
  }
323
470
  }
324
471
  }
472
+ async function cmdExport(file, output, format, withTools) {
473
+ if (!file) {
474
+ console.error("Please specify a conversation file with -f or --file");
475
+ console.error("Example: cct export -f ~/.claude/projects/myproject/conversation.jsonl");
476
+ process.exit(1);
477
+ }
478
+ if (!fs.existsSync(file)) {
479
+ console.error(`File not found: ${file}`);
480
+ process.exit(1);
481
+ }
482
+ const ext = format === "json" ? ".json" : ".md";
483
+ const outputPath = output || file.replace(".jsonl", `-export${ext}`);
484
+ console.log(`Exporting conversation...`);
485
+ console.log(` Source: ${file}`);
486
+ console.log(` Format: ${format}`);
487
+ console.log(` Output: ${outputPath}`);
488
+ console.log();
489
+ const result = exportConversationToFile(file, outputPath, {
490
+ format,
491
+ includeToolResults: withTools,
492
+ includeTimestamps: true,
493
+ });
494
+ if (!result.success) {
495
+ console.error(`\x1b[31mError: ${result.error}\x1b[0m`);
496
+ process.exit(1);
497
+ }
498
+ console.log(`\x1b[32m✓ Exported ${result.messageCount} messages to ${outputPath}\x1b[0m`);
499
+ }
500
+ async function cmdContext(file) {
501
+ if (!file) {
502
+ // If no file specified, show summary for all conversations
503
+ if (!fs.existsSync(PROJECTS_DIR)) {
504
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
505
+ process.exit(1);
506
+ }
507
+ const files = findAllJsonlFiles(PROJECTS_DIR);
508
+ const estimates = files.map((f) => {
509
+ try {
510
+ return estimateContextSize(f);
511
+ }
512
+ catch {
513
+ return null;
514
+ }
515
+ }).filter(Boolean);
516
+ estimates.sort((a, b) => b.totalTokens - a.totalTokens);
517
+ const totalTokens = estimates.reduce((sum, e) => sum + e.totalTokens, 0);
518
+ console.log("Context Usage Summary\n");
519
+ console.log(`Total conversations: ${estimates.length}`);
520
+ console.log(`Combined tokens: ~${totalTokens.toLocaleString()}\n`);
521
+ console.log("Top 10 by context size:\n");
522
+ for (const estimate of estimates.slice(0, 10)) {
523
+ const relPath = path.relative(PROJECTS_DIR, estimate.file);
524
+ const shortPath = relPath.length > 50 ? "..." + relPath.slice(-47) : relPath;
525
+ console.log(`\x1b[36m${shortPath}\x1b[0m`);
526
+ console.log(` ~${estimate.totalTokens.toLocaleString()} tokens (${estimate.messageCount} messages)`);
527
+ if (estimate.warnings.length > 0) {
528
+ console.log(` \x1b[33m⚠ ${estimate.warnings[0]}\x1b[0m`);
529
+ }
530
+ console.log();
531
+ }
532
+ return;
533
+ }
534
+ if (!fs.existsSync(file)) {
535
+ console.error(`File not found: ${file}`);
536
+ process.exit(1);
537
+ }
538
+ const estimate = estimateContextSize(file);
539
+ console.log(formatContextEstimate(estimate));
540
+ }
541
+ async function cmdAnalytics() {
542
+ if (!fs.existsSync(PROJECTS_DIR)) {
543
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
544
+ process.exit(1);
545
+ }
546
+ console.log("Generating analytics...\n");
547
+ const analytics = generateUsageAnalytics(PROJECTS_DIR, 30);
548
+ console.log(formatUsageAnalytics(analytics));
549
+ }
550
+ async function cmdDuplicates() {
551
+ if (!fs.existsSync(PROJECTS_DIR)) {
552
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
553
+ process.exit(1);
554
+ }
555
+ console.log("Scanning for duplicates...\n");
556
+ const report = findDuplicates(PROJECTS_DIR);
557
+ console.log(formatDuplicateReport(report));
558
+ }
559
+ async function cmdArchive(days, dryRun) {
560
+ if (!fs.existsSync(PROJECTS_DIR)) {
561
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
562
+ process.exit(1);
563
+ }
564
+ const archiveDays = days > 7 ? days : 30;
565
+ console.log(`Finding conversations inactive for ${archiveDays}+ days...\n`);
566
+ const candidates = findArchiveCandidates(PROJECTS_DIR, { minDaysInactive: archiveDays });
567
+ if (candidates.length === 0) {
568
+ console.log("✓ No conversations eligible for archiving.\n");
569
+ return;
570
+ }
571
+ const result = archiveConversations(PROJECTS_DIR, { minDaysInactive: archiveDays, dryRun });
572
+ console.log(formatArchiveReport(candidates, result, dryRun));
573
+ if (dryRun && candidates.length > 0) {
574
+ console.log("\x1b[33mRun without --dry-run to archive these conversations.\x1b[0m\n");
575
+ }
576
+ }
577
+ async function cmdMaintenance(dryRun, auto, schedule) {
578
+ if (schedule) {
579
+ console.log("Scheduled Maintenance Setup\n");
580
+ console.log("=== For macOS (launchd) ===");
581
+ console.log("Save this to ~/Library/LaunchAgents/com.claude-code-toolkit.maintenance.plist:\n");
582
+ console.log(generateLaunchdPlist());
583
+ console.log("\nThen run: launchctl load ~/Library/LaunchAgents/com.claude-code-toolkit.maintenance.plist\n");
584
+ console.log("=== For Linux/Unix (cron) ===\n");
585
+ console.log(generateCronSchedule());
586
+ return;
587
+ }
588
+ if (!fs.existsSync(PROJECTS_DIR)) {
589
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
590
+ process.exit(1);
591
+ }
592
+ console.log("Running maintenance checks...\n");
593
+ const report = runMaintenance(PROJECTS_DIR, { dryRun: !auto });
594
+ console.log(formatMaintenanceReport(report, !auto));
595
+ if (!auto && report.actions.length > 0) {
596
+ console.log("\x1b[33mRun with --auto to perform maintenance actions automatically.\x1b[0m\n");
597
+ }
598
+ }
599
+ async function cmdClean(dryRun, days, category) {
600
+ const analysis = analyzeClaudeStorage();
601
+ console.log(formatStorageReport(analysis));
602
+ const options = { dryRun: dryRun || true, days, categories: category ? [category] : undefined };
603
+ const targets = findCleanupTargets(undefined, options);
604
+ if (targets.length === 0) {
605
+ console.log("\x1b[32m✓ Nothing to clean.\x1b[0m\n");
606
+ return;
607
+ }
608
+ const result = cleanClaudeDirectory(undefined, { ...options, dryRun });
609
+ console.log(formatCleanupReport(targets, result, dryRun));
610
+ }
611
+ async function cmdMcpValidate(file, test) {
612
+ const report = await diagnoseMcpServers({ test, projectDir: process.cwd() });
613
+ console.log(formatMcpDiagnosticReport(report));
614
+ }
615
+ async function cmdSessions(project) {
616
+ const sessions = listSessions(undefined, { project });
617
+ if (sessions.length === 0) {
618
+ console.log("No sessions found.\n");
619
+ return;
620
+ }
621
+ console.log(formatSessionReport(sessions));
622
+ }
623
+ async function cmdRecover(sessionId, extract, repair) {
624
+ if (!sessionId) {
625
+ console.error("Usage: cct recover <session-id> [--extract] [--repair]");
626
+ process.exit(1);
627
+ }
628
+ const sessions = listSessions();
629
+ const session = sessions.find(s => s.id === sessionId || s.id.startsWith(sessionId));
630
+ if (!session) {
631
+ console.error(`Session not found: ${sessionId}`);
632
+ process.exit(1);
633
+ }
634
+ const diag = diagnoseSession(session.filePath);
635
+ console.log(formatSessionDiagnosticReport(diag));
636
+ if (repair) {
637
+ console.log("\nRepairing session...");
638
+ const result = repairSession(session.filePath);
639
+ if (result.success) {
640
+ console.log(`\x1b[32m✓ Repaired. Removed ${result.linesRemoved} invalid lines.\x1b[0m`);
641
+ if (result.backupPath)
642
+ console.log(` Backup: ${result.backupPath}`);
643
+ }
644
+ else {
645
+ console.log(`\x1b[31m✗ Repair failed: ${result.error}\x1b[0m`);
646
+ }
647
+ }
648
+ if (extract) {
649
+ console.log("\nExtracting session content...");
650
+ const content = extractSessionContent(session.filePath);
651
+ console.log(` User messages: ${content.userMessages.length}`);
652
+ console.log(` Assistant messages: ${content.assistantMessages.length}`);
653
+ console.log(` File edits: ${content.fileEdits.length}`);
654
+ console.log(` Commands run: ${content.commandsRun.length}`);
655
+ if (content.fileEdits.length > 0) {
656
+ console.log("\nFile edits:");
657
+ for (const edit of content.fileEdits.slice(0, 10)) {
658
+ console.log(` ${edit.path}`);
659
+ }
660
+ }
661
+ if (content.commandsRun.length > 0) {
662
+ console.log("\nCommands:");
663
+ for (const cmd of content.commandsRun.slice(0, 10)) {
664
+ const short = cmd.length > 80 ? cmd.slice(0, 77) + "..." : cmd;
665
+ console.log(` $ ${short}`);
666
+ }
667
+ }
668
+ }
669
+ }
670
+ async function cmdSecurityScan(file) {
671
+ console.log("Scanning for secrets in conversation data...\n");
672
+ const result = scanForSecrets(undefined, { file });
673
+ console.log(formatSecretsScanReport(result));
674
+ }
675
+ async function cmdAudit(sessionId) {
676
+ if (!sessionId) {
677
+ console.error("Usage: cct audit <session-id>");
678
+ process.exit(1);
679
+ }
680
+ const sessions = listSessions();
681
+ const session = sessions.find(s => s.id === sessionId || s.id.startsWith(sessionId));
682
+ if (!session) {
683
+ console.error(`Session not found: ${sessionId}`);
684
+ process.exit(1);
685
+ }
686
+ const audit = auditSession(session.filePath);
687
+ console.log(formatAuditReport(audit));
688
+ }
689
+ async function cmdRetention(days, dryRun) {
690
+ const retentionDays = days > 7 ? days : 30;
691
+ const result = enforceRetention(undefined, { days: retentionDays, dryRun });
692
+ console.log(formatRetentionReport(result));
693
+ }
694
+ async function cmdTrace(subcommand, options) {
695
+ if (!subcommand) {
696
+ const inv = inventoryTraces(undefined, { project: options?.project });
697
+ console.log(formatTraceInventory(inv));
698
+ return;
699
+ }
700
+ if (subcommand === "clean") {
701
+ const cleanOpts = {
702
+ dryRun: options?.dryRun ?? true,
703
+ days: options?.days,
704
+ categories: options?.categories?.split(","),
705
+ project: options?.project,
706
+ };
707
+ const result = cleanTraces(undefined, cleanOpts);
708
+ console.log(formatTraceCleanReport(result));
709
+ return;
710
+ }
711
+ if (subcommand === "wipe") {
712
+ if (!options?.confirm) {
713
+ console.log("\x1b[31m⚠ This will securely wipe ALL Claude Code traces.\x1b[0m");
714
+ console.log("Run with --confirm to execute.\n");
715
+ const inv = inventoryTraces();
716
+ console.log(`Would wipe: ${inv.totalFiles} files (${formatBytes(inv.totalSize)})`);
717
+ return;
718
+ }
719
+ const result = wipeAllTraces(undefined, {
720
+ confirm: true,
721
+ keepSettings: options.keepSettings,
722
+ });
723
+ console.log(result.wipeReceipt);
724
+ return;
725
+ }
726
+ if (subcommand === "guard") {
727
+ const mode = (options?.mode || "moderate");
728
+ const config = generateTraceGuardHooks({ mode });
729
+ console.log(formatTraceGuardConfig(config));
730
+ return;
731
+ }
732
+ console.error(`Unknown trace subcommand: ${subcommand}`);
733
+ console.error("Usage: cct trace [clean|wipe|guard]");
734
+ }
325
735
  async function cmdHealth() {
326
736
  if (!fs.existsSync(PROJECTS_DIR)) {
327
737
  console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
@@ -376,6 +786,24 @@ async function main() {
376
786
  case "stats":
377
787
  await cmdStats(args.limit, args.sort);
378
788
  break;
789
+ case "context":
790
+ await cmdContext(args.file);
791
+ break;
792
+ case "analytics":
793
+ await cmdAnalytics();
794
+ break;
795
+ case "duplicates":
796
+ await cmdDuplicates();
797
+ break;
798
+ case "archive":
799
+ await cmdArchive(args.days, args.dryRun);
800
+ break;
801
+ case "maintenance":
802
+ await cmdMaintenance(args.dryRun, args.auto, args.schedule);
803
+ break;
804
+ case "export":
805
+ await cmdExport(args.file, args.output, args.format, args.withTools);
806
+ break;
379
807
  case "backups":
380
808
  await cmdBackups();
381
809
  break;
@@ -388,6 +816,59 @@ async function main() {
388
816
  case "health":
389
817
  await cmdHealth();
390
818
  break;
819
+ case "clean":
820
+ await cmdClean(args.dryRun, args.days, args.category);
821
+ break;
822
+ case "mcp-validate":
823
+ await cmdMcpValidate(args.file, args.test);
824
+ break;
825
+ case "sessions":
826
+ await cmdSessions(args.project);
827
+ break;
828
+ case "recover":
829
+ await cmdRecover(args.file, args.extract, args.repair);
830
+ break;
831
+ case "security-scan":
832
+ await cmdSecurityScan(args.file);
833
+ break;
834
+ case "audit":
835
+ await cmdAudit(args.file);
836
+ break;
837
+ case "retention":
838
+ await cmdRetention(args.days, args.dryRun);
839
+ break;
840
+ case "trace":
841
+ await cmdTrace(args.subcommand, {
842
+ dryRun: args.dryRun,
843
+ days: args.days,
844
+ categories: args.categories,
845
+ project: args.project,
846
+ confirm: args.confirm,
847
+ keepSettings: args.keepSettings,
848
+ mode: args.mode,
849
+ install: args.install,
850
+ });
851
+ break;
852
+ case "dashboard":
853
+ if (args.stop) {
854
+ const stopped = stopDashboard();
855
+ if (stopped) {
856
+ console.log("\x1b[32m✓ Dashboard stopped.\x1b[0m");
857
+ }
858
+ else {
859
+ const status = isDashboardRunning();
860
+ if (!status.running) {
861
+ console.log("No dashboard process found.");
862
+ }
863
+ else {
864
+ console.error("Failed to stop dashboard.");
865
+ }
866
+ }
867
+ }
868
+ else {
869
+ await startDashboard({ port: args.port, daemon: args.daemon });
870
+ }
871
+ break;
391
872
  default:
392
873
  console.error(`Unknown command: ${args.command}`);
393
874
  printHelp();