@asifkibria/claude-code-toolkit 1.2.0 → 1.3.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/dist/cli.js CHANGED
@@ -8,11 +8,14 @@ import * as path from "path";
8
8
  import * as os from "os";
9
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
10
  import { analyzeClaudeStorage, cleanClaudeDirectory, findCleanupTargets, formatStorageReport, formatCleanupReport, } from "./lib/storage.js";
11
- import { diagnoseMcpServers, formatMcpDiagnosticReport, } from "./lib/mcp-validator.js";
11
+ import { diagnoseMcpServers, formatMcpDiagnosticReport, analyzeMcpPerformance, formatMcpPerformanceReport, } from "./lib/mcp-validator.js";
12
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";
13
+ import { scanForSecrets, scanForPII, auditSession, enforceRetention, formatSecretsScanReport, formatPIIScanReport, formatAuditReport, formatRetentionReport, } from "./lib/security.js";
14
14
  import { inventoryTraces, cleanTraces, wipeAllTraces, generateTraceGuardHooks, formatTraceInventory, formatTraceCleanReport, formatTraceGuardConfig, } from "./lib/trace.js";
15
15
  import { startDashboard, stopDashboard, isDashboardRunning } from "./lib/dashboard.js";
16
+ import { searchConversations, formatSearchReport, compareSessionsByCID, formatSessionDiff } from "./lib/search.js";
17
+ import { linkSessionsToGit, formatGitLinkReport } from "./lib/git.js";
18
+ import { checkAlerts, checkQuotas, formatAlertsReport, formatQuotasReport } from "./lib/alerts.js";
16
19
  function formatContentType(type) {
17
20
  switch (type) {
18
21
  case "image": return "🖼️ image";
@@ -36,7 +39,7 @@ function formatDate(date) {
36
39
  }
37
40
  function printHelp() {
38
41
  console.log(`
39
- Claude Code Toolkit v1.2.0
42
+ Claude Code Toolkit v1.3.0
40
43
  Maintain, optimize, secure, and troubleshoot your Claude Code installation.
41
44
 
42
45
  USAGE:
@@ -45,25 +48,35 @@ USAGE:
45
48
 
46
49
  COMMANDS:
47
50
  health Quick health check (start here!)
51
+ search <query> Full-text search across all conversations
48
52
  stats Show conversation statistics
49
53
  context Estimate context/token usage
54
+ cost Estimate API costs based on token usage
50
55
  analytics Usage analytics dashboard
51
56
  duplicates Find duplicate content and conversations
52
57
  archive Archive old/inactive conversations
53
58
  maintenance Run maintenance checks and actions
54
59
  scan Scan for issues (dry run)
55
60
  fix Fix all detected issues
61
+ watch Monitor sessions for new oversized content
56
62
  export Export conversation to markdown or JSON
57
63
  backups List backup files
58
64
  restore <path> Restore from a backup file
59
65
  cleanup Delete old backup files
60
66
  clean Analyze and clean .claude directory
61
67
  mcp-validate Validate MCP server configurations
68
+ mcp-perf Track MCP server performance and usage
62
69
  sessions List all sessions with health status
70
+ diff <id1> <id2> Compare two sessions
71
+ git Link sessions to git branches/commits
63
72
  recover <id> Diagnose/repair/extract from a session
64
73
  security-scan Scan conversations for leaked secrets
74
+ pii-scan Scan conversations for personal data (PII)
75
+ --details: Show unmasked values (handle with care!)
65
76
  audit <id> Audit a session's actions (files, commands, etc.)
66
77
  retention Enforce data retention policy
78
+ alerts Check for issues and notifications
79
+ quotas Show usage quotas and limits
67
80
  dashboard Open web dashboard in browser
68
81
  dashboard --daemon Run dashboard as background process
69
82
  dashboard --stop Stop background dashboard
@@ -75,12 +88,14 @@ COMMANDS:
75
88
  OPTIONS:
76
89
  -f, --file <path> Target a specific file
77
90
  -o, --output <path> Output file path (for export)
91
+ -q, --query <text> Search query text
92
+ --role <type> For search: filter by role (user|assistant|all)
78
93
  --format <type> Export format: markdown or json (default: markdown)
79
94
  --with-tools Include tool results in export
80
95
  -d, --dry-run Show what would be done without making changes
81
96
  --no-backup Skip creating backups when fixing (not recommended)
82
97
  --days <n> For cleanup/archive/retention: days threshold (default: 7/30)
83
- --limit <n> For stats: limit results (default: 10)
98
+ --limit <n> For stats/search: limit results (default: 10/50)
84
99
  --sort <field> For stats: sort by size|messages|images|modified
85
100
  --auto For maintenance: run automatically without prompts
86
101
  --schedule For maintenance: show cron/launchd setup
@@ -96,12 +111,19 @@ OPTIONS:
96
111
  --port <n> For dashboard: port number (default: 1405)
97
112
  --daemon For dashboard: run as background process
98
113
  --stop For dashboard: stop background process
114
+ --token <value> Require dashboard auth with bearer token
99
115
  --project <path> Filter by project path
116
+ --json Output structured JSON (scan/watch)
117
+ --interval <sec> For watch: polling interval in seconds (default: 15)
118
+ --auto-fix For watch: automatically fix detected issues
100
119
  -h, --help Show this help message
101
120
  -v, --version Show version
102
121
 
103
122
  EXAMPLES:
104
123
  cct health # Quick health check
124
+ cct search "authentication" # Search all conversations
125
+ cct search "api" --role user # Search only user messages
126
+ cct cost # Estimate API costs
105
127
  cct clean --dry-run # Preview .claude directory cleanup
106
128
  cct mcp-validate --test # Validate and test MCP servers
107
129
  cct sessions # List all sessions
@@ -123,6 +145,8 @@ function parseArgs(args) {
123
145
  subcommand: undefined,
124
146
  file: undefined,
125
147
  output: undefined,
148
+ query: undefined,
149
+ role: undefined,
126
150
  format: "markdown",
127
151
  withTools: false,
128
152
  dryRun: false,
@@ -145,6 +169,11 @@ function parseArgs(args) {
145
169
  port: 1405,
146
170
  daemon: false,
147
171
  stop: false,
172
+ token: undefined,
173
+ json: false,
174
+ interval: 15,
175
+ autoFix: false,
176
+ details: false,
148
177
  };
149
178
  for (let i = 0; i < args.length; i++) {
150
179
  const arg = args[i];
@@ -153,7 +182,7 @@ function parseArgs(args) {
153
182
  process.exit(0);
154
183
  }
155
184
  if (arg === "-v" || arg === "--version") {
156
- console.log("1.2.0");
185
+ console.log("1.3.0");
157
186
  process.exit(0);
158
187
  }
159
188
  if (arg === "-f" || arg === "--file") {
@@ -164,6 +193,14 @@ function parseArgs(args) {
164
193
  result.output = args[++i];
165
194
  continue;
166
195
  }
196
+ if (arg === "-q" || arg === "--query") {
197
+ result.query = args[++i];
198
+ continue;
199
+ }
200
+ if (arg === "--role") {
201
+ result.role = args[++i];
202
+ continue;
203
+ }
167
204
  if (arg === "--format") {
168
205
  const fmt = args[++i];
169
206
  if (fmt === "json" || fmt === "markdown") {
@@ -255,6 +292,26 @@ function parseArgs(args) {
255
292
  result.project = args[++i];
256
293
  continue;
257
294
  }
295
+ if (arg === "--token") {
296
+ result.token = args[++i];
297
+ continue;
298
+ }
299
+ if (arg === "--json") {
300
+ result.json = true;
301
+ continue;
302
+ }
303
+ if (arg === "--interval") {
304
+ result.interval = parseInt(args[++i], 10);
305
+ continue;
306
+ }
307
+ if (arg === "--auto-fix") {
308
+ result.autoFix = true;
309
+ continue;
310
+ }
311
+ if (arg === "--details") {
312
+ result.details = true;
313
+ continue;
314
+ }
258
315
  if (!arg.startsWith("-") && !result.command) {
259
316
  result.command = arg;
260
317
  continue;
@@ -263,6 +320,19 @@ function parseArgs(args) {
263
320
  result.file = arg;
264
321
  continue;
265
322
  }
323
+ if (!arg.startsWith("-") && result.command === "search" && !result.query) {
324
+ result.query = arg;
325
+ continue;
326
+ }
327
+ if (!arg.startsWith("-") && result.command === "diff") {
328
+ if (!result.file) {
329
+ result.file = arg;
330
+ }
331
+ else if (!result.subcommand) {
332
+ result.subcommand = arg;
333
+ }
334
+ continue;
335
+ }
266
336
  if (!arg.startsWith("-") && result.command === "trace" && !result.subcommand) {
267
337
  result.subcommand = arg;
268
338
  continue;
@@ -270,13 +340,22 @@ function parseArgs(args) {
270
340
  }
271
341
  return result;
272
342
  }
273
- async function cmdScan(file) {
343
+ async function cmdScan(file, asJson) {
274
344
  if (!fs.existsSync(PROJECTS_DIR)) {
275
345
  console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
276
346
  process.exit(1);
277
347
  }
278
348
  const files = file ? [file] : findAllJsonlFiles(PROJECTS_DIR);
279
- console.log(`Scanning ${files.length} file(s)...\n`);
349
+ const summary = {
350
+ success: true,
351
+ filesScanned: files.length,
352
+ filesWithIssues: 0,
353
+ totalIssues: 0,
354
+ files: [],
355
+ };
356
+ if (!asJson) {
357
+ console.log(`Scanning ${files.length} file(s)...\n`);
358
+ }
280
359
  let totalIssues = 0;
281
360
  let filesWithIssues = 0;
282
361
  for (const f of files) {
@@ -286,10 +365,21 @@ async function cmdScan(file) {
286
365
  filesWithIssues++;
287
366
  totalIssues += result.issues.length;
288
367
  const relPath = path.relative(PROJECTS_DIR, f);
289
- console.log(`\x1b[33m${relPath}\x1b[0m`);
290
- for (const issue of result.issues) {
291
- console.log(` Line ${issue.line}: ${formatContentType(issue.contentType)} (~${formatBytes(issue.estimatedSize)})`);
368
+ if (!asJson) {
369
+ console.log(`\x1b[33m${relPath}\x1b[0m`);
370
+ for (const issue of result.issues) {
371
+ console.log(` Line ${issue.line}: ${formatContentType(issue.contentType)} (~${formatBytes(issue.estimatedSize)})`);
372
+ }
292
373
  }
374
+ summary.files.push({
375
+ file: relPath,
376
+ issues: result.issues.map((issue) => ({
377
+ line: issue.line,
378
+ type: issue.contentType,
379
+ location: issue.location,
380
+ size: formatBytes(issue.estimatedSize),
381
+ })),
382
+ });
293
383
  }
294
384
  }
295
385
  catch {
@@ -297,6 +387,11 @@ async function cmdScan(file) {
297
387
  }
298
388
  }
299
389
  console.log();
390
+ summary.totalIssues = totalIssues;
391
+ summary.filesWithIssues = filesWithIssues;
392
+ if (asJson) {
393
+ return summary;
394
+ }
300
395
  if (totalIssues === 0) {
301
396
  console.log("\x1b[32m✓ No oversized content found.\x1b[0m");
302
397
  }
@@ -305,6 +400,100 @@ async function cmdScan(file) {
305
400
  console.log("Run 'cct fix' to fix them.");
306
401
  }
307
402
  }
403
+ async function cmdWatch(asJson, intervalSeconds, autoFix) {
404
+ if (!fs.existsSync(PROJECTS_DIR)) {
405
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
406
+ process.exit(1);
407
+ }
408
+ const effectiveSeconds = Number.isFinite(intervalSeconds) && intervalSeconds > 0 ? intervalSeconds : 15;
409
+ const intervalMs = Math.max(5, effectiveSeconds) * 1000;
410
+ const seen = new Map();
411
+ const logEvent = (event) => {
412
+ if (asJson) {
413
+ console.log(JSON.stringify(event));
414
+ }
415
+ else {
416
+ const actionText = event.action === "fixed" ? "Fixed" : event.action === "error" ? "Error" : "Detected";
417
+ console.log(`[${event.timestamp}] ${actionText}: ${event.file} (${event.issues} issue(s))${event.details ? ` - ${event.details}` : ""}`);
418
+ }
419
+ };
420
+ const checkFiles = async () => {
421
+ const files = findAllJsonlFiles(PROJECTS_DIR);
422
+ const active = new Set();
423
+ for (const file of files) {
424
+ active.add(file);
425
+ let stat;
426
+ try {
427
+ stat = fs.statSync(file);
428
+ }
429
+ catch {
430
+ continue;
431
+ }
432
+ const last = seen.get(file) || 0;
433
+ if (stat.mtimeMs <= last)
434
+ continue;
435
+ seen.set(file, stat.mtimeMs);
436
+ let result;
437
+ try {
438
+ result = scanFile(file);
439
+ }
440
+ catch {
441
+ continue;
442
+ }
443
+ if (result.issues.length === 0)
444
+ continue;
445
+ const relPath = path.relative(PROJECTS_DIR, file);
446
+ const eventBase = {
447
+ timestamp: new Date().toISOString(),
448
+ file: relPath,
449
+ issues: result.issues.length,
450
+ action: "detected",
451
+ };
452
+ if (autoFix) {
453
+ try {
454
+ const fixResult = fixFile(file);
455
+ if (fixResult.fixed) {
456
+ logEvent({ ...eventBase, action: "fixed" });
457
+ }
458
+ else {
459
+ logEvent({ ...eventBase, action: "error", details: "No changes applied" });
460
+ }
461
+ }
462
+ catch (err) {
463
+ logEvent({ ...eventBase, action: "error", details: err instanceof Error ? err.message : String(err) });
464
+ }
465
+ }
466
+ else {
467
+ logEvent(eventBase);
468
+ }
469
+ }
470
+ for (const entry of Array.from(seen.keys())) {
471
+ if (!active.has(entry)) {
472
+ seen.delete(entry);
473
+ }
474
+ }
475
+ };
476
+ await checkFiles();
477
+ if (!asJson) {
478
+ console.log(`Watching ${PROJECTS_DIR} every ${intervalMs / 1000}s. Press Ctrl+C to stop.`);
479
+ if (autoFix) {
480
+ console.log("Auto-fix is enabled. Backups will be created before changes.\n");
481
+ }
482
+ }
483
+ setInterval(() => {
484
+ checkFiles().catch((err) => {
485
+ if (asJson) {
486
+ console.log(JSON.stringify({ timestamp: new Date().toISOString(), action: "error", details: err.message }));
487
+ }
488
+ else {
489
+ console.error("Watch error:", err);
490
+ }
491
+ });
492
+ }, intervalMs);
493
+ return new Promise(() => {
494
+ // Keep process alive until Ctrl+C
495
+ });
496
+ }
308
497
  async function cmdFix(file, noBackup = false) {
309
498
  if (!fs.existsSync(PROJECTS_DIR)) {
310
499
  console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
@@ -574,7 +763,7 @@ async function cmdArchive(days, dryRun) {
574
763
  console.log("\x1b[33mRun without --dry-run to archive these conversations.\x1b[0m\n");
575
764
  }
576
765
  }
577
- async function cmdMaintenance(dryRun, auto, schedule) {
766
+ async function cmdMaintenance(auto, schedule) {
578
767
  if (schedule) {
579
768
  console.log("Scheduled Maintenance Setup\n");
580
769
  console.log("=== For macOS (launchd) ===");
@@ -608,7 +797,7 @@ async function cmdClean(dryRun, days, category) {
608
797
  const result = cleanClaudeDirectory(undefined, { ...options, dryRun });
609
798
  console.log(formatCleanupReport(targets, result, dryRun));
610
799
  }
611
- async function cmdMcpValidate(file, test) {
800
+ async function cmdMcpValidate(test) {
612
801
  const report = await diagnoseMcpServers({ test, projectDir: process.cwd() });
613
802
  console.log(formatMcpDiagnosticReport(report));
614
803
  }
@@ -672,6 +861,14 @@ async function cmdSecurityScan(file) {
672
861
  const result = scanForSecrets(undefined, { file });
673
862
  console.log(formatSecretsScanReport(result));
674
863
  }
864
+ async function cmdPIIScan(file, details) {
865
+ console.log("Scanning for Personal Identifiable Information (PII)...\n");
866
+ if (details) {
867
+ console.log("\x1b[33m⚠ WARNING: Showing unmasked PII values. Handle with care!\x1b[0m\n");
868
+ }
869
+ const result = scanForPII(undefined, { file, includeFullValues: details });
870
+ console.log(formatPIIScanReport(result, details));
871
+ }
675
872
  async function cmdAudit(sessionId) {
676
873
  if (!sessionId) {
677
874
  console.error("Usage: cct audit <session-id>");
@@ -732,6 +929,127 @@ async function cmdTrace(subcommand, options) {
732
929
  console.error(`Unknown trace subcommand: ${subcommand}`);
733
930
  console.error("Usage: cct trace [clean|wipe|guard]");
734
931
  }
932
+ async function cmdSearch(query, options) {
933
+ if (!query || query.length < 2) {
934
+ console.error("Usage: cct search <query> [--role user|assistant|all] [--limit n] [--project name]");
935
+ console.error("Query must be at least 2 characters.");
936
+ process.exit(1);
937
+ }
938
+ if (!fs.existsSync(PROJECTS_DIR)) {
939
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
940
+ process.exit(1);
941
+ }
942
+ console.log(`Searching for "${query}"...\n`);
943
+ const searchOpts = {
944
+ query,
945
+ limit: options?.limit || 50,
946
+ role: options?.role || "all",
947
+ project: options?.project,
948
+ daysBack: options?.days,
949
+ };
950
+ const report = searchConversations(searchOpts);
951
+ console.log(formatSearchReport(report));
952
+ }
953
+ async function cmdCost() {
954
+ if (!fs.existsSync(PROJECTS_DIR)) {
955
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
956
+ process.exit(1);
957
+ }
958
+ console.log("Calculating API cost estimates...\n");
959
+ const files = findAllJsonlFiles(PROJECTS_DIR);
960
+ let totalInputTokens = 0;
961
+ let totalOutputTokens = 0;
962
+ let sessionCount = 0;
963
+ const projectCosts = new Map();
964
+ for (const file of files) {
965
+ try {
966
+ const estimate = estimateContextSize(file);
967
+ const projectName = path.basename(path.dirname(file));
968
+ const b = estimate.breakdown;
969
+ const inputTokens = b.userTokens + b.systemTokens + b.toolUseTokens;
970
+ const outputTokens = b.assistantTokens + b.toolResultTokens;
971
+ if (!projectCosts.has(projectName)) {
972
+ projectCosts.set(projectName, { input: 0, output: 0, sessions: 0 });
973
+ }
974
+ const project = projectCosts.get(projectName);
975
+ project.input += inputTokens;
976
+ project.output += outputTokens;
977
+ project.sessions++;
978
+ totalInputTokens += inputTokens;
979
+ totalOutputTokens += outputTokens;
980
+ sessionCount++;
981
+ }
982
+ catch {
983
+ // Skip
984
+ }
985
+ }
986
+ const inputCostPerMillion = 15;
987
+ const outputCostPerMillion = 75;
988
+ const totalInputCost = (totalInputTokens / 1_000_000) * inputCostPerMillion;
989
+ const totalOutputCost = (totalOutputTokens / 1_000_000) * outputCostPerMillion;
990
+ const totalCost = totalInputCost + totalOutputCost;
991
+ console.log("API Cost Estimate (Claude Sonnet pricing)\n");
992
+ console.log("═".repeat(50));
993
+ console.log(`Sessions analyzed: ${sessionCount}`);
994
+ console.log(`\nToken Usage:`);
995
+ console.log(` Input tokens: ${totalInputTokens.toLocaleString()}`);
996
+ console.log(` Output tokens: ${totalOutputTokens.toLocaleString()}`);
997
+ console.log(` Total tokens: ${(totalInputTokens + totalOutputTokens).toLocaleString()}`);
998
+ console.log(`\nEstimated Cost:`);
999
+ console.log(` Input: $${totalInputCost.toFixed(2)} ($${inputCostPerMillion}/M tokens)`);
1000
+ console.log(` Output: $${totalOutputCost.toFixed(2)} ($${outputCostPerMillion}/M tokens)`);
1001
+ console.log(` \x1b[36mTotal: $${totalCost.toFixed(2)}\x1b[0m\n`);
1002
+ const sortedProjects = Array.from(projectCosts.entries())
1003
+ .sort((a, b) => (b[1].input + b[1].output) - (a[1].input + a[1].output))
1004
+ .slice(0, 10);
1005
+ if (sortedProjects.length > 0) {
1006
+ console.log("Top Projects by Token Usage:\n");
1007
+ for (const [name, data] of sortedProjects) {
1008
+ const projectTotal = data.input + data.output;
1009
+ const projectCost = ((data.input / 1_000_000) * inputCostPerMillion) + ((data.output / 1_000_000) * outputCostPerMillion);
1010
+ console.log(` ${name}`);
1011
+ console.log(` ${projectTotal.toLocaleString()} tokens (~$${projectCost.toFixed(2)}) - ${data.sessions} session(s)`);
1012
+ }
1013
+ }
1014
+ console.log("\n\x1b[33mNote: These are estimates based on stored conversation history.\x1b[0m");
1015
+ console.log("\x1b[33mActual costs depend on your API plan and usage patterns.\x1b[0m\n");
1016
+ }
1017
+ async function cmdDiff(sessionId1, sessionId2) {
1018
+ if (!sessionId1 || !sessionId2) {
1019
+ console.error("Usage: cct diff <session-id-1> <session-id-2>");
1020
+ console.error("Example: cct diff abc123 def456");
1021
+ process.exit(1);
1022
+ }
1023
+ if (!fs.existsSync(PROJECTS_DIR)) {
1024
+ console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
1025
+ process.exit(1);
1026
+ }
1027
+ const diff = compareSessionsByCID({ sessionId1, sessionId2 });
1028
+ if (!diff) {
1029
+ console.error("One or both sessions not found.");
1030
+ console.error("Use 'cct sessions' to list available sessions.");
1031
+ process.exit(1);
1032
+ }
1033
+ console.log(formatSessionDiff(diff));
1034
+ }
1035
+ async function cmdGit() {
1036
+ console.log("Linking sessions to git repositories...\n");
1037
+ const report = linkSessionsToGit();
1038
+ console.log(formatGitLinkReport(report));
1039
+ }
1040
+ async function cmdMcpPerf() {
1041
+ console.log("Analyzing MCP tool performance...\n");
1042
+ const report = analyzeMcpPerformance();
1043
+ console.log(formatMcpPerformanceReport(report));
1044
+ }
1045
+ async function cmdAlerts() {
1046
+ const report = checkAlerts();
1047
+ console.log(formatAlertsReport(report));
1048
+ }
1049
+ async function cmdQuotas() {
1050
+ const quotas = checkQuotas();
1051
+ console.log(formatQuotasReport(quotas));
1052
+ }
735
1053
  async function cmdHealth() {
736
1054
  if (!fs.existsSync(PROJECTS_DIR)) {
737
1055
  console.error(`Claude projects directory not found: ${PROJECTS_DIR}`);
@@ -772,13 +1090,14 @@ async function cmdHealth() {
772
1090
  }
773
1091
  async function main() {
774
1092
  const args = parseArgs(process.argv.slice(2));
1093
+ let commandResult;
775
1094
  if (!args.command) {
776
1095
  printHelp();
777
1096
  process.exit(0);
778
1097
  }
779
1098
  switch (args.command) {
780
1099
  case "scan":
781
- await cmdScan(args.file);
1100
+ commandResult = await cmdScan(args.file, args.json);
782
1101
  break;
783
1102
  case "fix":
784
1103
  await cmdFix(args.file, args.noBackup);
@@ -799,7 +1118,7 @@ async function main() {
799
1118
  await cmdArchive(args.days, args.dryRun);
800
1119
  break;
801
1120
  case "maintenance":
802
- await cmdMaintenance(args.dryRun, args.auto, args.schedule);
1121
+ await cmdMaintenance(args.auto, args.schedule);
803
1122
  break;
804
1123
  case "export":
805
1124
  await cmdExport(args.file, args.output, args.format, args.withTools);
@@ -816,27 +1135,51 @@ async function main() {
816
1135
  case "health":
817
1136
  await cmdHealth();
818
1137
  break;
1138
+ case "search":
1139
+ await cmdSearch(args.query, { role: args.role, limit: args.limit, project: args.project, days: args.days });
1140
+ break;
1141
+ case "cost":
1142
+ await cmdCost();
1143
+ break;
819
1144
  case "clean":
820
1145
  await cmdClean(args.dryRun, args.days, args.category);
821
1146
  break;
822
1147
  case "mcp-validate":
823
- await cmdMcpValidate(args.file, args.test);
1148
+ await cmdMcpValidate(args.test);
1149
+ break;
1150
+ case "mcp-perf":
1151
+ await cmdMcpPerf();
824
1152
  break;
825
1153
  case "sessions":
826
1154
  await cmdSessions(args.project);
827
1155
  break;
1156
+ case "diff":
1157
+ await cmdDiff(args.file, args.subcommand);
1158
+ break;
1159
+ case "git":
1160
+ await cmdGit();
1161
+ break;
828
1162
  case "recover":
829
1163
  await cmdRecover(args.file, args.extract, args.repair);
830
1164
  break;
831
1165
  case "security-scan":
832
1166
  await cmdSecurityScan(args.file);
833
1167
  break;
1168
+ case "pii-scan":
1169
+ await cmdPIIScan(args.file, args.details);
1170
+ break;
834
1171
  case "audit":
835
1172
  await cmdAudit(args.file);
836
1173
  break;
837
1174
  case "retention":
838
1175
  await cmdRetention(args.days, args.dryRun);
839
1176
  break;
1177
+ case "alerts":
1178
+ await cmdAlerts();
1179
+ break;
1180
+ case "quotas":
1181
+ await cmdQuotas();
1182
+ break;
840
1183
  case "trace":
841
1184
  await cmdTrace(args.subcommand, {
842
1185
  dryRun: args.dryRun,
@@ -849,6 +1192,9 @@ async function main() {
849
1192
  install: args.install,
850
1193
  });
851
1194
  break;
1195
+ case "watch":
1196
+ await cmdWatch(args.json, args.interval, args.autoFix);
1197
+ break;
852
1198
  case "dashboard":
853
1199
  if (args.stop) {
854
1200
  const stopped = stopDashboard();
@@ -866,7 +1212,7 @@ async function main() {
866
1212
  }
867
1213
  }
868
1214
  else {
869
- await startDashboard({ port: args.port, daemon: args.daemon });
1215
+ await startDashboard({ port: args.port, daemon: args.daemon, authToken: args.token });
870
1216
  }
871
1217
  break;
872
1218
  default:
@@ -874,6 +1220,9 @@ async function main() {
874
1220
  printHelp();
875
1221
  process.exit(1);
876
1222
  }
1223
+ if (args.json && commandResult !== undefined) {
1224
+ console.log(JSON.stringify(commandResult, null, 2));
1225
+ }
877
1226
  }
878
1227
  main().catch((err) => {
879
1228
  console.error("Error:", err.message);