claudmax 3.4.2 → 3.4.3

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 +178 -124
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -13,6 +13,7 @@ const C = {
13
13
  bold: (s) => `\x1b[1m${s}\x1b[0m`,
14
14
  yellow: (s) => `\x1b[33m${s}\x1b[0m`,
15
15
  red: (s) => `\x1b[31m${s}\x1b[0m`,
16
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
16
17
  reset: '\x1b[0m',
17
18
  };
18
19
 
@@ -25,7 +26,81 @@ const BANNER_SIDE = C.magenta('\u2551');
25
26
  const MCP_PKG = 'claudmax-mcp';
26
27
  const API_BASE = 'https://api.claudmax.pro';
27
28
  const HOME = os.homedir();
28
- const VERSION = '3.4.1';
29
+ const VERSION = '3.4.3';
30
+
31
+ // ── Helpers ────────────────────────────────────────────────────────────────────
32
+ function readJson(filePath) {
33
+ try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
34
+ catch { return null; }
35
+ }
36
+
37
+ function writeJson(filePath, data) {
38
+ const dir = path.dirname(filePath);
39
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
40
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
41
+ }
42
+
43
+ function deepMerge(target, source) {
44
+ for (const key of Object.keys(source)) {
45
+ if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
46
+ if (!target[key]) target[key] = {};
47
+ deepMerge(target[key], source[key]);
48
+ } else {
49
+ target[key] = source[key];
50
+ }
51
+ }
52
+ return target;
53
+ }
54
+
55
+ function removeKeys(obj, keys) {
56
+ for (const k of keys) delete obj[k];
57
+ }
58
+
59
+ function getVSCodeSettingsPath() {
60
+ switch (process.platform) {
61
+ case 'win32':
62
+ return path.join(process.env.APPDATA || path.join(HOME, 'AppData', 'Roaming'), 'Code', 'User', 'settings.json');
63
+ case 'darwin':
64
+ return path.join(HOME, 'Library', 'Application Support', 'Code', 'User', 'settings.json');
65
+ default:
66
+ return path.join(HOME, '.config', 'Code', 'User', 'settings.json');
67
+ }
68
+ }
69
+
70
+ // ── Clean all proxy artifacts ─────────────────────────────────────────────────
71
+ const ALL_PROXY_KEYS = [
72
+ 'ANTHROPIC_AUTH_TOKEN', 'ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL',
73
+ 'ANTHROPIC_MODEL', 'ANTHROPIC_SMALL_FAST_MODEL',
74
+ 'ANTHROPIC_DEFAULT_SONNET_MODEL', 'ANTHROPIC_DEFAULT_OPUS_MODEL',
75
+ 'ANTHROPIC_DEFAULT_HAIKU_MODEL', 'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC',
76
+ 'OPUSMAX_API_KEY', 'OPUSMAX_URL',
77
+ ];
78
+
79
+ function cleanAllProxyConfig() {
80
+ const settingsPath = path.join(HOME, '.claude', 'settings.json');
81
+ const dotClaudePath = path.join(HOME, '.claude.json');
82
+ const backupFile = path.join(HOME, '.claudmax', '.backup.json');
83
+
84
+ // Clean settings.json env
85
+ const settings = readJson(settingsPath);
86
+ if (settings && settings.env) {
87
+ removeKeys(settings.env, ALL_PROXY_KEYS);
88
+ if (Object.keys(settings.env).length === 0) delete settings.env;
89
+ writeJson(settingsPath, settings);
90
+ }
91
+
92
+ // Clean .claude.json mcpServers
93
+ const dotClaude = readJson(dotClaudePath);
94
+ if (dotClaude && dotClaude.mcpServers) {
95
+ delete dotClaude.mcpServers['ClaudMax'];
96
+ delete dotClaude.mcpServers['OpusMax'];
97
+ if (Object.keys(dotClaude.mcpServers).length === 0) delete dotClaude.mcpServers;
98
+ writeJson(dotClaudePath, dotClaude);
99
+ }
100
+
101
+ // Delete backup (may have OpusMax keys)
102
+ try { fs.unlinkSync(backupFile); } catch { /* ignore */ }
103
+ }
29
104
 
