@lanonasis/cli 3.6.5 → 3.7.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 (43) hide show
  1. package/README.md +19 -2
  2. package/dist/commands/api-keys.d.ts +2 -1
  3. package/dist/commands/api-keys.js +73 -78
  4. package/dist/commands/auth.js +244 -177
  5. package/dist/commands/completion.js +31 -39
  6. package/dist/commands/config.js +162 -201
  7. package/dist/commands/enhanced-memory.js +11 -17
  8. package/dist/commands/guide.js +79 -88
  9. package/dist/commands/init.js +14 -20
  10. package/dist/commands/mcp.d.ts +10 -0
  11. package/dist/commands/mcp.js +215 -156
  12. package/dist/commands/memory.js +77 -83
  13. package/dist/commands/organization.js +15 -21
  14. package/dist/commands/topics.js +52 -58
  15. package/dist/core/achievements.js +19 -26
  16. package/dist/core/architecture.js +42 -59
  17. package/dist/core/dashboard.js +71 -81
  18. package/dist/core/error-handler.js +30 -39
  19. package/dist/core/power-mode.js +46 -53
  20. package/dist/core/progress.js +35 -44
  21. package/dist/core/welcome.js +56 -64
  22. package/dist/enhanced-cli.js +49 -58
  23. package/dist/index-simple.js +75 -113
  24. package/dist/index.js +64 -69
  25. package/dist/mcp/access-control.js +13 -17
  26. package/dist/mcp/client/enhanced-client.js +17 -28
  27. package/dist/mcp/enhanced-server.js +10 -14
  28. package/dist/mcp/logger.js +3 -7
  29. package/dist/mcp/memory-state.js +13 -17
  30. package/dist/mcp/schemas/tool-schemas.d.ts +16 -16
  31. package/dist/mcp/schemas/tool-schemas.js +122 -126
  32. package/dist/mcp/server/lanonasis-server.js +66 -57
  33. package/dist/mcp/transports/transport-manager.js +18 -25
  34. package/dist/mcp/vector-store.js +6 -10
  35. package/dist/mcp-server.js +23 -27
  36. package/dist/utils/api.js +21 -27
  37. package/dist/utils/config.d.ts +2 -1
  38. package/dist/utils/config.js +65 -78
  39. package/dist/utils/formatting.js +6 -14
  40. package/dist/utils/hash-utils.d.ts +23 -0
  41. package/dist/utils/hash-utils.js +37 -0
  42. package/dist/utils/mcp-client.js +76 -117
  43. package/package.json +36 -5
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @lanonasis/cli v3.4.15 - Enhanced MCP & Interactive CLI Experience
1
+ # @lanonasis/cli v3.7.0 - Enterprise Security & MCP Experience
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/@lanonasis/cli)](https://www.npmjs.com/package/@lanonasis/cli)
4
4
  [![Downloads](https://img.shields.io/npm/dt/@lanonasis/cli)](https://www.npmjs.com/package/@lanonasis/cli)
@@ -53,7 +53,24 @@ memory list
53
53
  maas memory list
54
54
  ```
55
55
 
56
- ## 🔐 Authentication Methods
56
+ ## 🔐 Security & Authentication
57
+
58
+ ### Enterprise-Grade SHA-256 Security (v3.7.0+)
59
+
60
+ All API keys are now secured with SHA-256 cryptographic hashing:
61
+
62
+ - ✅ **Automatic Hash Normalization**: Keys are automatically hashed before transmission
63
+ - ✅ **Double-Hash Prevention**: Smart detection prevents re-hashing already hashed keys
64
+ - ✅ **Cross-Platform Compatibility**: Works seamlessly across Node.js and browser environments
65
+ - ✅ **Zero Configuration**: Security is automatic and transparent
66
+
67
+ ```typescript
68
+ // Hash utilities are built-in and automatic
69
+ // Your vendor keys are automatically secured
70
+ onasis login --vendor-key pk_xxxxx.sk_xxxxx // ✅ Automatically hashed
71
+ ```
72
+
73
+ ### Authentication Methods
57
74
 
58
75
  ### 1. Vendor Key Authentication (Recommended)
59
76
 
@@ -1,2 +1,3 @@
1
- declare const apiKeysCommand: any;
1
+ import { Command } from 'commander';
2
+ declare const apiKeysCommand: Command;
2
3
  export default apiKeysCommand;
@@ -1,32 +1,27 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const commander_1 = require("commander");
7
- const inquirer_1 = __importDefault(require("inquirer"));
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const cli_table3_1 = __importDefault(require("cli-table3"));
10
- const api_js_1 = require("../utils/api.js");
11
- const formatting_js_1 = require("../utils/formatting.js");
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import chalk from 'chalk';
4
+ import Table from 'cli-table3';
5
+ import { apiClient } from '../utils/api.js';
6
+ import { formatDate, truncateText } from '../utils/formatting.js';
12
7
  // Enhanced VPS-style color scheme
13
8
  const colors = {
14
- primary: chalk_1.default.blue.bold,
15
- success: chalk_1.default.green,
16
- warning: chalk_1.default.yellow,
17
- error: chalk_1.default.red,
18
- info: chalk_1.default.cyan,
19
- accent: chalk_1.default.magenta,
20
- muted: chalk_1.default.gray,
21
- highlight: chalk_1.default.white.bold
9
+ primary: chalk.blue.bold,
10
+ success: chalk.green,
11
+ warning: chalk.yellow,
12
+ error: chalk.red,
13
+ info: chalk.cyan,
14
+ accent: chalk.magenta,
15
+ muted: chalk.gray,
16
+ highlight: chalk.white.bold
22
17
  };
23
- const apiKeysCommand = new commander_1.Command('api-keys')
18
+ const apiKeysCommand = new Command('api-keys')
24
19
  .alias('keys')
25
20
  .description(colors.info('🔐 Manage API keys securely with enterprise-grade encryption'));
26
21
  // ============================================================================
27
22
  // PROJECT COMMANDS
28
23
  // ============================================================================
29
- const projectsCommand = new commander_1.Command('projects')
24
+ const projectsCommand = new Command('projects')
30
25
  .description(colors.accent('📁 Manage API key projects and organization'));
31
26
  projectsCommand
32
27
  .command('create')
@@ -43,7 +38,7 @@ projectsCommand
43
38
  organizationId: options.organizationId
44
39
  };
45
40
  if (options.interactive || !projectData.name || !projectData.organizationId) {
46
- const answers = await inquirer_1.default.prompt([
41
+ const answers = await inquirer.prompt([
47
42
  {
48
43
  type: 'input',
49
44
  name: 'name',
@@ -70,16 +65,16 @@ projectsCommand
70
65
  ]);
71
66
  projectData = { ...projectData, ...answers };
72
67
  }
73
- const project = await api_js_1.apiClient.post('/api-keys/projects', projectData);
74
- console.log(chalk_1.default.green('✅ Project created successfully!'));
75
- console.log(chalk_1.default.blue(`Project ID: ${project.id}`));
76
- console.log(chalk_1.default.blue(`Name: ${project.name}`));
68
+ const project = await apiClient.post('/api-keys/projects', projectData);
69
+ console.log(chalk.green('✅ Project created successfully!'));
70
+ console.log(chalk.blue(`Project ID: ${project.id}`));
71
+ console.log(chalk.blue(`Name: ${project.name}`));
77
72
  if (project.description) {
78
- console.log(chalk_1.default.blue(`Description: ${project.description}`));
73
+ console.log(chalk.blue(`Description: ${project.description}`));
79
74
  }
80
75
  }
81
76
  catch (error) {
82
- console.error(chalk_1.default.red('❌ Failed to create project:'), error.message);
77
+ console.error(chalk.red('❌ Failed to create project:'), error.message);
83
78
  process.exit(1);
84
79
  }
85
80
  });
@@ -90,33 +85,33 @@ projectsCommand
90
85
  .option('--json', 'Output as JSON')
91
86
  .action(async (options) => {
92
87
  try {
93
- const projects = await api_js_1.apiClient.get('/api-keys/projects');
88
+ const projects = await apiClient.get('/api-keys/projects');
94
89
  if (options.json) {
95
90
  console.log(JSON.stringify(projects, null, 2));
96
91
  return;
97
92
  }
98
93
  if (projects.length === 0) {
99
- console.log(chalk_1.default.yellow('No projects found'));
94
+ console.log(chalk.yellow('No projects found'));
100
95
  return;
101
96
  }
102
- const table = new cli_table3_1.default({
103
- head: ['ID', 'Name', 'Description', 'Owner', 'Created'].map(h => chalk_1.default.cyan(h)),
97
+ const table = new Table({
98
+ head: ['ID', 'Name', 'Description', 'Owner', 'Created'].map(h => chalk.cyan(h)),
104
99
  style: { head: [], border: [] }
105
100
  });
106
101
  projects.forEach((project) => {
107
102
  table.push([
108
- (0, formatting_js_1.truncateText)(project.id, 20),
103
+ truncateText(project.id, 20),
109
104
  project.name,
110
- (0, formatting_js_1.truncateText)(project.description || '-', 30),
111
- (0, formatting_js_1.truncateText)(project.ownerId, 20),
112
- (0, formatting_js_1.formatDate)(project.createdAt)
105
+ truncateText(project.description || '-', 30),
106
+ truncateText(project.ownerId, 20),
107
+ formatDate(project.createdAt)
113
108
  ]);
114
109
  });
115
110
  console.log(table.toString());
116
- console.log(chalk_1.default.gray(`Total: ${projects.length} projects`));
111
+ console.log(chalk.gray(`Total: ${projects.length} projects`));
117
112
  }
118
113
  catch (error) {
119
- console.error(chalk_1.default.red('❌ Failed to list projects:'), error.message);
114
+ console.error(chalk.red('❌ Failed to list projects:'), error.message);
120
115
  process.exit(1);
121
116
  }
122
117
  });
@@ -150,8 +145,8 @@ apiKeysCommand
150
145
  rotationFrequency: parseInt(options.rotationFrequency)
151
146
  };
152
147
  if (options.interactive || !keyData.name || !keyData.value || !keyData.projectId) {
153
- const projects = await api_js_1.apiClient.get('/api-keys/projects');
154
- const answers = await inquirer_1.default.prompt([
148
+ const projects = await apiClient.get('/api-keys/projects');
149
+ const answers = await inquirer.prompt([
155
150
  {
156
151
  type: 'input',
157
152
  name: 'name',
@@ -230,7 +225,7 @@ apiKeysCommand
230
225
  ]);
231
226
  keyData = { ...keyData, ...answers };
232
227
  }
233
- const apiKey = await api_js_1.apiClient.post('/api-keys', keyData);
228
+ const apiKey = await apiClient.post('/api-keys', keyData);
234
229
  console.log(colors.success('🔐 API key created successfully!'));
235
230
  console.log(colors.info('━'.repeat(50)));
236
231
  console.log(`${colors.highlight('Key ID:')} ${colors.primary(apiKey.id)}`);
@@ -258,7 +253,7 @@ apiKeysCommand
258
253
  if (options.projectId) {
259
254
  url += `?projectId=${options.projectId}`;
260
255
  }
261
- const apiKeys = await api_js_1.apiClient.get(url);
256
+ const apiKeys = await apiClient.get(url);
262
257
  if (options.json) {
263
258
  console.log(JSON.stringify(apiKeys, null, 2));
264
259
  return;
@@ -270,7 +265,7 @@ apiKeysCommand
270
265
  }
271
266
  console.log(colors.primary('🔐 API Key Management'));
272
267
  console.log(colors.info('═'.repeat(80)));
273
- const table = new cli_table3_1.default({
268
+ const table = new Table({
274
269
  head: ['ID', 'Name', 'Type', 'Environment', 'Status', 'Usage', 'Last Rotated'].map(h => colors.accent(h)),
275
270
  style: { head: [], border: [] }
276
271
  });
@@ -278,13 +273,13 @@ apiKeysCommand
278
273
  const statusColor = key.status === 'active' ? colors.success :
279
274
  key.status === 'rotating' ? colors.warning : colors.error;
280
275
  table.push([
281
- (0, formatting_js_1.truncateText)(key.id, 20),
276
+ truncateText(key.id, 20),
282
277
  key.name,
283
278
  key.keyType,
284
279
  key.environment,
285
280
  statusColor(key.status),
286
281
  colors.highlight(key.usageCount.toString()),
287
- (0, formatting_js_1.formatDate)(key.lastRotated)
282
+ formatDate(key.lastRotated)
288
283
  ]);
289
284
  });
290
285
  console.log(table.toString());
@@ -304,7 +299,7 @@ apiKeysCommand
304
299
  .option('--json', 'Output as JSON')
305
300
  .action(async (keyId, options) => {
306
301
  try {
307
- const apiKey = await api_js_1.apiClient.get(`/api-keys/${keyId}`);
302
+ const apiKey = await apiClient.get(`/api-keys/${keyId}`);
308
303
  if (options.json) {
309
304
  console.log(JSON.stringify(apiKey, null, 2));
310
305
  return;
@@ -323,11 +318,11 @@ apiKeysCommand
323
318
  console.log(`${colors.highlight('Usage Count:')} ${colors.accent(apiKey.usageCount)}`);
324
319
  console.log(`${colors.highlight('Tags:')} ${colors.muted(apiKey.tags.join(', ') || 'None')}`);
325
320
  console.log(`${colors.highlight('Rotation Frequency:')} ${colors.info(apiKey.rotationFrequency)} days`);
326
- console.log(`${colors.highlight('Last Rotated:')} ${colors.muted((0, formatting_js_1.formatDate)(apiKey.lastRotated))}`);
327
- console.log(`${colors.highlight('Created:')} ${colors.muted((0, formatting_js_1.formatDate)(apiKey.createdAt))}`);
328
- console.log(`${colors.highlight('Updated:')} ${colors.muted((0, formatting_js_1.formatDate)(apiKey.updatedAt))}`);
321
+ console.log(`${colors.highlight('Last Rotated:')} ${colors.muted(formatDate(apiKey.lastRotated))}`);
322
+ console.log(`${colors.highlight('Created:')} ${colors.muted(formatDate(apiKey.createdAt))}`);
323
+ console.log(`${colors.highlight('Updated:')} ${colors.muted(formatDate(apiKey.updatedAt))}`);
329
324
  if (apiKey.expiresAt) {
330
- console.log(`${colors.highlight('Expires:')} ${colors.warning((0, formatting_js_1.formatDate)(apiKey.expiresAt))}`);
325
+ console.log(`${colors.highlight('Expires:')} ${colors.warning(formatDate(apiKey.expiresAt))}`);
331
326
  }
332
327
  console.log(colors.info('═'.repeat(60)));
333
328
  }
@@ -358,8 +353,8 @@ apiKeysCommand
358
353
  if (options.rotationFrequency)
359
354
  updateData.rotationFrequency = parseInt(options.rotationFrequency);
360
355
  if (options.interactive || Object.keys(updateData).length === 0) {
361
- const current = await api_js_1.apiClient.get(`/api-keys/${keyId}`);
362
- const answers = await inquirer_1.default.prompt([
356
+ const current = await apiClient.get(`/api-keys/${keyId}`);
357
+ const answers = await inquirer.prompt([
363
358
  {
364
359
  type: 'input',
365
360
  name: 'name',
@@ -400,7 +395,7 @@ apiKeysCommand
400
395
  updateData = { ...updateData, ...answers };
401
396
  delete updateData.updateValue;
402
397
  }
403
- const updatedKey = await api_js_1.apiClient.put(`/api-keys/${keyId}`, updateData);
398
+ const updatedKey = await apiClient.put(`/api-keys/${keyId}`, updateData);
404
399
  console.log(colors.success('🔄 API key updated successfully!'));
405
400
  console.log(colors.info('━'.repeat(40)));
406
401
  console.log(`${colors.highlight('Name:')} ${colors.accent(updatedKey.name)}`);
@@ -425,8 +420,8 @@ apiKeysCommand
425
420
  .action(async (keyId, options) => {
426
421
  try {
427
422
  if (!options.force) {
428
- const apiKey = await api_js_1.apiClient.get(`/api-keys/${keyId}`);
429
- const { confirm } = await inquirer_1.default.prompt([
423
+ const apiKey = await apiClient.get(`/api-keys/${keyId}`);
424
+ const { confirm } = await inquirer.prompt([
430
425
  {
431
426
  type: 'confirm',
432
427
  name: 'confirm',
@@ -439,7 +434,7 @@ apiKeysCommand
439
434
  return;
440
435
  }
441
436
  }
442
- await api_js_1.apiClient.delete(`/api-keys/${keyId}`);
437
+ await apiClient.delete(`/api-keys/${keyId}`);
443
438
  console.log(colors.success('🗑️ API key deleted successfully!'));
444
439
  }
445
440
  catch (error) {
@@ -450,7 +445,7 @@ apiKeysCommand
450
445
  // ============================================================================
451
446
  // MCP COMMANDS
452
447
  // ============================================================================
453
- const mcpCommand = new commander_1.Command('mcp')
448
+ const mcpCommand = new Command('mcp')
454
449
  .description(colors.accent('🤖 Model Context Protocol (MCP) - Secure AI agent access'));
455
450
  mcpCommand
456
451
  .command('register-tool')
@@ -483,7 +478,7 @@ mcpCommand
483
478
  riskLevel: options.riskLevel
484
479
  };
485
480
  if (options.interactive || !toolData.toolId || !toolData.toolName || !toolData.organizationId) {
486
- const answers = await inquirer_1.default.prompt([
481
+ const answers = await inquirer.prompt([
487
482
  {
488
483
  type: 'input',
489
484
  name: 'toolId',
@@ -569,7 +564,7 @@ mcpCommand
569
564
  delete toolData.maxConcurrentSessions;
570
565
  delete toolData.maxSessionDuration;
571
566
  }
572
- const tool = await api_js_1.apiClient.post('/api-keys/mcp/tools', toolData);
567
+ const tool = await apiClient.post('/api-keys/mcp/tools', toolData);
573
568
  console.log(colors.success('🤖 MCP tool registered successfully!'));
574
569
  console.log(colors.info('━'.repeat(50)));
575
570
  console.log(`${colors.highlight('Tool ID:')} ${colors.primary(tool.toolId)}`);
@@ -589,7 +584,7 @@ mcpCommand
589
584
  .option('--json', 'Output as JSON')
590
585
  .action(async (options) => {
591
586
  try {
592
- const tools = await api_js_1.apiClient.get('/api-keys/mcp/tools');
587
+ const tools = await apiClient.get('/api-keys/mcp/tools');
593
588
  if (options.json) {
594
589
  console.log(JSON.stringify(tools, null, 2));
595
590
  return;
@@ -601,7 +596,7 @@ mcpCommand
601
596
  }
602
597
  console.log(colors.primary('🤖 Registered MCP Tools'));
603
598
  console.log(colors.info('═'.repeat(80)));
604
- const table = new cli_table3_1.default({
599
+ const table = new Table({
605
600
  head: ['Tool ID', 'Name', 'Risk Level', 'Status', 'Auto Approve', 'Created'].map(h => colors.accent(h)),
606
601
  style: { head: [], border: [] }
607
602
  });
@@ -614,7 +609,7 @@ mcpCommand
614
609
  tool.riskLevel,
615
610
  statusColor(tool.status),
616
611
  tool.autoApprove ? colors.success('Yes') : colors.error('No'),
617
- (0, formatting_js_1.formatDate)(tool.createdAt)
612
+ formatDate(tool.createdAt)
618
613
  ]);
619
614
  });
620
615
  console.log(table.toString());
@@ -649,8 +644,8 @@ mcpCommand
649
644
  };
650
645
  if (options.interactive || !requestData.toolId || !requestData.organizationId ||
651
646
  requestData.keyNames.length === 0 || !requestData.environment || !requestData.justification) {
652
- const tools = await api_js_1.apiClient.get('/api-keys/mcp/tools');
653
- const answers = await inquirer_1.default.prompt([
647
+ const tools = await apiClient.get('/api-keys/mcp/tools');
648
+ const answers = await inquirer.prompt([
654
649
  {
655
650
  type: 'list',
656
651
  name: 'toolId',
@@ -700,7 +695,7 @@ mcpCommand
700
695
  ]);
701
696
  requestData = { ...requestData, ...answers };
702
697
  }
703
- const response = await api_js_1.apiClient.post('/api-keys/mcp/request-access', requestData);
698
+ const response = await apiClient.post('/api-keys/mcp/request-access', requestData);
704
699
  console.log(colors.success('🔐 Access request created successfully!'));
705
700
  console.log(colors.info('━'.repeat(50)));
706
701
  console.log(`${colors.highlight('Request ID:')} ${colors.primary(response.requestId)}`);
@@ -716,7 +711,7 @@ mcpCommand
716
711
  // ============================================================================
717
712
  // ANALYTICS COMMANDS
718
713
  // ============================================================================
719
- const analyticsCommand = new commander_1.Command('analytics')
714
+ const analyticsCommand = new Command('analytics')
720
715
  .description('View API key usage analytics and security events');
721
716
  analyticsCommand
722
717
  .command('usage')
@@ -735,27 +730,27 @@ analyticsCommand
735
730
  if (params.toString()) {
736
731
  url += `?${params.toString()}`;
737
732
  }
738
- const analytics = await api_js_1.apiClient.get(url);
733
+ const analytics = await apiClient.get(url);
739
734
  if (options.json) {
740
735
  console.log(JSON.stringify(analytics, null, 2));
741
736
  return;
742
737
  }
743
738
  if (analytics.length === 0) {
744
- console.log(chalk_1.default.yellow('No usage data found'));
739
+ console.log(chalk.yellow('No usage data found'));
745
740
  return;
746
741
  }
747
- const table = new cli_table3_1.default({
748
- head: ['Key ID', 'Operation', 'Tool ID', 'Success', 'Timestamp'].map(h => chalk_1.default.cyan(h)),
742
+ const table = new Table({
743
+ head: ['Key ID', 'Operation', 'Tool ID', 'Success', 'Timestamp'].map(h => chalk.cyan(h)),
749
744
  style: { head: [], border: [] }
750
745
  });
751
746
  analytics.forEach((entry) => {
752
747
  const successColor = entry.success ? colors.success('✓') : colors.error('✗');
753
748
  table.push([
754
- (0, formatting_js_1.truncateText)(entry.keyId || '-', 20),
749
+ truncateText(entry.keyId || '-', 20),
755
750
  entry.operation,
756
- (0, formatting_js_1.truncateText)(entry.toolId || '-', 15),
751
+ truncateText(entry.toolId || '-', 15),
757
752
  successColor,
758
- (0, formatting_js_1.formatDate)(entry.timestamp)
753
+ formatDate(entry.timestamp)
759
754
  ]);
760
755
  });
761
756
  console.log(table.toString());
@@ -779,7 +774,7 @@ analyticsCommand
779
774
  if (options.severity) {
780
775
  url += `?severity=${options.severity}`;
781
776
  }
782
- const events = await api_js_1.apiClient.get(url);
777
+ const events = await apiClient.get(url);
783
778
  if (options.json) {
784
779
  console.log(JSON.stringify(events, null, 2));
785
780
  return;
@@ -790,7 +785,7 @@ analyticsCommand
790
785
  }
791
786
  console.log(colors.primary('🛡️ Security Events Monitor'));
792
787
  console.log(colors.info('═'.repeat(80)));
793
- const table = new cli_table3_1.default({
788
+ const table = new Table({
794
789
  head: ['Event Type', 'Severity', 'Description', 'Resolved', 'Timestamp'].map(h => colors.accent(h)),
795
790
  style: { head: [], border: [] }
796
791
  });
@@ -801,9 +796,9 @@ analyticsCommand
801
796
  table.push([
802
797
  event.eventType,
803
798
  severityColor(event.severity.toUpperCase()),
804
- (0, formatting_js_1.truncateText)(event.description, 40),
799
+ truncateText(event.description, 40),
805
800
  event.resolved ? colors.success('✓') : colors.warning('Pending'),
806
- (0, formatting_js_1.formatDate)(event.timestamp)
801
+ formatDate(event.timestamp)
807
802
  ]);
808
803
  });
809
804
  console.log(table.toString());
@@ -820,4 +815,4 @@ analyticsCommand
820
815
  apiKeysCommand.addCommand(projectsCommand);
821
816
  apiKeysCommand.addCommand(mcpCommand);
822
817
  apiKeysCommand.addCommand(analyticsCommand);
823
- exports.default = apiKeysCommand;
818
+ export default apiKeysCommand;