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.
- package/index.js +178 -124
- 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.
|
|
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
|
|
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
|
-
--
|
|
50
|
-
--
|
|
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
|
-
|
|
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 =
|
|
168
|
+
const backup = readJson(BACKUP_FILE);
|
|
96
169
|
if (!backup) {
|
|
97
|
-
console.log(C.yellow('\u26A0 No backup found.
|
|
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 =
|
|
103
|
-
if (settings.env) {
|
|
104
|
-
delete settings.env[
|
|
105
|
-
delete settings.env
|
|
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
|
-
|
|
115
|
-
console.log(` ${C.
|
|
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 =
|
|
119
|
-
if (dotClaude.mcpServers
|
|
190
|
+
const dotClaude = readJson(dotClaudePath) || {};
|
|
191
|
+
if (dotClaude.mcpServers) {
|
|
120
192
|
delete dotClaude.mcpServers['ClaudMax'];
|
|
121
|
-
|
|
122
|
-
|
|
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.
|
|
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) =>
|
|
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
|
-
|
|
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 —
|
|
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.
|
|
272
|
+
console.log(` ${C.green('\u2713')} Wrote ${settingsPath}`);
|
|
224
273
|
|
|
225
|
-
// .claude.json —
|
|
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:
|
|
287
|
+
ANTHROPIC_BASE_URL: apiBase,
|
|
235
288
|
},
|
|
236
289
|
},
|
|
237
290
|
},
|
|
238
291
|
});
|
|
239
292
|
writeJson(dotClaudePath, dotClaude);
|
|
240
|
-
console.log(` ${C.
|
|
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:
|
|
312
|
+
ANTHROPIC_BASE_URL: apiBase,
|
|
259
313
|
},
|
|
260
314
|
},
|
|
261
315
|
},
|
|
262
316
|
});
|
|
263
317
|
writeJson(mcpPath, existing);
|
|
264
|
-
console.log(` ${C.
|
|
265
|
-
console.log(` ${C.magenta('i')} For API routing, open Cursor Settings > Models > Add OpenAI-compatible model with base URL: ${C.bold(
|
|
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:
|
|
332
|
+
ANTHROPIC_BASE_URL: apiBase,
|
|
279
333
|
},
|
|
280
334
|
},
|
|
281
335
|
},
|
|
282
336
|
});
|
|
283
337
|
writeJson(mcpPath, existing);
|
|
284
|
-
console.log(` ${C.
|
|
285
|
-
console.log(` ${C.magenta('i')} For API routing, open Windsurf Settings > AI Provider and set base URL: ${C.bold(
|
|
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':
|
|
347
|
+
'cline.anthropicBaseUrl': apiBase + '/v1',
|
|
294
348
|
'cline.apiKey': apiKey,
|
|
295
349
|
});
|
|
296
350
|
writeJson(settingsPath, existing);
|
|
297
|
-
console.log(` ${C.
|
|
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':
|
|
359
|
+
'roo-cline.anthropicBaseUrl': apiBase + '/v1',
|
|
306
360
|
'roo-cline.apiKey': apiKey,
|
|
307
361
|
});
|
|
308
362
|
writeJson(settingsPath, existing);
|
|
309
|
-
console.log(` ${C.
|
|
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:
|
|
376
|
+
ANTHROPIC_BASE_URL: apiBase,
|
|
323
377
|
},
|
|
324
378
|
},
|
|
325
379
|
},
|
|
326
380
|
});
|
|
327
381
|
writeJson(mcpPath, existing);
|
|
328
|
-
console.log(` ${C.
|
|
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',
|
|
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)',
|
|
339
|
-
{ id: 7, name: 'Antigravity',
|
|
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
|
|
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.
|
|
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.
|
|
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!
|
|
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