30
105
  // ── Args ──────────────────────────────────────────────────────────────────────
31
106
  const args = process.argv.slice(2);
@@ -36,7 +111,7 @@ for (let i = 0; i < args.length; i++) {
36
111
  }
37
112
  }
38
113
 
39
- // ── Help / Version / Uninstall ─────────────────────────────────────────────────
114
+ // ── Help / Version ──────────────────────────────────────────────────────────────
40
115
  if (args.includes('--help') || args.includes('-h')) {
41
116
  console.log(`
42
117
  ${BANNER_TOP}
@@ -46,11 +121,13 @@ ${BANNER_BOTTOM}
46
121
  Usage: npx claudmax
47
122
 
48
123
  Options:
49
- --uninstall, -u Restore previous config and remove ClaudMax entry
50
- --version, -v Show version number
124
+ --reset, -r Clean all ClaudMax + OpusMax proxy config (before reinstalling)
125
+ --uninstall, -u Remove ClaudMax and restore previous config
126
+ --version, -v Show version number
51
127
 
52
128
  Examples:
53
129
  npx claudmax Interactive setup
130
+ npx claudmax --reset && npx claudmax Full clean reinstall
54
131
  npx claudmax --uninstall Remove ClaudMax, restore previous config
55
132
  `);
56
133
  process.exit(0);
@@ -61,30 +138,26 @@ if (args.includes('--version') || args.includes('-v')) {
61
138
  process.exit(0);
62
139
  }
63
140
 
141
+ // ── Reset: clean all proxy config ───────────────────────────────────────────────
142
+ if (flags.reset || flags.r) {
143
+ console.log('');
144
+ console.log(BANNER_TOP);
145
+ console.log(BANNER_SIDE + C.bold(' \u2726 ClaudMax Reset ') + BANNER_SIDE);
146
+ console.log(BANNER_BOTTOM);
147
+ console.log('');
148
+ cleanAllProxyConfig();
149
+ console.log(` ${C.green('\u2713')} Cleaned all proxy config from ~/.claude/settings.json`);
150
+ console.log(` ${C.green('\u2713')} Removed ClaudMax + OpusMax from ~/.claude.json mcpServers`);
151
+ console.log(` ${C.green('\u2713')} Deleted ~/.claudmax backup`);
152
+ console.log('');
153
+ console.log(` ${C.yellow('\u26A0')} Restart your terminal before running ${C.bold('npx claudmax')} again.`);
154
+ console.log('');
155
+ process.exit(0);
156
+ }
157
+
158
+ // ── Uninstall ─────────────────────────────────────────────────────────────────
64
159
  if (flags.uninstall || flags.u) {
65
- // Restore from backup
66
- const BACKUP_DIR = path.join(HOME, '.claudmax');
67
- const BACKUP_FILE = path.join(BACKUP_DIR, '.backup.json');
68
- function readJsonSafe(filePath) {
69
- try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
70
- catch { return null; }
71
- }
72
- function writeJsonF(filePath, data) {
73
- const dir = path.dirname(filePath);
74
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
75
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
76
- }
77
- function deepMerge(target, source) {
78
- for (const key of Object.keys(source)) {
79
- if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
80
- if (!target[key]) target[key] = {};
81
- deepMerge(target[key], source[key]);
82
- } else {
83
- target[key] = source[key];
84
- }
85
- }
86
- return target;
87
- }
160
+ const BACKUP_FILE = path.join(HOME, '.claudmax', '.backup.json');
88
161
 
89
162
  console.log('');
90
163
  console.log(BANNER_TOP);
@@ -92,86 +165,52 @@ if (flags.uninstall || flags.u) {
92
165
  console.log(BANNER_BOTTOM);
93
166
  console.log('');
94
167
 
95
- const backup = readJsonSafe(BACKUP_FILE);
168
+ const backup = readJson(BACKUP_FILE);
96
169
  if (!backup) {
97
- console.log(C.yellow('\u26A0 No backup found. Nothing to restore.'));
170
+ console.log(C.yellow('\u26A0 No backup found. Performing clean removal...'));
171
+ cleanAllProxyConfig();
172
+ console.log(` ${C.green('\u2713')} Proxy config removed.`);
173
+ console.log('');
174
+ console.log(` ${C.green('\u2713')} ClaudMax uninstalled.`);
175
+ console.log('');
98
176
  process.exit(0);
99
177
  }
100
178
 
179
+ // Restore from backup (only the keys ClaudMax originally owned)
101
180
  const settingsPath = path.join(HOME, '.claude', 'settings.json');
102
- const settings = readJsonSafe(settingsPath) || {};
103
- if (settings.env) {
104
- delete settings.env['ANTHROPIC_AUTH_TOKEN'];
105
- delete settings.env['ANTHROPIC_BASE_URL'];
106
- delete settings.env['ANTHROPIC_MODEL'];
107
- delete settings.env['ANTHROPIC_SMALL_FAST_MODEL'];
108
- delete settings.env['ANTHROPIC_DEFAULT_SONNET_MODEL'];
109
- delete settings.env['ANTHROPIC_DEFAULT_OPUS_MODEL'];
110
- delete settings.env['ANTHROPIC_DEFAULT_HAIKU_MODEL'];
111
- delete settings.env['CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC'];
112
- if (Object.keys(settings.env).length === 0) delete settings.env;
181
+ const settings = readJson(settingsPath) || {};
182
+ if (backup.settings && backup.settings.env) {
183
+ for (const k of ALL_PROXY_KEYS) delete settings.env?.[k];
184
+ if (settings.env && Object.keys(settings.env).length === 0) delete settings.env;
113
185
  }
114
- writeJsonF(settingsPath, settings);
115
- console.log(` ${C.magenta('\u2713')} Restored ${settingsPath}`);
186
+ writeJson(settingsPath, settings);
187
+ console.log(` ${C.green('\u2713')} Restored ${settingsPath}`);
116
188
 
117
189
  const dotClaudePath = path.join(HOME, '.claude.json');
118
- const dotClaude = readJsonSafe(dotClaudePath) || {};
119
- if (dotClaude.mcpServers && dotClaude.mcpServers['ClaudMax']) {
190
+ const dotClaude = readJson(dotClaudePath) || {};
191
+ if (dotClaude.mcpServers) {
120
192
  delete dotClaude.mcpServers['ClaudMax'];
121
- writeJsonF(dotClaudePath, dotClaude);
122
- console.log(` ${C.magenta('\u2713')} Removed ClaudMax from ${dotClaudePath}`);
193
+ if (Object.keys(dotClaude.mcpServers).length === 0) delete dotClaude.mcpServers;
194
+ writeJson(dotClaudePath, dotClaude);
195
+ console.log(` ${C.green('\u2713')} Removed ClaudMax from ${dotClaudePath}`);
123
196
  }
124
197
 
125
198
  try { fs.unlinkSync(BACKUP_FILE); } catch { /* ignore */ }
126
199
  console.log('');
127
- console.log(` ${C.magenta('\u2713')} ClaudMax uninstalled. Previous config restored.`);
200
+ console.log(` ${C.green('\u2713')} ClaudMax uninstalled. Previous config restored.`);
128
201
  console.log('');
129
202
  process.exit(0);
130
203
  }
131
204
 
132
- // ── JSON helpers ──────────────────────────────────────────────────────────────
133
- function readJson(filePath) {
134
- try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
135
- catch { return {}; }
136
- }
137
-
138
- function writeJson(filePath, data) {
139
- const dir = path.dirname(filePath);
140
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
141
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
142
- }
143
-
144
- function deepMerge(target, source) {
145
- for (const key of Object.keys(source)) {
146
- if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
147
- if (!target[key]) target[key] = {};
148
- deepMerge(target[key], source[key]);
149
- } else {
150
- target[key] = source[key];
151
- }
152
- }
153
- return target;
154
- }
155
-
156
- // ── Platform paths ─────────────────────────────────────────────────────────────
157
- function getVSCodeSettingsPath() {
158
- switch (process.platform) {
159
- case 'win32':
160
- return path.join(process.env.APPDATA || path.join(HOME, 'AppData', 'Roaming'), 'Code', 'User', 'settings.json');
161
- case 'darwin':
162
- return path.join(HOME, 'Library', 'Application Support', 'Code', 'User', 'settings.json');
163
- default:
164
- return path.join(HOME, '.config', 'Code', 'User', 'settings.json');
165
- }
166
- }
167
-
168
205
  // ── Readline helper ────────────────────────────────────────────────────────────
169
206
  function createRL() {
170
207
  return readline.createInterface({ input: process.stdin, output: process.stdout });
171
208
  }
172
209
 
173
210
  function ask(rl, question) {
174
- return new Promise((resolve) => rl.question(question, resolve));
211
+ return new Promise((resolve) => {
212
+ rl.question(question, (answer) => resolve(answer));
213
+ });
175
214
  }
176
215
 
177
216
  // ── HTTPS verification ─────────────────────────────────────────────────────────
@@ -200,16 +239,26 @@ function verifyConnection(apiKey) {
200
239
  }
201
240
 
202
241
  // ── IDE configurators ──────────────────────────────────────────────────────────
203
- function configureClaudeCodeCLI(apiKey) {
242
+ // Clean up conflicting proxy keys BEFORE writing new config
243
+ function preCleanForClaudeCodeCLI() {
244
+ const settingsPath = path.join(HOME, '.claude', 'settings.json');
245
+ const settings = readJson(settingsPath);
246
+ if (settings && settings.env) {
247
+ removeKeys(settings.env, ALL_PROXY_KEYS);
248
+ if (Object.keys(settings.env).length === 0) delete settings.env;
249
+ writeJson(settingsPath, settings);
250
+ }
251
+ }
252
+
253
+ function configureClaudeCodeCLI(apiKey, apiBase) {
204
254
  const settingsPath = path.join(HOME, '.claude', 'settings.json');
205
255
  const dotClaudePath = path.join(HOME, '.claude.json');
206
256
 
207
- // settings.json — deep merge only OpusMax's keys, preserve all others
257
+ // settings.json — set model hints only (no auth keys, avoiding conflicts)
258
+ preCleanForClaudeCodeCLI();
208
259
  const settings = readJson(settingsPath);
209
260
  deepMerge(settings, {
210
261
  env: {
211
- ANTHROPIC_AUTH_TOKEN: apiKey,
212
- ANTHROPIC_BASE_URL: API_BASE,
213
262
  ANTHROPIC_MODEL: 'Opus 4.6',
214
263
  ANTHROPIC_SMALL_FAST_MODEL: 'Haiku 4.5',
215
264
  ANTHROPIC_DEFAULT_SONNET_MODEL: 'Sonnet 4.5',
@@ -220,10 +269,14 @@ function configureClaudeCodeCLI(apiKey) {
220
269
  hasCompletedOnboarding: true,
221
270
  });
222
271
  writeJson(settingsPath, settings);
223
- console.log(` ${C.magenta('\u2713')} Wrote ${C.magenta(settingsPath)}`);
272
+ console.log(` ${C.green('\u2713')} Wrote ${settingsPath}`);
224
273
 
225
- // .claude.json — deep merge only ClaudMax MCP entry, preserve all others
274
+ // .claude.json — MCP server for routing (cleans OpusMax first)
226
275
  const dotClaude = readJson(dotClaudePath);
276
+ // Remove OpusMax to avoid auth conflicts
277
+ if (dotClaude.mcpServers) {
278
+ delete dotClaude.mcpServers['OpusMax'];
279
+ }
227
280
  deepMerge(dotClaude, {
228
281
  mcpServers: {
229
282
  ClaudMax: {
@@ -231,23 +284,24 @@ function configureClaudeCodeCLI(apiKey) {
231
284
  args: ['-y', MCP_PKG],
232
285
  env: {
233
286
  ANTHROPIC_API_KEY: apiKey,
234
- ANTHROPIC_BASE_URL: API_BASE,
287
+ ANTHROPIC_BASE_URL: apiBase,
235
288
  },
236
289
  },
237
290
  },
238
291
  });
239
292
  writeJson(dotClaudePath, dotClaude);
240
- console.log(` ${C.magenta('\u2713')} Wrote ${C.magenta(dotClaudePath)}`);
293
+ console.log(` ${C.green('\u2713')} Wrote ${dotClaudePath}`);
294
+ console.log(` ${C.magenta('i')} Removed OpusMax MCP entry to avoid auth conflict.`);
241
295
  }
242
296
 
243
- function configureVSCodeClaude(apiKey) {
244
- configureClaudeCodeCLI(apiKey);
297
+ function configureVSCodeClaude(apiKey, apiBase) {
298
+ configureClaudeCodeCLI(apiKey, apiBase);
245
299
  console.log(` ${C.magenta('i')} VS Code Claude extension uses the same config as Claude Code CLI.`);
246
300
  }
247
301
 
248
- function configureCursor(apiKey) {
302
+ function configureCursor(apiKey, apiBase) {
249
303
  const mcpPath = path.join(HOME, '.cursor', 'mcp.json');
250
- const existing = readJson(mcpPath);
304
+ const existing = readJson(mcpPath) || {};
251
305
  deepMerge(existing, {
252
306
  mcpServers: {
253
307
  ClaudMax: {
@@ -255,19 +309,19 @@ function configureCursor(apiKey) {
255
309
  args: ['-y', MCP_PKG],
256
310
  env: {
257
311
  ANTHROPIC_API_KEY: apiKey,
258
- ANTHROPIC_BASE_URL: API_BASE,
312
+ ANTHROPIC_BASE_URL: apiBase,
259
313
  },
260
314
  },
261
315
  },
262
316
  });
263
317
  writeJson(mcpPath, existing);
264
- console.log(` ${C.magenta('\u2713')} Wrote ${C.magenta(mcpPath)}`);
265
- console.log(` ${C.magenta('i')} For API routing, open Cursor Settings > Models > Add OpenAI-compatible model with base URL: ${C.bold(API_BASE + '/v1')}`);
318
+ console.log(` ${C.green('\u2713')} Wrote ${mcpPath}`);
319
+ console.log(` ${C.magenta('i')} For API routing, open Cursor Settings > Models > Add OpenAI-compatible model with base URL: ${C.bold(apiBase + '/v1')}`);
266
320
  }
267
321
 
268
- function configureWindsurf(apiKey) {
322
+ function configureWindsurf(apiKey, apiBase) {
269
323
  const mcpPath = path.join(HOME, '.windsurf', 'mcp.json');
270
- const existing = readJson(mcpPath);
324
+ const existing = readJson(mcpPath) || {};
271
325
  deepMerge(existing, {
272
326
  mcpServers: {
273
327
  ClaudMax: {
@@ -275,43 +329,43 @@ function configureWindsurf(apiKey) {
275
329
  args: ['-y', MCP_PKG],
276
330
  env: {
277
331
  ANTHROPIC_API_KEY: apiKey,
278
- ANTHROPIC_BASE_URL: API_BASE,
332
+ ANTHROPIC_BASE_URL: apiBase,
279
333
  },
280
334
  },
281
335
  },
282
336
  });
283
337
  writeJson(mcpPath, existing);
284
- console.log(` ${C.magenta('\u2713')} Wrote ${C.magenta(mcpPath)}`);
285
- console.log(` ${C.magenta('i')} For API routing, open Windsurf Settings > AI Provider and set base URL: ${C.bold(API_BASE + '/v1')}`);
338
+ console.log(` ${C.green('\u2713')} Wrote ${mcpPath}`);
339
+ console.log(` ${C.magenta('i')} For API routing, open Windsurf Settings > AI Provider and set base URL: ${C.bold(apiBase + '/v1')}`);
286
340
  }
287
341
 
288
- function configureCline(apiKey) {
342
+ function configureCline(apiKey, apiBase) {
289
343
  const settingsPath = getVSCodeSettingsPath();
290
- const existing = readJson(settingsPath);
344
+ const existing = readJson(settingsPath) || {};
291
345
  deepMerge(existing, {
292
346
  'cline.apiProvider': 'anthropic',
293
- 'cline.anthropicBaseUrl': API_BASE + '/v1',
347
+ 'cline.anthropicBaseUrl': apiBase + '/v1',
294
348
  'cline.apiKey': apiKey,
295
349
  });
296
350
  writeJson(settingsPath, existing);
297
- console.log(` ${C.magenta('\u2713')} Wrote ${C.magenta(settingsPath)}`);
351
+ console.log(` ${C.green('\u2713')} Wrote ${settingsPath}`);
298
352
  }
299
353
 
300
- function configureRooCode(apiKey) {
354
+ function configureRooCode(apiKey, apiBase) {
301
355
  const settingsPath = getVSCodeSettingsPath();
302
- const existing = readJson(settingsPath);
356
+ const existing = readJson(settingsPath) || {};
303
357
  deepMerge(existing, {
304
358
  'roo-cline.apiProvider': 'anthropic',
305
- 'roo-cline.anthropicBaseUrl': API_BASE + '/v1',
359
+ 'roo-cline.anthropicBaseUrl': apiBase + '/v1',
306
360
  'roo-cline.apiKey': apiKey,
307
361
  });
308
362
  writeJson(settingsPath, existing);
309
- console.log(` ${C.magenta('\u2713')} Wrote ${C.magenta(settingsPath)}`);
363
+ console.log(` ${C.green('\u2713')} Wrote ${settingsPath}`);
310
364
  }
311
365
 
312
- function configureAntigravity(apiKey) {
366
+ function configureAntigravity(apiKey, apiBase) {
313
367
  const mcpPath = path.join(HOME, '.config', 'antigravity', 'mcp.json');
314
- const existing = readJson(mcpPath);
368
+ const existing = readJson(mcpPath) || {};
315
369
  deepMerge(existing, {
316
370
  mcpServers: {
317
371
  ClaudMax: {
@@ -319,13 +373,13 @@ function configureAntigravity(apiKey) {
319
373
  args: ['-y', MCP_PKG],
320
374
  env: {
321
375
  ANTHROPIC_API_KEY: apiKey,
322
- ANTHROPIC_BASE_URL: API_BASE,
376
+ ANTHROPIC_BASE_URL: apiBase,
323
377
  },
324
378
  },
325
379
  },
326
380
  });
327
381
  writeJson(mcpPath, existing);
328
- console.log(` ${C.magenta('\u2713')} Wrote ${C.magenta(mcpPath)}`);
382
+ console.log(` ${C.green('\u2713')} Wrote ${mcpPath}`);
329
383
  }
330
384
 
331
385
  // ── IDE registry ───────────────────────────────────────────────────────────────
@@ -333,10 +387,10 @@ const IDES = [
333
387
  { id: 1, name: 'Claude Code (CLI)', configure: configureClaudeCodeCLI },
334
388
  { id: 2, name: 'VS Code (Claude Extension)', configure: configureVSCodeClaude },
335
389
  { id: 3, name: 'Cursor', configure: configureCursor },
336
- { id: 4, name: 'Windsurf', configure: configureWindsurf },
390
+ { id: 4, name: 'Windsurf', configure: configureWindsurf },
337
391
  { id: 5, name: 'Cline (VS Code Extension)', configure: configureCline },
338
- { id: 6, name: 'Roo Code (VS Code Extension)', configure: configureRooCode },
339
- { id: 7, name: 'Antigravity', configure: configureAntigravity },
392
+ { id: 6, name: 'Roo Code (VS Code Extension)', configure: configureRooCode },
393
+ { id: 7, name: 'Antigravity', configure: configureAntigravity },
340
394
  ];
341
395
 
342
396
  // ── Main ───────────────────────────────────────────────────────────────────────
@@ -350,7 +404,7 @@ async function main() {
350
404
  console.log(BANNER_BOTTOM);
351
405
  console.log('');
352
406
 
353
- // 2. API key prompt (always interactive — no flags)
407
+ // 2. API key prompt
354
408
  let apiKey = '';
355
409
  while (!apiKey.trim()) {
356
410
  apiKey = await ask(rl, C.bold('Enter your ClaudMax API key: '));
@@ -394,7 +448,7 @@ async function main() {
394
448
  for (const ide of selectedIDEs) {
395
449
  console.log(C.bold(`\nConfiguring ${C.magenta(ide.name)}...`));
396
450
  try {
397
- ide.configure(apiKey);
451
+ ide.configure(apiKey, API_BASE);
398
452
  } catch (err) {
399
453
  console.log(` ${C.red('\u2717')} Failed to configure ${ide.name}: ${err.message}`);
400
454
  }
@@ -410,7 +464,7 @@ async function main() {
410
464
  stdio: ['pipe', 'pipe', 'pipe'],
411
465
  timeout: 60000,
412
466
  });
413
- console.log(` ${C.magenta('\u2713')} claudmax-mcp installed successfully.`);
467
+ console.log(` ${C.green('\u2713')} claudmax-mcp installed successfully.`);
414
468
  } catch (err) {
415
469
  console.log(` ${C.yellow('\u26A0')} Could not install claudmax-mcp globally: ${(err.stderr || err.message || '').trim()}`);
416
470
  console.log(` ${C.yellow('\u26A0')} You can install it manually later: ${C.bold('npm i -g claudmax-mcp')}`);
@@ -423,7 +477,7 @@ async function main() {
423
477
  const result = await verifyConnection(apiKey);
424
478
 
425
479
  if (result.status === 200) {
426
- console.log(` ${C.magenta('\u2713')} Connected \u2014 API key is valid.`);
480
+ console.log(` ${C.green('\u2713')} Connected \u2014 API key is valid.`);
427
481
  } else if (result.status > 0) {
428
482
  console.log(` ${C.yellow('\u26A0')} HTTP ${result.status} \u2014 the server responded, but the key may be invalid.`);
429
483
  } else {
@@ -433,7 +487,7 @@ async function main() {
433
487
  // 7. Summary
434
488
  console.log('');
435
489
  console.log(BANNER_TOP);
436
- console.log(BANNER_SIDE + C.bold(' \u2713 Setup complete! ') + BANNER_SIDE);
490
+ console.log(BANNER_SIDE + C.bold(' \u2713 Setup complete! ') + BANNER_SIDE);
437
491
  console.log(BANNER_SIDE + ' Restart your IDE(s) to apply. ' + BANNER_SIDE);
438
492
  console.log(BANNER_BOTTOM);
439
493
  console.log('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudmax",
3
- "version": "3.4.2",
3
+ "version": "3.4.3",
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": {