claudmax 1.0.2 → 1.0.5

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 (2) hide show
  1. package/index.js +149 -73
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -398,7 +398,8 @@ function installMCPServer() {
398
398
  console.log(` ${CHECK} ${C.green(MCP_PKG + ' installed successfully.')}`);
399
399
  return true;
400
400
  } catch (err) {
401
- console.log(` ${WARN} Could not install ${MCP_PKG}: ${C.dim((err.stderr || err.message || '').trim())}`);
401
+ const errMsg = String(err.stderr || err.message || '');
402
+ console.log(` ${WARN} Could not install ${MCP_PKG}: ${C.dim(errMsg.trim())}`);
402
403
  console.log(` ${INFO} Install manually later: ${C.bold('npm install -g ' + MCP_PKG)}`);
403
404
  return false;
404
405
  }
@@ -407,14 +408,116 @@ function installMCPServer() {
407
408
  // ── Banner ────────────────────────────────────────────────────────────────────
408
409
  function printBanner() {
409
410
  console.log('');
410
- console.log(C.magenta('\u2554' + '\u2550'.repeat(48) + '\u2557'));
411
- console.log(C.magenta('\u2551') + C.bold(' \u2726 ClaudMax Setup Wizard \u2726 ') + C.magenta('\u2551'));
411
+ console.log(C.magenta('\u2554' + '\u2550'.repeat(44) + '\u2557'));
412
+ console.log(C.magenta('\u2551') + C.bold(' \u26A1 ClaudMax Setup ') + C.magenta('\u2551'));
413
+ console.log(C.magenta('\u255A' + '\u2550'.repeat(44) + '\u255D'));
414
+ console.log('');
415
+ }
416
+
417
+ // ── CLI argument parsing ────────────────────────────────────────────────────────
418
+ const args = process.argv.slice(2);
419
+ const command = args[0];
420
+
421
+ // ── Status command ─────────────────────────────────────────────────────────────
422
+ async function showStatus() {
423
+ const config = readJson(CONFIG_FILE);
424
+ if (!config || !config.apiKey) {
425
+ console.log(`\n${WARN} No API key configured. Run ${C.bold('npx claudmax')} first.\n`);
426
+ process.exit(1);
427
+ }
428
+
429
+ console.log(`\n${C.magenta('\u2554' + '\u2550'.repeat(48) + '\u2557')}`);
430
+ console.log(C.magenta('\u2551') + C.bold(' \u2726 ClaudMax Status \u2726 ') + C.magenta('\u2551'));
412
431
  console.log(C.magenta('\u255A' + '\u2550'.repeat(48) + '\u255D'));
413
432
  console.log('');
433
+
434
+ // Fetch key status
435
+ const body = JSON.stringify({ apiKey: config.apiKey });
436
+ const postData = Buffer.from(body);
437
+
438
+ const options = {
439
+ hostname: 'api.claudmax.pro',
440
+ port: 443,
441
+ path: '/v1/key-status',
442
+ method: 'POST',
443
+ headers: {
444
+ 'Content-Type': 'application/json',
445
+ 'Content-Length': postData.length,
446
+ 'User-Agent': 'ClaudMax-CLI/1.0.0',
447
+ },
448
+ timeout: 15000,
449
+ };
450
+
451
+ return new Promise((resolve) => {
452
+ const req = https.request(options, (res) => {
453
+ let data = '';
454
+ res.on('data', (chunk) => { data += chunk; });
455
+ res.on('end', () => {
456
+ try {
457
+ const json = JSON.parse(data);
458
+ if (res.statusCode === 200) {
459
+ const pct = json.tokensLimit > 0 ? Math.min(100, (json.tokensUsed / json.tokensLimit) * 100) : 0;
460
+ const tierColors = { free: C.dim('Gray'), '5x': C.cyan('Blue'), '20x': C.magenta('Purple'), unlimited: C.green('Gold') };
461
+ console.log(` ${CHECK} ${C.green('API Key is active')}`);
462
+ console.log(` ${INFO} Name: ${C.bold(json.name || 'ClaudMax Key')}`);
463
+ console.log(` ${INFO} Prefix: ${C.magenta(json.prefix)}••••••`);
464
+ console.log(` ${INFO} Tier: ${tierColors[json.tier] || C.dim('Free')} (${C.bold(json.tier?.toUpperCase() || 'FREE')})`);
465
+ console.log(` ${INFO} Status: ${json.isActive ? C.green('Active') : C.red('Inactive')}`);
466
+ console.log('');
467
+ console.log(` ${C.bold('Usage (5h window):')}`);
468
+ const barLen = 30;
469
+ const filled = Math.round((pct / 100) * barLen);
470
+ const bar = C.purple('\u2588'.repeat(filled)) + C.dim('\u2591'.repeat(barLen - filled));
471
+ console.log(` ${bar} ${C.dim(`${pct.toFixed(1)}%`)}`);
472
+ console.log(` ${INFO} Requests: ${C.cyan(json.requestsUsed?.toLocaleString() || 0)} / ${C.cyan(json.requestsLimit?.toLocaleString() || 'N/A')}`);
473
+ console.log(` ${INFO} Tokens: ${C.cyan((json.tokensUsed || 0).toLocaleString())} / ${C.cyan((json.tokensLimit || 0).toLocaleString())}`);
474
+ console.log('');
475
+ if (json.windowResetAt) {
476
+ const reset = new Date(json.windowResetAt);
477
+ console.log(` ${INFO} Resets: ${C.dim(reset.toLocaleString())}`);
478
+ }
479
+ } else {
480
+ console.log(` ${CROSS} ${C.red('Failed to fetch status: ' + (json.error || `HTTP ${res.statusCode}`))}`);
481
+ }
482
+ } catch {
483
+ console.log(` ${CROSS} ${C.red('Failed to parse response')}`);
484
+ }
485
+ console.log('');
486
+ resolve();
487
+ });
488
+ });
489
+ req.on('error', (err) => {
490
+ console.log(` ${WARN} ${C.yellow('Network error: ' + err.message)}`);
491
+ console.log('');
492
+ resolve();
493
+ });
494
+ req.on('timeout', () => { req.destroy(); console.log(` ${CROSS} ${C.red('Request timed out')}\n`); resolve(); });
495
+ req.write(postData);
496
+ req.end();
497
+ });
498
+ }
499
+
500
+ // ── Help ───────────────────────────────────────────────────────────────────────
501
+ function showHelp() {
502
+ console.log(`\n${C.bold('ClaudMax CLI')} — Configure Claude Code and other IDEs to use ClaudMax API.\n`);
503
+ console.log(` ${C.cyan('npx claudmax')} ${C.dim('Launch the interactive setup wizard')}`);
504
+ console.log(` ${C.cyan('npx claudmax status')} ${C.dim('Check your API key usage and limits')}`);
505
+ console.log(` ${C.cyan('npx claudmax --help')} ${C.dim('Show this help message')}`);
506
+ console.log('');
414
507
  }
415
508
 
416
509
  // ── Main ──────────────────────────────────────────────────────────────────────
417
510
  async function main() {
511
+ if (command === 'status') {
512
+ await showStatus();
513
+ return;
514
+ }
515
+ if (command === '--help' || command === '-h') {
516
+ showHelp();
517
+ return;
518
+ }
519
+
520
+ // Default: interactive setup wizard
418
521
  const rl = createRL();
419
522
 
420
523
  printBanner();
@@ -450,31 +553,8 @@ async function main() {
450
553
  }
451
554
  }
452
555
 
453
- if (nodeOk && !gitOk) {
454
- if (!installDep('Git', installGit)) {
455
- console.log(`\n${C.yellow('Git installation failed. You can install it manually.')}`);
456
- } else {
457
- gitOk = isCommandAvailable('git');
458
- }
459
- }
460
-
461
- if (nodeOk && !claudeOk) {
462
- const installClaude = await ask(rl, `\n${WARN} Claude CLI not found. Install it? ${C.bold('[Y/n]: ')}`);
463
- if (!installClaude || installClaude.toLowerCase() === 'y' || installClaude.toLowerCase() === 'yes') {
464
- if (!installDep('Claude CLI', installClaudeCLI)) {
465
- console.log(`\n${C.yellow('Claude CLI installation failed. You can install it with: npm i -g @anthropic-ai/claude-code')}`);
466
- } else {
467
- claudeOk = isCommandAvailable('claude');
468
- }
469
- }
470
- }
471
-
472
- console.log('');
473
-
474
- // ── Step 2: API key prompt ───────────────────────────────────────────────
475
- console.log(C.bold('Step 2: Enter your ClaudMax API key\n'));
476
- console.log(` ${INFO} Get your API key from the ${C.bold('ClaudMax Admin Dashboard')}: ${C.cyan('https://claudmax.pro/admin/dashboard')}`);
477
- console.log('');
556
+ // ── Step 1: API key prompt ───────────────────────────────────────────────
557
+ console.log(C.bold('\nStep 1: Enter your ClaudMax API key\n'));
478
558
 
479
559
  let apiKey = '';
480
560
  while (!apiKey.trim()) {
@@ -486,42 +566,14 @@ async function main() {
486
566
  apiKey = apiKey.trim();
487
567
  console.log('');
488
568
 
489
- // ── Step 3: Verify API key ───────────────────────────────────────────────
490
- console.log(C.bold('Step 3: Verifying API key...\n'));
491
- const result = await verifyConnection(apiKey);
492
-
493
- if (result.ok) {
494
- const data = result.data;
495
- if (result.status === 401) {
496
- console.log(` ${CROSS} ${C.red('Invalid API key. Please check and try again.')}`);
497
- console.log(` ${INFO} ${C.dim(data.error || 'Authentication failed')}`);
498
- rl.close();
499
- process.exit(1);
500
- } else {
501
- console.log(` ${CHECK} ${C.green('API key is valid!')}`);
502
- const tier = (data.tier || 'free').toUpperCase();
503
- const limit = data.requestsLimit?.toLocaleString() || 'N/A';
504
- const tokenLimit = data.tokensLimit ? (data.tokensLimit >= 1e9 ? 'Unlimited' : (data.tokensLimit / 1e6).toFixed(0) + 'M tokens/5h') : 'N/A';
505
- console.log(` ${INFO} Plan: ${C.magenta(tier)} | Requests: ${C.cyan(limit)} | Tokens: ${C.cyan(tokenLimit)}`);
506
- }
507
- } else {
508
- console.log(` ${WARN} ${C.yellow('Could not verify API key (network error). Continuing with setup anyway...')}`);
509
- console.log(` ${INFO} ${C.dim(result.error || 'Connection failed')}`);
510
- }
511
-
512
- // ── Step 4: Configure system ──────────────────────────────────────────────
513
- console.log('');
514
- const profile = configureSystem(apiKey);
515
-
516
- // ── Step 5: IDE selection ─────────────────────────────────────────────────
517
- console.log('');
518
- console.log(C.bold('Step 5: Select IDEs to configure\n'));
569
+ // ── Step 2: IDE selection ─────────────────────────────────────────────────
570
+ console.log(C.bold('Step 2: Select IDEs to configure\n'));
519
571
 
520
572
  const IDES = [
521
- { id: 1, name: 'Claude Code CLI', shortName: 'Claude Code', configure: configureClaudeCLI },
573
+ { id: 1, name: 'Claude Code (CLI)', shortName: 'Claude Code', configure: configureClaudeCLI },
522
574
  { id: 2, name: 'VS Code (Claude Extension)', shortName: 'VS Code', configure: configureVSCodeClaude },
523
- { id: 3, name: 'Cursor', shortName: 'Cursor', configure: configureCursor },
524
- { id: 4, name: 'Windsurf', shortName: 'Windsurf', configure: configureWindsurf },
575
+ { id: 3, name: 'Cursor', shortName: 'Cursor', configure: configureCursor },
576
+ { id: 4, name: 'Windsurf', shortName: 'Windsurf', configure: configureWindsurf },
525
577
  { id: 5, name: 'Cline (VS Code Extension)', shortName: 'Cline', configure: configureCline },
526
578
  { id: 6, name: 'Roo Code (VS Code Extension)', shortName: 'Roo Code', configure: configureRooCode },
527
579
  ];
@@ -530,7 +582,7 @@ async function main() {
530
582
  console.log(` ${C.purple('[' + ide.id + ']')} ${ide.name}`);
531
583
  }
532
584
  console.log('');
533
- console.log(` ${C.dim("Enter numbers separated by spaces (e.g. 1 3 4), " + C.bold("'a'") + " for all, or press Enter to skip")}`);
585
+ console.log(` ${C.dim("Enter numbers separated by spaces (e.g. 1 3 4), or " + C.bold("'a'") + " for all")}`);
534
586
 
535
587
  const choice = await ask(rl, ` ${C.bold('Your choice')}: `);
536
588
  let selectedIds = [];
@@ -541,42 +593,66 @@ async function main() {
541
593
  selectedIds = choice.trim().split(/[\s,]+/).map(Number).filter((n) => n >= 1 && n <= IDES.length);
542
594
  }
543
595
 
596
+ console.log('');
597
+
598
+ // ── Configure selected IDEs ──────────────────────────────────────────────
544
599
  if (selectedIds.length > 0) {
545
600
  const selectedIDEs = IDES.filter((ide) => selectedIds.includes(ide.id));
546
601
  for (const ide of selectedIDEs) {
547
602
  try {
548
603
  ide.configure(apiKey);
549
604
  } catch (err) {
550
- console.log(` ${CROSS} Failed to configure ${ide.name}: ${err.message}`);
605
+ console.log(` ${CROSS} Failed to configure ${ide.name}: ${String(err.message || err)}`);
551
606
  }
552
607
  }
553
608
  } else {
554
- console.log(`\n ${WARN} ${C.yellow('No IDEs selected. You can configure them manually later.')}`);
609
+ console.log(` ${WARN} ${C.yellow('No IDEs selected. Skipping IDE configuration.')}`);
555
610
  }
556
611
 
557
- // ── Step 6: Install MCP server ───────────────────────────────────────────
612
+ // ── Install MCP server ───────────────────────────────────────────────────
558
613
  installMCPServer();
559
614
 
615
+ // ── Verify connection ─────────────────────────────────────────────────────
616
+ console.log(`\n${ARROW} ${C.bold('Verifying connection to ClaudMax API...')}`);
617
+ const result = await verifyConnection(apiKey);
618
+
619
+ if (result.ok) {
620
+ const data = result.data;
621
+ if (result.status === 401) {
622
+ console.log(` ${CROSS} ${C.red('Invalid API key. Please check and try again.')}`);
623
+ console.log(` ${INFO} ${C.dim(data.error || 'Authentication failed')}`);
624
+ rl.close();
625
+ process.exit(1);
626
+ } else {
627
+ console.log(` ${CHECK} ${C.green('Connected — API key is valid.')}`);
628
+ const tier = (data.tier || 'free').toUpperCase();
629
+ const limit = data.requestsLimit?.toLocaleString() || 'N/A';
630
+ const tokenLimit = data.tokensLimit ? (data.tokensLimit >= 1e9 ? 'Unlimited' : (data.tokensLimit / 1e6).toFixed(0) + 'M tokens/5h') : 'N/A';
631
+ console.log(` ${INFO} Plan: ${C.magenta(tier)} | Requests: ${C.cyan(limit)} | Tokens: ${C.cyan(tokenLimit)}`);
632
+ }
633
+ } else {
634
+ console.log(` ${WARN} ${C.yellow('Could not verify API key (network error).')}`);
635
+ console.log(` ${INFO} ${C.dim(result.error || 'Connection failed')}`);
636
+ }
637
+
560
638
  // ── Summary ───────────────────────────────────────────────────────────────
561
639
  console.log('');
562
- console.log(C.magenta('\u2554' + '\u2550'.repeat(48) + '\u2557'));
563
- console.log(C.magenta('\u2551') + C.bold(' \u2713 Setup complete! ') + C.magenta('\u2551'));
564
- console.log(C.magenta('\u2551') + C.green(' All systems configured successfully. ') + C.magenta('\u2551'));
565
- console.log(C.magenta('\u255A' + '\u2550'.repeat(48) + '\u255D'));
640
+ console.log(C.magenta('\u2554' + '\u2550'.repeat(44) + '\u2557'));
641
+ console.log(C.magenta('\u2551') + C.bold(' \u2713 Setup complete! ') + C.magenta('\u2551'));
642
+ console.log(C.magenta('\u2551') + C.green(' Restart your IDE(s) to apply. ') + C.magenta('\u2551'));
643
+ console.log(C.magenta('\u255A' + '\u2550'.repeat(44) + '\u255D'));
566
644
  console.log('');
567
645
  console.log(` ${INFO} ${C.bold('Next steps:')}`);
568
- console.log(` 1. ${C.dim('Run:')} ${C.bold('source ' + profile)} ${C.dim('(or restart your terminal)')}`);
646
+ console.log(` 1. ${C.dim('Restart your IDE(s) to apply.')}`);
569
647
  console.log(` 2. ${C.dim('Verify with:')} ${C.bold('claude --version')}`);
570
648
  console.log(` 3. ${C.dim('Start chatting:')} ${C.bold('claude')}`);
571
649
  console.log(` 4. ${C.dim('Check usage:')} ${C.bold('npx claudmax status')}`);
572
650
  console.log('');
573
- console.log(` ${INFO} Config saved at: ${C.magenta(CONFIG_FILE)}`);
574
- console.log('');
575
651
 
576
652
  rl.close();
577
653
  }
578
654
 
579
655
  main().catch((err) => {
580
- console.error('\n' + C.red('\u2717 Fatal error: ' + err.message));
656
+ console.error('\n' + C.red('\u2717 Fatal error: ' + String(err.message || err)));
581
657
  process.exit(1);
582
658
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudmax",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "ClaudMax CLI — Configure Claude Code, Cursor, Windsurf, Cline, and Roo Code to use ClaudMax API gateway with one command",
5
5
  "main": "index.js",
6
6
  "bin": {