claudmax 1.0.3 → 1.0.6

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 +78 -87
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -231,32 +231,46 @@ function configureSystem(apiKey) {
231
231
  apiKey,
232
232
  baseUrl: API_BASE,
233
233
  configuredAt: new Date().toISOString(),
234
- version: '1.0.0',
234
+ version: '1.0.5',
235
235
  });
236
236
  console.log(` ${CHECK} Saved config to ${C.magenta(CONFIG_FILE)}`);
237
237
 
238
238
  // 2. Write environment variables to shell profile
239
239
  const profile = getShellProfile();
240
+
241
+ // Remove any existing ClaudMax/OpusCode/OpusMax blocks first
242
+ const existing = fs.existsSync(profile) ? fs.readFileSync(profile, 'utf8') : '';
243
+ let cleaned = existing
244
+ .split('\n')
245
+ .filter(line => {
246
+ const trimmed = line.trim();
247
+ return (
248
+ !trimmed.startsWith('# ClaudMax') &&
249
+ !trimmed.startsWith('export ANTHROPIC_API_KEY=') &&
250
+ !trimmed.startsWith('export ANTHROPIC_BASE_URL=') &&
251
+ !trimmed.startsWith('export OPUSCODE') &&
252
+ !trimmed.startsWith('export OPUSMAX') &&
253
+ !trimmed.startsWith('# OpusCode') &&
254
+ !trimmed.startsWith('# OpusMax')
255
+ );
256
+ })
257
+ .join('\n');
258
+
240
259
  const envBlock = [
241
260
  '# ClaudMax Configuration',
242
- `export ANTHROPIC_BASE_URL="${API_BASE}/v1/messages"`,
243
261
  `export ANTHROPIC_API_KEY="${apiKey}"`,
244
- '# Alias for quick access',
245
- 'alias claude="claude"',
262
+ `export ANTHROPIC_BASE_URL="${API_BASE}/v1/messages"`,
246
263
  '',
247
264
  ].join('\n');
248
265
 
249
- const appended = appendToFile(profile, envBlock);
250
- if (appended) {
251
- console.log(` ${CHECK} Added environment variables to ${C.magenta(profile)}`);
252
- console.log(` ${INFO} ${C.dim('Run: source ' + profile + ' or restart your terminal')}`);
253
- } else {
254
- console.log(` ${INFO} Environment variables already configured in ${C.magenta(profile)}`);
255
- }
266
+ const newContent = cleaned.trimEnd() + '\n' + envBlock;
267
+ fs.writeFileSync(profile, newContent);
268
+ console.log(` ${CHECK} Updated environment variables in ${C.magenta(profile)}`);
269
+ console.log(` ${INFO} ${C.dim('Run: source ' + profile + ' or restart your terminal')}`);
256
270
 
257
271
  // Set for current process too
258
- process.env.ANTHROPIC_BASE_URL = `${API_BASE}/v1/messages`;
259
272
  process.env.ANTHROPIC_API_KEY = apiKey;
273
+ process.env.ANTHROPIC_BASE_URL = `${API_BASE}/v1/messages`;
260
274
 
261
275
  return profile;
262
276
  }
