claudmax 1.0.15 → 1.0.18
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/bin/claudmax.js +2 -0
- package/claudmax-1.0.16.tgz +0 -0
- package/claudmax-1.0.17.tgz +0 -0
- package/index.js +80 -316
- package/package.json +3 -3
package/bin/claudmax.js
CHANGED
|
@@ -94,6 +94,8 @@ async function cmdConfigure() {
|
|
|
94
94
|
printBanner();
|
|
95
95
|
console.log(`${BOLD}Configure your ClaudMax API key${RESET}`);
|
|
96
96
|
console.log('');
|
|
97
|
+
console.log(`${CYAN}Get Your API Key: https://www.claudmax.pro/support${RESET}`);
|
|
98
|
+
console.log('');
|
|
97
99
|
|
|
98
100
|
const config = getConfig();
|
|
99
101
|
if (config?.apiKey) {
|
|
Binary file
|
|
Binary file
|
package/index.js
CHANGED
|
@@ -14,8 +14,6 @@ const MCP_PKG = 'claudmax-mcp';
|
|
|
14
14
|
const API_BASE = 'https://api.claudmax.pro';
|
|
15
15
|
|
|
16
16
|
const HOME = os.homedir();
|
|
17
|
-
const CONFIG_DIR = path.join(HOME, '.claudmax');
|
|
18
|
-
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
19
17
|
|
|
20
18
|
// ── Color helpers ─────────────────────────────────────────────────────────────
|
|
21
19
|
const C = {
|
|
@@ -28,15 +26,12 @@ const C = {
|
|
|
28
26
|
blue: (s) => `\x1b[34m${s}\x1b[0m`,
|
|
29
27
|
magenta: (s) => `\x1b[35m${s}\x1b[0m`,
|
|
30
28
|
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
31
|
-
white: (s) => `\x1b[37m${s}\x1b[0m`,
|
|
32
|
-
purple: (s) => `\x1b[38;5;141m${s}\x1b[0m`,
|
|
33
29
|
};
|
|
34
30
|
|
|
35
31
|
const CHECK = C.green('\u2713');
|
|
36
32
|
const CROSS = C.red('\u2717');
|
|
37
33
|
const WARN = C.yellow('\u26A0');
|
|
38
34
|
const INFO = C.cyan('\u2139');
|
|
39
|
-
const ARROW = C.magenta('\u25b6');
|
|
40
35
|
|
|
41
36
|
// ── Readline helper ────────────────────────────────────────────────────────────
|
|
42
37
|
function createRL() {
|
|
@@ -75,99 +70,17 @@ function ensureDir(dir) {
|
|
|
75
70
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
76
71
|
}
|
|
77
72
|
|
|
78
|
-
// ──
|
|
79
|
-
function getCommandVersion(cmd) {
|
|
80
|
-
try {
|
|
81
|
-
const v = execSync(cmd + ' --version', { encoding: 'utf8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
82
|
-
return v.trim().split('\n')[0];
|
|
83
|
-
} catch { return null; }
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function isCommandAvailable(cmd) {
|
|
87
|
-
try {
|
|
88
|
-
execSync(cmd + ' --version', { stdio: ['pipe', 'pipe', 'pipe'], timeout: 5000 });
|
|
89
|
-
return true;
|
|
90
|
-
} catch { return false; }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// ── Dependency installers ─────────────────────────────────────────────────────
|
|
94
|
-
function installDep(label, installFn) {
|
|
95
|
-
console.log(`\n${ARROW} ${C.bold('Installing ' + label + '...')}`);
|
|
96
|
-
try {
|
|
97
|
-
installFn();
|
|
98
|
-
console.log(` ${CHECK} ${C.green(label + ' installed successfully.')}`);
|
|
99
|
-
return true;
|
|
100
|
-
} catch (err) {
|
|
101
|
-
console.log(` ${CROSS} ${C.red('Failed to install ' + label + ': ' + (err.message || 'unknown error'))}`);
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function installNode() {
|
|
107
|
-
const platform = process.platform;
|
|
108
|
-
let installCmd;
|
|
109
|
-
|
|
110
|
-
if (platform === 'win32') {
|
|
111
|
-
installCmd = 'winget install OpenJS.NodeJS.LTS';
|
|
112
|
-
} else if (platform === 'darwin') {
|
|
113
|
-
installCmd = 'brew install node';
|
|
114
|
-
} else {
|
|
115
|
-
// Linux
|
|
116
|
-
if (isCommandAvailable('apt-get')) {
|
|
117
|
-
execSync('curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs', { stdio: 'inherit', timeout: 120000 });
|
|
118
|
-
return;
|
|
119
|
-
} else if (isCommandAvailable('yum')) {
|
|
120
|
-
execSync('curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash - && sudo yum install -y nodejs', { stdio: 'inherit', timeout: 120000 });
|
|
121
|
-
return;
|
|
122
|
-
} else if (isCommandAvailable('pacman')) {
|
|
123
|
-
execSync('sudo pacman -S nodejs npm', { stdio: 'inherit', timeout: 120000 });
|
|
124
|
-
return;
|
|
125
|
-
} else {
|
|
126
|
-
throw new Error('No supported package manager found. Please install Node.js manually from https://nodejs.org');
|
|
127
|
-
}
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
execSync(installCmd, { stdio: 'inherit', timeout: 120000 });
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function installGit() {
|
|
135
|
-
const platform = process.platform;
|
|
136
|
-
if (platform === 'win32') {
|
|
137
|
-
execSync('winget install Git.Git', { stdio: 'inherit', timeout: 120000 });
|
|
138
|
-
} else if (platform === 'darwin') {
|
|
139
|
-
execSync('brew install git', { stdio: 'inherit', timeout: 120000 });
|
|
140
|
-
} else {
|
|
141
|
-
if (isCommandAvailable('apt-get')) {
|
|
142
|
-
execSync('sudo apt-get update && sudo apt-get install -y git', { stdio: 'inherit', timeout: 120000 });
|
|
143
|
-
} else if (isCommandAvailable('yum')) {
|
|
144
|
-
execSync('sudo yum install -y git', { stdio: 'inherit', timeout: 120000 });
|
|
145
|
-
} else if (isCommandAvailable('pacman')) {
|
|
146
|
-
execSync('sudo pacman -S git', { stdio: 'inherit', timeout: 120000 });
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function installClaudeCLI() {
|
|
152
|
-
const platform = process.platform;
|
|
153
|
-
if (platform === 'win32') {
|
|
154
|
-
execSync('npm install -g @anthropic-ai/claude-code', { stdio: 'inherit', timeout: 120000 });
|
|
155
|
-
} else {
|
|
156
|
-
execSync('npm install -g @anthropic-ai/claude-code', { stdio: 'inherit', timeout: 120000 });
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// ── HTTPS verification ────────────────────────────────────────────────────────
|
|
73
|
+
// ── API verification ────────────────────────────────────────────────────────
|
|
161
74
|
function verifyConnection(apiKey) {
|
|
162
75
|
return new Promise((resolve) => {
|
|
163
76
|
const options = {
|
|
164
77
|
hostname: API_BASE.replace('https://', ''),
|
|
165
78
|
port: 443,
|
|
166
|
-
path: '/v1/key-status',
|
|
79
|
+
path: '/api/v1/key-status',
|
|
167
80
|
method: 'POST',
|
|
168
81
|
headers: {
|
|
169
82
|
'Content-Type': 'application/json',
|
|
170
|
-
'User-Agent': 'ClaudMax-CLI/1.0.
|
|
83
|
+
'User-Agent': 'ClaudMax-CLI/1.0.18',
|
|
171
84
|
},
|
|
172
85
|
timeout: 15000,
|
|
173
86
|
};
|
|
@@ -178,11 +91,7 @@ function verifyConnection(apiKey) {
|
|
|
178
91
|
res.on('end', () => {
|
|
179
92
|
try {
|
|
180
93
|
const data = JSON.parse(body);
|
|
181
|
-
|
|
182
|
-
resolve({ status: res.statusCode, data, ok: true });
|
|
183
|
-
} else {
|
|
184
|
-
resolve({ status: res.statusCode, error: body, ok: false });
|
|
185
|
-
}
|
|
94
|
+
resolve({ status: res.statusCode, data, ok: true });
|
|
186
95
|
} catch {
|
|
187
96
|
resolve({ status: res.statusCode, error: body, ok: false });
|
|
188
97
|
}
|
|
@@ -197,37 +106,21 @@ function verifyConnection(apiKey) {
|
|
|
197
106
|
});
|
|
198
107
|
}
|
|
199
108
|
|
|
200
|
-
// ──
|
|
201
|
-
function configureSystem(apiKey) {
|
|
202
|
-
console.log(` ${ARROW} ${C.bold('Saving configuration...')}`);
|
|
203
|
-
|
|
204
|
-
// Save config file
|
|
205
|
-
ensureDir(CONFIG_DIR);
|
|
206
|
-
writeJson(CONFIG_FILE, {
|
|
207
|
-
apiKey,
|
|
208
|
-
baseUrl: API_BASE,
|
|
209
|
-
configuredAt: new Date().toISOString(),
|
|
210
|
-
version: '1.0.14',
|
|
211
|
-
});
|
|
212
|
-
console.log(` ${CHECK} Config saved to ${C.magenta('~/.claudmax/config.json')}`);
|
|
213
|
-
console.log(` ${INFO} ${C.dim('Claude Code CLI reads settings.json — no shell profile modification needed.')}`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// ── Claude Code CLI configuration ─────────────────────────────────────────────
|
|
109
|
+
// ── IDE configurators ────────────────────────────────────────────────────────
|
|
217
110
|
function configureClaudeCLI(apiKey) {
|
|
218
|
-
|
|
111
|
+
process.stdout.write(` Configuring Claude Code (CLI)... `);
|
|
219
112
|
|
|
220
113
|
const settingsPath = path.join(HOME, '.claude', 'settings.json');
|
|
221
114
|
const dotClaudePath = path.join(HOME, '.claude.json');
|
|
222
115
|
|
|
223
116
|
ensureDir(path.dirname(settingsPath));
|
|
224
117
|
|
|
225
|
-
// settings.json
|
|
118
|
+
// settings.json — Claude Code reads ANTHROPIC_AUTH_TOKEN and ANTHROPIC_BASE_URL from here
|
|
226
119
|
const settings = readJson(settingsPath) || {};
|
|
227
120
|
deepMerge(settings, {
|
|
228
121
|
env: {
|
|
229
122
|
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
230
|
-
ANTHROPIC_BASE_URL:
|
|
123
|
+
ANTHROPIC_BASE_URL: API_BASE + '/v1',
|
|
231
124
|
ANTHROPIC_MODEL: 'Opus 4.6',
|
|
232
125
|
ANTHROPIC_SMALL_FAST_MODEL: 'Haiku 4.5',
|
|
233
126
|
ANTHROPIC_DEFAULT_SONNET_MODEL: 'Sonnet 4.5',
|
|
@@ -238,9 +131,10 @@ function configureClaudeCLI(apiKey) {
|
|
|
238
131
|
hasCompletedOnboarding: true,
|
|
239
132
|
});
|
|
240
133
|
writeJson(settingsPath, settings);
|
|
241
|
-
|
|
134
|
+
process.stdout.write(`${CHECK} `);
|
|
135
|
+
process.stdout.write(`${C.dim(settingsPath + '\n')}`);
|
|
242
136
|
|
|
243
|
-
// .claude.json
|
|
137
|
+
// .claude.json — MCP servers
|
|
244
138
|
const dotClaude = readJson(dotClaudePath) || {};
|
|
245
139
|
if (!dotClaude.mcpServers) dotClaude.mcpServers = {};
|
|
246
140
|
dotClaude.mcpServers['ClaudMax'] = {
|
|
@@ -252,28 +146,11 @@ function configureClaudeCLI(apiKey) {
|
|
|
252
146
|
},
|
|
253
147
|
};
|
|
254
148
|
writeJson(dotClaudePath, dotClaude);
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// ── IDE configurators ────────────────────────────────────────────────────────
|
|
259
|
-
function getVSCodeSettingsPath() {
|
|
260
|
-
switch (process.platform) {
|
|
261
|
-
case 'win32':
|
|
262
|
-
return path.join(process.env.APPDATA || path.join(HOME, 'AppData', 'Roaming'), 'Code', 'User', 'settings.json');
|
|
263
|
-
case 'darwin':
|
|
264
|
-
return path.join(HOME, 'Library', 'Application Support', 'Code', 'User', 'settings.json');
|
|
265
|
-
default:
|
|
266
|
-
return path.join(HOME, '.config', 'Code', 'User', 'settings.json');
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function configureVSCodeClaude(apiKey) {
|
|
271
|
-
configureClaudeCLI(apiKey);
|
|
272
|
-
console.log(` ${INFO} Claude extension auto-detects Claude Code settings. ${C.dim('Restart VS Code after setup.')}`);
|
|
149
|
+
process.stdout.write(` ${CHECK} ${C.dim(dotClaudePath + '\n')}`);
|
|
273
150
|
}
|
|
274
151
|
|
|
275
152
|
function configureCursor(apiKey) {
|
|
276
|
-
|
|
153
|
+
process.stdout.write(` Configuring Cursor... `);
|
|
277
154
|
const mcpPath = path.join(HOME, '.cursor', 'mcp.json');
|
|
278
155
|
ensureDir(path.dirname(mcpPath));
|
|
279
156
|
const existing = readJson(mcpPath) || {};
|
|
@@ -287,13 +164,11 @@ function configureCursor(apiKey) {
|
|
|
287
164
|
},
|
|
288
165
|
};
|
|
289
166
|
writeJson(mcpPath, existing);
|
|
290
|
-
console.log(
|
|
291
|
-
console.log(` ${INFO} ${C.dim('Add model in Cursor: Settings > Models > Add custom model')}`);
|
|
292
|
-
console.log(` ${C.dim('Anthropic Base URL: https://api.claudmax.pro')}`);
|
|
167
|
+
console.log(`${CHECK} ${C.dim(mcpPath)}`);
|
|
293
168
|
}
|
|
294
169
|
|
|
295
170
|
function configureWindsurf(apiKey) {
|
|
296
|
-
|
|
171
|
+
process.stdout.write(` Configuring Windsurf... `);
|
|
297
172
|
const mcpPath = path.join(HOME, '.windsurf', 'mcp.json');
|
|
298
173
|
ensureDir(path.dirname(mcpPath));
|
|
299
174
|
const existing = readJson(mcpPath) || {};
|
|
@@ -307,48 +182,57 @@ function configureWindsurf(apiKey) {
|
|
|
307
182
|
},
|
|
308
183
|
};
|
|
309
184
|
writeJson(mcpPath, existing);
|
|
310
|
-
console.log(
|
|
311
|
-
console.log(` ${INFO} ${C.dim('Set base URL in Windsurf: Settings > AI Provider')}`);
|
|
312
|
-
console.log(` ${C.dim('https://api.claudmax.pro')}`);
|
|
185
|
+
console.log(`${CHECK} ${C.dim(mcpPath)}`);
|
|
313
186
|
}
|
|
314
187
|
|
|
315
188
|
function configureCline(apiKey) {
|
|
316
|
-
|
|
317
|
-
const settingsPath =
|
|
189
|
+
process.stdout.write(` Configuring Cline... `);
|
|
190
|
+
const settingsPath = path.join(HOME, 'Library', 'Application Support', 'Code', 'User', 'settings.json');
|
|
318
191
|
ensureDir(path.dirname(settingsPath));
|
|
319
192
|
const existing = readJson(settingsPath) || {};
|
|
320
193
|
deepMerge(existing, {
|
|
321
194
|
'cline.apiProvider': 'anthropic',
|
|
322
|
-
'cline.anthropicBaseUrl': API_BASE,
|
|
195
|
+
'cline.anthropicBaseUrl': API_BASE + '/v1',
|
|
323
196
|
'cline.apiKey': apiKey,
|
|
324
197
|
});
|
|
325
198
|
writeJson(settingsPath, existing);
|
|
326
|
-
console.log(
|
|
199
|
+
console.log(`${CHECK} ${C.dim(settingsPath)}`);
|
|
327
200
|
}
|
|
328
201
|
|
|
329
202
|
function configureRooCode(apiKey) {
|
|
330
|
-
|
|
331
|
-
const settingsPath =
|
|
203
|
+
process.stdout.write(` Configuring Roo Code... `);
|
|
204
|
+
const settingsPath = path.join(HOME, 'Library', 'Application Support', 'Code', 'User', 'settings.json');
|
|
332
205
|
ensureDir(path.dirname(settingsPath));
|
|
333
206
|
const existing = readJson(settingsPath) || {};
|
|
334
207
|
deepMerge(existing, {
|
|
335
208
|
'roo-cline.apiProvider': 'anthropic',
|
|
336
|
-
'roo-cline.anthropicBaseUrl': API_BASE,
|
|
209
|
+
'roo-cline.anthropicBaseUrl': API_BASE + '/v1',
|
|
337
210
|
'roo-cline.apiKey': apiKey,
|
|
338
211
|
});
|
|
339
212
|
writeJson(settingsPath, existing);
|
|
340
|
-
console.log(
|
|
213
|
+
console.log(`${CHECK} ${C.dim(settingsPath)}`);
|
|
341
214
|
}
|
|
342
215
|
|
|
343
|
-
|
|
216
|
+
function configureVSCodeClaude(apiKey) {
|
|
217
|
+
configureClaudeCLI(apiKey);
|
|
218
|
+
console.log(` ${INFO} Claude extension auto-detects settings. Restart VS Code after setup.`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ── MCP server install ────────────────────────────────────────────────────────
|
|
344
222
|
function installMCPServer() {
|
|
345
|
-
|
|
223
|
+
process.stdout.write(` Installing ${MCP_PKG} globally... `);
|
|
346
224
|
try {
|
|
347
|
-
execSync('npm install -g ' + MCP_PKG, {
|
|
348
|
-
console.log(
|
|
225
|
+
execSync('npm install -g ' + MCP_PKG, { encoding: 'utf8', timeout: 60000 });
|
|
226
|
+
console.log(`${CHECK}`);
|
|
349
227
|
return true;
|
|
350
228
|
} catch (err) {
|
|
351
|
-
|
|
229
|
+
const msg = err.message || '';
|
|
230
|
+
// Check if already installed
|
|
231
|
+
if (msg.includes('EACCES') || msg.includes('permission')) {
|
|
232
|
+
console.log(`${WARN} Permission denied — try: sudo npm install -g ${MCP_PKG}`);
|
|
233
|
+
} else {
|
|
234
|
+
console.log(`${WARN} npm install failed. Run manually: ${C.bold('npm install -g ' + MCP_PKG)}`);
|
|
235
|
+
}
|
|
352
236
|
return false;
|
|
353
237
|
}
|
|
354
238
|
}
|
|
@@ -356,112 +240,19 @@ function installMCPServer() {
|
|
|
356
240
|
// ── Banner ────────────────────────────────────────────────────────────────────
|
|
357
241
|
function printBanner() {
|
|
358
242
|
console.log('');
|
|
359
|
-
console.log(C.
|
|
360
|
-
console.log(C.
|
|
361
|
-
console.log(C.
|
|
362
|
-
console.log(C.purple(' ║') + C.dim(' One-command setup for Claude API ') + C.purple('║'));
|
|
363
|
-
console.log(C.purple(' ║') + C.bold(' ') + C.purple('║'));
|
|
364
|
-
console.log(C.purple(' ╚════════════════════════════════════════════════════════════════╝'));
|
|
365
|
-
console.log('');
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// ── Step header ────────────────────────────────────────────────────────────────
|
|
369
|
-
function printStep(stepNum, title) {
|
|
370
|
-
console.log('');
|
|
371
|
-
console.log(C.bold(' ┌─────────────────────────────────────────────────────────┐'));
|
|
372
|
-
console.log(C.bold(' │ ') + C.purple('Step ' + stepNum) + C.bold(' ' + title.padEnd(42) + '│'));
|
|
373
|
-
console.log(C.bold(' └─────────────────────────────────────────────────────────┘'));
|
|
374
|
-
console.log('');
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// ── Section box ────────────────────────────────────────────────────────────────
|
|
378
|
-
function printBox(lines) {
|
|
379
|
-
const maxLen = Math.max(...lines.map(l => l.length), 40);
|
|
380
|
-
const top = ' ' + C.dim('\u250C' + '\u2500'.repeat(maxLen + 4) + '\u2510');
|
|
381
|
-
const bot = ' ' + C.dim('\u2514' + '\u2500'.repeat(maxLen + 4) + '\u2518');
|
|
382
|
-
console.log(top);
|
|
383
|
-
lines.forEach(line => {
|
|
384
|
-
const padded = line + ' '.repeat(maxLen - line.length);
|
|
385
|
-
console.log(' ' + C.dim('\u2502') + ' ' + padded + ' ' + C.dim('\u2502'));
|
|
386
|
-
});
|
|
387
|
-
console.log(bot);
|
|
243
|
+
console.log(C.magenta(' ╔════════════════════════════════════════════════════════════╗'));
|
|
244
|
+
console.log(C.magenta(' ║') + C.bold(' ⚡ ClaudMax Setup ⚡ ') + C.magenta('║'));
|
|
245
|
+
console.log(C.magenta(' ╚════════════════════════════════════════════════════════════╝'));
|
|
388
246
|
console.log('');
|
|
389
247
|
}
|
|
390
248
|
|
|
391
249
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
392
250
|
async function main() {
|
|
393
251
|
const rl = createRL();
|
|
394
|
-
|
|
395
252
|
printBanner();
|
|
396
253
|
|
|
397
|
-
// ──
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
let nodeOk = isCommandAvailable('node');
|
|
401
|
-
let gitOk = isCommandAvailable('git');
|
|
402
|
-
let claudeOk = isCommandAvailable('claude');
|
|
403
|
-
|
|
404
|
-
const deps = [
|
|
405
|
-
{ label: 'Node.js', ok: nodeOk, cmd: 'node --version' },
|
|
406
|
-
{ label: 'Git', ok: gitOk, cmd: 'git --version' },
|
|
407
|
-
{ label: 'Claude CLI', ok: claudeOk, cmd: 'claude --version' },
|
|
408
|
-
];
|
|
409
|
-
|
|
410
|
-
for (const dep of deps) {
|
|
411
|
-
if (dep.ok) {
|
|
412
|
-
const version = getCommandVersion(dep.cmd);
|
|
413
|
-
console.log(` ${CHECK} ${C.green(dep.label)} ${C.dim(version || '')}`);
|
|
414
|
-
} else {
|
|
415
|
-
console.log(` ${CROSS} ${C.red(dep.label)} ${C.dim('not found')}`);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
if (!nodeOk) {
|
|
420
|
-
if (!installDep('Node.js', installNode)) {
|
|
421
|
-
console.log(`\n ${CROSS} ${C.red('Node.js installation failed. Please install manually from https://nodejs.org')}`);
|
|
422
|
-
} else {
|
|
423
|
-
nodeOk = isCommandAvailable('node');
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (nodeOk && !gitOk) {
|
|
428
|
-
if (!installDep('Git', installGit)) {
|
|
429
|
-
console.log(`\n ${WARN} ${C.yellow('Git installation failed. You can install it manually.')}`);
|
|
430
|
-
} else {
|
|
431
|
-
gitOk = isCommandAvailable('git');
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if (nodeOk && !claudeOk) {
|
|
436
|
-
const installClaude = await ask(rl, `\n ${WARN} ${C.yellow('Claude CLI not found. Install it?')} ${C.bold('[Y/n]: ')}`);
|
|
437
|
-
if (!installClaude || installClaude.toLowerCase() === 'y' || installClaude.toLowerCase() === 'yes') {
|
|
438
|
-
if (!installDep('Claude CLI', installClaudeCLI)) {
|
|
439
|
-
console.log(`\n ${WARN} ${C.yellow('Claude CLI installation failed. Run: npm i -g @anthropic-ai/claude-code')}`);
|
|
440
|
-
} else {
|
|
441
|
-
claudeOk = isCommandAvailable('claude');
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// ── Step 2: API key prompt ───────────────────────────────────────────────
|
|
447
|
-
printStep(2, 'API Key Configuration');
|
|
448
|
-
|
|
449
|
-
printBox([
|
|
450
|
-
C.bold(' Enter your API key to get started.'),
|
|
451
|
-
'',
|
|
452
|
-
|
|
453
|
-
]);
|
|
454
|
-
|
|
455
|
-
let apiKey = '';
|
|
456
|
-
let attempts = 0;
|
|
457
|
-
const maxAttempts = 3;
|
|
458
|
-
while (!apiKey.trim() && attempts < maxAttempts) {
|
|
459
|
-
if (attempts > 0) {
|
|
460
|
-
console.log(` ${CROSS} ${C.red('API key cannot be empty. Please try again.')}`);
|
|
461
|
-
}
|
|
462
|
-
apiKey = await ask(rl, ` ${C.bold('API Key')}: `);
|
|
463
|
-
attempts++;
|
|
464
|
-
}
|
|
254
|
+
// ── API key ───────────────────────────────────────────────────────────────
|
|
255
|
+
let apiKey = await ask(rl, ` ${C.bold('Enter your ClaudMax API key')}: `);
|
|
465
256
|
apiKey = apiKey.trim();
|
|
466
257
|
|
|
467
258
|
if (!apiKey) {
|
|
@@ -470,46 +261,9 @@ async function main() {
|
|
|
470
261
|
process.exit(1);
|
|
471
262
|
}
|
|
472
263
|
|
|
473
|
-
//
|
|
474
|
-
const maskedKey = apiKey.length > 8
|
|
475
|
-
? apiKey.slice(0, 4) + '\u2022'.repeat(apiKey.length - 8) + apiKey.slice(-4)
|
|
476
|
-
: '\u2022'.repeat(apiKey.length);
|
|
477
|
-
console.log(` ${CHECK} ${C.green('Key received')} ${C.dim(maskedKey)}`);
|
|
478
|
-
|
|
479
|
-
// ── Step 3: Verify API key ───────────────────────────────────────────────
|
|
480
|
-
printStep(3, 'Validating Credentials');
|
|
481
|
-
|
|
482
|
-
process.stdout.write(` ${C.dim('Verifying...')} `);
|
|
483
|
-
const result = await verifyConnection(apiKey);
|
|
484
|
-
|
|
485
|
-
if (result.ok) {
|
|
486
|
-
if (result.status === 401) {
|
|
487
|
-
console.log(`\n ${CROSS} ${C.red('Invalid API key. Please check your key and try again.')}`);
|
|
488
|
-
console.log(` ${INFO} ${C.dim('Get a valid key at: https://claudmax.pro/admin/dashboard')}`);
|
|
489
|
-
rl.close();
|
|
490
|
-
process.exit(1);
|
|
491
|
-
} else {
|
|
492
|
-
const data = result.data;
|
|
493
|
-
const tier = (data.tier || 'free').toUpperCase();
|
|
494
|
-
const limit = data.requestsLimit?.toLocaleString() || 'N/A';
|
|
495
|
-
const tokenLimit = data.tokensLimit ? (data.tokensLimit >= 1e9 ? 'Unlimited' : (data.tokensLimit / 1e6).toFixed(0) + 'M tokens/5h') : 'N/A';
|
|
496
|
-
console.log(`\n ${CHECK} ${C.green('Authentication successful')}`);
|
|
497
|
-
console.log(` ${C.dim('Plan:')} ${C.magenta(tier)} ${C.dim('Requests:')} ${C.cyan(limit + '/5h')} ${C.dim('Tokens:')} ${C.cyan(tokenLimit)}`);
|
|
498
|
-
}
|
|
499
|
-
} else {
|
|
500
|
-
console.log(`\n ${WARN} ${C.yellow('Could not verify (network error). Continuing anyway...')}`);
|
|
501
|
-
console.log(` ${INFO} ${C.dim(result.error || 'Connection failed')}`);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
// ── Step 4: Configure system ──────────────────────────────────────────────
|
|
505
|
-
printStep(4, 'System Configuration');
|
|
506
|
-
configureSystem(apiKey);
|
|
507
|
-
|
|
508
|
-
// ── Step 5: IDE selection ─────────────────────────────────────────────────
|
|
509
|
-
printStep(5, 'IDE Configuration');
|
|
510
|
-
|
|
264
|
+
// ── IDE selection ────────────────────────────────────────────────────────
|
|
511
265
|
const IDES = [
|
|
512
|
-
{ id: 1, name: 'Claude Code CLI', shortName: 'Claude Code', configure: configureClaudeCLI },
|
|
266
|
+
{ id: 1, name: 'Claude Code (CLI)', shortName: 'Claude Code', configure: configureClaudeCLI },
|
|
513
267
|
{ id: 2, name: 'VS Code (Claude Extension)', shortName: 'VS Code', configure: configureVSCodeClaude },
|
|
514
268
|
{ id: 3, name: 'Cursor', shortName: 'Cursor', configure: configureCursor },
|
|
515
269
|
{ id: 4, name: 'Windsurf', shortName: 'Windsurf', configure: configureWindsurf },
|
|
@@ -517,13 +271,14 @@ async function main() {
|
|
|
517
271
|
{ id: 6, name: 'Roo Code (VS Code Extension)', shortName: 'Roo Code', configure: configureRooCode },
|
|
518
272
|
];
|
|
519
273
|
|
|
274
|
+
console.log('');
|
|
520
275
|
for (const ide of IDES) {
|
|
521
|
-
console.log(`
|
|
276
|
+
console.log(` ${C.magenta('[' + ide.id + ']')} ${ide.name}`);
|
|
522
277
|
}
|
|
523
278
|
console.log('');
|
|
524
|
-
console.log(`
|
|
279
|
+
console.log(` ${C.dim("Enter numbers separated by spaces, or 'a' for all:")}`);
|
|
525
280
|
|
|
526
|
-
const choice = await ask(rl, `
|
|
281
|
+
const choice = await ask(rl, ` ${C.bold('Your choice')}: `);
|
|
527
282
|
let selectedIds = [];
|
|
528
283
|
|
|
529
284
|
if (choice.trim().toLowerCase() === 'a') {
|
|
@@ -532,45 +287,54 @@ async function main() {
|
|
|
532
287
|
selectedIds = choice.trim().split(/[\s,]+/).map(Number).filter((n) => n >= 1 && n <= IDES.length);
|
|
533
288
|
}
|
|
534
289
|
|
|
290
|
+
console.log('');
|
|
291
|
+
|
|
292
|
+
// ── Configure IDEs ───────────────────────────────────────────────────────
|
|
535
293
|
if (selectedIds.length > 0) {
|
|
536
294
|
const selectedIDEs = IDES.filter((ide) => selectedIds.includes(ide.id));
|
|
537
295
|
for (const ide of selectedIDEs) {
|
|
538
296
|
try {
|
|
539
297
|
ide.configure(apiKey);
|
|
540
298
|
} catch (err) {
|
|
541
|
-
console.log(`
|
|
299
|
+
console.log(` ${CROSS} ${C.red('Failed to configure')} ${ide.name}: ${err.message}`);
|
|
542
300
|
}
|
|
543
301
|
}
|
|
302
|
+
console.log('');
|
|
544
303
|
} else {
|
|
545
|
-
console.log(`
|
|
304
|
+
console.log(` ${WARN} ${C.yellow('No IDEs selected — skipping configuration.')}`);
|
|
305
|
+
console.log('');
|
|
546
306
|
}
|
|
547
307
|
|
|
548
|
-
// ──
|
|
549
|
-
printStep(6, 'MCP Server Setup');
|
|
308
|
+
// ── Install MCP server ───────────────────────────────────────────────────
|
|
550
309
|
installMCPServer();
|
|
551
|
-
|
|
552
|
-
// ── Summary ───────────────────────────────────────────────────────────────
|
|
553
310
|
console.log('');
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
311
|
+
|
|
312
|
+
// ── Verify API key ───────────────────────────────────────────────────────
|
|
313
|
+
process.stdout.write(` Verifying connection to ClaudMax API... `);
|
|
314
|
+
const result = await verifyConnection(apiKey);
|
|
315
|
+
|
|
316
|
+
if (result.ok && result.status === 200) {
|
|
317
|
+
console.log(`${CHECK} ${C.green('API key is valid.')}`);
|
|
318
|
+
} else if (result.ok && result.status === 401) {
|
|
319
|
+
console.log(`${CROSS} ${C.red('Invalid API key.')}`);
|
|
320
|
+
rl.close();
|
|
321
|
+
process.exit(1);
|
|
322
|
+
} else {
|
|
323
|
+
console.log(`${WARN} ${C.yellow('Could not verify — check your network.')}`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ── Summary ──────────────────────────────────────────────────────────────
|
|
563
327
|
console.log('');
|
|
564
|
-
console.log(
|
|
328
|
+
console.log(C.magenta(' ╔════════════════════════════════════════════════════════════╗'));
|
|
329
|
+
console.log(C.magenta(' ║') + C.green(' ✓ Setup complete! ') + C.magenta('║'));
|
|
330
|
+
console.log(C.magenta(' ║') + C.dim(' Restart your IDE(s) to apply. ') + C.magenta('║'));
|
|
331
|
+
console.log(C.magenta(' ╚════════════════════════════════════════════════════════════╝'));
|
|
565
332
|
console.log('');
|
|
566
333
|
|
|
567
334
|
rl.close();
|
|
568
335
|
}
|
|
569
336
|
|
|
570
337
|
main().catch((err) => {
|
|
571
|
-
|
|
572
|
-
? (String(err.stderr || err.message || err).trim())
|
|
573
|
-
: String(err);
|
|
574
|
-
console.error('\n' + C.red('\u2717 Fatal error: ' + msg));
|
|
338
|
+
console.error('\n' + C.red('\u2717 Fatal error: ' + (err && err.message ? err.message : err)));
|
|
575
339
|
process.exit(1);
|
|
576
340
|
});
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudmax",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
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": {
|
|
7
|
-
"claudmax": "./
|
|
7
|
+
"claudmax": "./index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node ./index.js"
|
|
@@ -30,4 +30,4 @@
|
|
|
30
30
|
"node": ">=16.0.0"
|
|
31
31
|
},
|
|
32
32
|
"preferGlobal": true
|
|
33
|
-
}
|
|
33
|
+
}
|