@@ -270,9 +284,8 @@ function configureClaudeCLI(apiKey) {
270
284
 
271
285
  ensureDir(path.dirname(settingsPath));
272
286
 
273
- // settings.json
274
- const settings = readJson(settingsPath) || {};
275
- deepMerge(settings, {
287
+ // settings.json — start fresh to override OpusCode settings
288
+ const settings = {
276
289
  env: {
277
290
  ANTHROPIC_AUTH_TOKEN: apiKey,
278
291
  ANTHROPIC_BASE_URL: `${API_BASE}/v1/messages`,
@@ -283,7 +296,7 @@ function configureClaudeCLI(apiKey) {
283
296
  ANTHROPIC_DEFAULT_HAIKU_MODEL: 'claude-haiku-4-5-20251001',
284
297
  },
285
298
  hasCompletedOnboarding: true,
286
- });
299
+ };
287
300
  writeJson(settingsPath, settings);
288
301
  console.log(` ${CHECK} Wrote Claude Code settings: ${C.magenta(settingsPath)}`);
289
302
 
@@ -398,7 +411,8 @@ function installMCPServer() {
398
411
  console.log(` ${CHECK} ${C.green(MCP_PKG + ' installed successfully.')}`);
399
412
  return true;
400
413
  } catch (err) {
401
- console.log(` ${WARN} Could not install ${MCP_PKG}: ${C.dim((err.stderr || err.message || '').trim())}`);
414
+ const errMsg = String(err.stderr || err.message || '');
415
+ console.log(` ${WARN} Could not install ${MCP_PKG}: ${C.dim(errMsg.trim())}`);
402
416
  console.log(` ${INFO} Install manually later: ${C.bold('npm install -g ' + MCP_PKG)}`);
403
417
  return false;
404
418
  }
@@ -407,9 +421,9 @@ function installMCPServer() {
407
421
  // ── Banner ────────────────────────────────────────────────────────────────────
408
422
  function printBanner() {
409
423
  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'));
412
- console.log(C.magenta('\u255A' + '\u2550'.repeat(48) + '\u255D'));
424
+ console.log(C.magenta('\u2554' + '\u2550'.repeat(44) + '\u2557'));
425
+ console.log(C.magenta('\u2551') + C.bold(' \u26A1 ClaudMax Setup ') + C.magenta('\u2551'));
426
+ console.log(C.magenta('\u255A' + '\u2550'.repeat(44) + '\u255D'));
413
427
  console.log('');
414
428
  }
415
429
 
@@ -552,30 +566,8 @@ async function main() {
552
566
  }
553
567
  }
554
568
 
555
- if (nodeOk && !gitOk) {
556
- if (!installDep('Git', installGit)) {
557
- console.log(`\n${C.yellow('Git installation failed. You can install it manually.')}`);
558
- } else {
559
- gitOk = isCommandAvailable('git');
560
- }
561
- }
562
-
563
- if (nodeOk && !claudeOk) {
564
- const installClaude = await ask(rl, `\n${WARN} Claude CLI not found. Install it? ${C.bold('[Y/n]: ')}`);
565
- if (!installClaude || installClaude.toLowerCase() === 'y' || installClaude.toLowerCase() === 'yes') {
566
- if (!installDep('Claude CLI', installClaudeCLI)) {
567
- console.log(`\n${C.yellow('Claude CLI installation failed. You can install it with: npm i -g @anthropic-ai/claude-code')}`);
568
- } else {
569
- claudeOk = isCommandAvailable('claude');
570
- }
571
- }
572
- }
573
-
574
- console.log('');
575
-
576
- // ── Step 2: API key prompt ───────────────────────────────────────────────
577
- console.log(C.bold('Step 2: Enter your ClaudMax API key\n'));
578
- console.log('');
569
+ // ── Step 1: API key prompt ───────────────────────────────────────────────
570
+ console.log(C.bold('\nStep 1: Enter your ClaudMax API key\n'));
579
571
 
580
572
  let apiKey = '';
581
573
  while (!apiKey.trim()) {
@@ -587,42 +579,17 @@ async function main() {
587
579
  apiKey = apiKey.trim();
588
580
  console.log('');
589
581
 
590
- // ── Step 3: Verify API key ───────────────────────────────────────────────
591
- console.log(C.bold('Step 3: Verifying API key...\n'));
592
- const result = await verifyConnection(apiKey);
593
-
594
- if (result.ok) {
595
- const data = result.data;
596
- if (result.status === 401) {
597
- console.log(` ${CROSS} ${C.red('Invalid API key. Please check and try again.')}`);
598
- console.log(` ${INFO} ${C.dim(data.error || 'Authentication failed')}`);
599
- rl.close();
600
- process.exit(1);
601
- } else {
602
- console.log(` ${CHECK} ${C.green('API key is valid!')}`);
603
- const tier = (data.tier || 'free').toUpperCase();
604
- const limit = data.requestsLimit?.toLocaleString() || 'N/A';
605
- const tokenLimit = data.tokensLimit ? (data.tokensLimit >= 1e9 ? 'Unlimited' : (data.tokensLimit / 1e6).toFixed(0) + 'M tokens/5h') : 'N/A';
606
- console.log(` ${INFO} Plan: ${C.magenta(tier)} | Requests: ${C.cyan(limit)} | Tokens: ${C.cyan(tokenLimit)}`);
607
- }
608
- } else {
609
- console.log(` ${WARN} ${C.yellow('Could not verify API key (network error). Continuing with setup anyway...')}`);
610
- console.log(` ${INFO} ${C.dim(result.error || 'Connection failed')}`);
611
- }
612
-
613
- // ── Step 4: Configure system ──────────────────────────────────────────────
614
- console.log('');
582
+ // ── Configure system ──────────────────────────────────────────────────────
615
583
  const profile = configureSystem(apiKey);
616
584
 
617
- // ── Step 5: IDE selection ─────────────────────────────────────────────────
618
- console.log('');
619
- console.log(C.bold('Step 5: Select IDEs to configure\n'));
585
+ // ── Step 2: IDE selection ─────────────────────────────────────────────────
586
+ console.log(C.bold('Step 2: Select IDEs to configure\n'));
620
587
 
621
588
  const IDES = [
622
- { id: 1, name: 'Claude Code CLI', shortName: 'Claude Code', configure: configureClaudeCLI },
589
+ { id: 1, name: 'Claude Code (CLI)', shortName: 'Claude Code', configure: configureClaudeCLI },
623
590
  { id: 2, name: 'VS Code (Claude Extension)', shortName: 'VS Code', configure: configureVSCodeClaude },
624
- { id: 3, name: 'Cursor', shortName: 'Cursor', configure: configureCursor },
625
- { id: 4, name: 'Windsurf', shortName: 'Windsurf', configure: configureWindsurf },
591
+ { id: 3, name: 'Cursor', shortName: 'Cursor', configure: configureCursor },
592
+ { id: 4, name: 'Windsurf', shortName: 'Windsurf', configure: configureWindsurf },
626
593
  { id: 5, name: 'Cline (VS Code Extension)', shortName: 'Cline', configure: configureCline },
627
594
  { id: 6, name: 'Roo Code (VS Code Extension)', shortName: 'Roo Code', configure: configureRooCode },
628
595
  ];
@@ -631,7 +598,7 @@ async function main() {
631
598
  console.log(` ${C.purple('[' + ide.id + ']')} ${ide.name}`);
632
599
  }
633
600
  console.log('');
634
- console.log(` ${C.dim("Enter numbers separated by spaces (e.g. 1 3 4), " + C.bold("'a'") + " for all, or press Enter to skip")}`);
601
+ console.log(` ${C.dim("Enter numbers separated by spaces (e.g. 1 3 4), or " + C.bold("'a'") + " for all")}`);
635
602
 
636
603
  const choice = await ask(rl, ` ${C.bold('Your choice')}: `);
637
604
  let selectedIds = [];
@@ -642,42 +609,66 @@ async function main() {
642
609
  selectedIds = choice.trim().split(/[\s,]+/).map(Number).filter((n) => n >= 1 && n <= IDES.length);
643
610
  }
644
611
 
612
+ console.log('');
613
+
614
+ // ── Configure selected IDEs ──────────────────────────────────────────────
645
615
  if (selectedIds.length > 0) {
646
616
  const selectedIDEs = IDES.filter((ide) => selectedIds.includes(ide.id));
647
617
  for (const ide of selectedIDEs) {
648
618
  try {
649
619
  ide.configure(apiKey);
650
620
  } catch (err) {
651
- console.log(` ${CROSS} Failed to configure ${ide.name}: ${err.message}`);
621
+ console.log(` ${CROSS} Failed to configure ${ide.name}: ${String(err && err.message ? err.message : err)}`);
652
622
  }
653
623
  }
654
624
  } else {
655
- console.log(`\n ${WARN} ${C.yellow('No IDEs selected. You can configure them manually later.')}`);
625
+ console.log(` ${WARN} ${C.yellow('No IDEs selected. Skipping IDE configuration.')}`);
656
626
  }
657
627
 
658
- // ── Step 6: Install MCP server ───────────────────────────────────────────
628
+ // ── Install MCP server ───────────────────────────────────────────────────
659
629
  installMCPServer();
660
630
 
631
+ // ── Verify connection ─────────────────────────────────────────────────────
632
+ console.log(`\n${ARROW} ${C.bold('Verifying connection to ClaudMax API...')}`);
633
+ const result = await verifyConnection(apiKey);
634
+
635
+ if (result.ok) {
636
+ const data = result.data;
637
+ if (result.status === 401) {
638
+ console.log(` ${CROSS} ${C.red('Invalid API key. Please check and try again.')}`);
639
+ console.log(` ${INFO} ${C.dim(data.error || 'Authentication failed')}`);
640
+ rl.close();
641
+ process.exit(1);
642
+ } else {
643
+ console.log(` ${CHECK} ${C.green('Connected — API key is valid.')}`);
644
+ const tier = (data.tier || 'free').toUpperCase();
645
+ const limit = data.requestsLimit?.toLocaleString() || 'N/A';
646
+ const tokenLimit = data.tokensLimit ? (data.tokensLimit >= 1e9 ? 'Unlimited' : (data.tokensLimit / 1e6).toFixed(0) + 'M tokens/5h') : 'N/A';
647
+ console.log(` ${INFO} Plan: ${C.magenta(tier)} | Requests: ${C.cyan(limit)} | Tokens: ${C.cyan(tokenLimit)}`);
648
+ }
649
+ } else {
650
+ console.log(` ${WARN} ${C.yellow('Could not verify API key (network error).')}`);
651
+ console.log(` ${INFO} ${C.dim(result.error || 'Connection failed')}`);
652
+ }
653
+
661
654
  // ── Summary ───────────────────────────────────────────────────────────────
662
655
  console.log('');
663
- console.log(C.magenta('\u2554' + '\u2550'.repeat(48) + '\u2557'));
664
- console.log(C.magenta('\u2551') + C.bold(' \u2713 Setup complete! ') + C.magenta('\u2551'));
665
- console.log(C.magenta('\u2551') + C.green(' All systems configured successfully. ') + C.magenta('\u2551'));
666
- console.log(C.magenta('\u255A' + '\u2550'.repeat(48) + '\u255D'));
656
+ console.log(C.magenta('\u2554' + '\u2550'.repeat(44) + '\u2557'));
657
+ console.log(C.magenta('\u2551') + C.bold(' \u2713 Setup complete! ') + C.magenta('\u2551'));
658
+ console.log(C.magenta('\u2551') + C.green(' Restart your IDE(s) to apply. ') + C.magenta('\u2551'));
659
+ console.log(C.magenta('\u255A' + '\u2550'.repeat(44) + '\u255D'));
667
660
  console.log('');
668
661
  console.log(` ${INFO} ${C.bold('Next steps:')}`);
669
- console.log(` 1. ${C.dim('Run:')} ${C.bold('source ' + profile)} ${C.dim('(or restart your terminal)')}`);
662
+ console.log(` 1. ${C.dim('Restart your IDE(s) to apply.')}`);
670
663
  console.log(` 2. ${C.dim('Verify with:')} ${C.bold('claude --version')}`);
671
664
  console.log(` 3. ${C.dim('Start chatting:')} ${C.bold('claude')}`);
672
665
  console.log(` 4. ${C.dim('Check usage:')} ${C.bold('npx claudmax status')}`);
673
666
  console.log('');
674
- console.log(` ${INFO} Config saved at: ${C.magenta(CONFIG_FILE)}`);
675
- console.log('');
676
667
 
677
668
  rl.close();
678
669
  }
679
670
 
680
671
  main().catch((err) => {
681
- console.error('\n' + C.red('\u2717 Fatal error: ' + err.message));
672
+ console.error('\n' + C.red('\u2717 Fatal error: ' + String(err.message || err)));
682
673
  process.exit(1);
683
674
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudmax",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
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": {