-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.js
More file actions
executable file
·159 lines (133 loc) · 5.09 KB
/
install.js
File metadata and controls
executable file
·159 lines (133 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env node
/**
* Claude Code Router Config - Interactive Installer
* Unified router + configuration package
*
* Configuration by Halil Ertekin
*/
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const inquirer = require('inquirer');
const { execSync } = require('child_process');
const configDir = path.join(process.env.HOME || process.env.USERPROFILE, '.claude-code-router');
const packageDir = __dirname;
const argv = new Set(process.argv.slice(2));
const envIsTrue = (value) => /^(1|true|yes|y)$/i.test(value || '');
const forceOverwrite =
argv.has('--overwrite') ||
argv.has('--force') ||
envIsTrue(process.env.CCR_CONFIG_OVERWRITE);
const nonInteractive =
argv.has('--no-prompt') ||
argv.has('--non-interactive') ||
envIsTrue(process.env.CCR_CONFIG_NO_PROMPT) ||
envIsTrue(process.env.CI);
const canPrompt = Boolean(process.stdin.isTTY) && !nonInteractive;
async function checkRequirements() {
console.log(chalk.blue('📋 Checking requirements...'));
// Check Node version
const nodeVersion = process.version;
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
if (majorVersion < 16) {
console.error(chalk.red(`❌ Node.js ${majorVersion} detected. Node.js 16+ required.`));
process.exit(1);
}
console.log(chalk.green(`✅ Node.js ${nodeVersion}`));
// Check for npm (for optional updates)
try {
execSync('npm --version', { stdio: 'ignore' });
console.log(chalk.green('✅ npm found'));
} catch {
console.log(chalk.yellow('⚠️ npm not found (optional)'));
}
}
async function setupConfig() {
console.log(chalk.blue('⚙️ Setting up configuration...'));
// Ensure config directory exists
await fs.ensureDir(configDir);
// Copy config files
const configFiles = ['config.json', 'intent-router.js', 'smart-intent-router.js'];
for (const file of configFiles) {
const src = path.join(packageDir, 'config', file);
const dest = path.join(configDir, file);
if (await fs.pathExists(dest)) {
if (forceOverwrite) {
console.log(chalk.yellow(`⚠️ Overwriting ${file} (forced)`));
} else if (!canPrompt) {
console.log(
chalk.yellow(
`⚠️ Skipping ${file} (non-interactive). Set CCR_CONFIG_OVERWRITE=1 to overwrite.`
)
);
continue;
} else {
const { overwrite } = await inquirer.prompt([
{
type: 'confirm',
name: 'overwrite',
message: `File ${file} exists. Overwrite?`,
default: false
}
]);
if (!overwrite) {
console.log(chalk.yellow(`⚠️ Skipping ${file}`));
continue;
}
}
}
await fs.copy(src, dest);
console.log(chalk.green(`✅ ${file} copied`));
}
// Copy .env.example if .env doesn't exist
const envFile = path.join(process.env.HOME || process.env.USERPROFILE, '.env');
const envExample = path.join(packageDir, '.env.example');
if (!(await fs.pathExists(envFile))) {
await fs.copy(envExample, envFile);
console.log(chalk.green('✅ .env file created from example'));
} else {
console.log(chalk.yellow('⚠️ .env file already exists'));
}
}
async function showNextSteps() {
console.log(chalk.green('\n🎉 Installation complete!'));
console.log(chalk.blue('\n📝 Next steps:'));
console.log('\n1. Edit your API keys in ~/.env file:');
console.log(chalk.gray(' nano ~/.env'));
console.log('\n2. Add environment variables to your shell (~/.zshrc or ~/.bashrc):');
console.log(chalk.cyan(`
# Claude Code Router (safe .env load)
set -a
source ~/.env
set +a
export ANTHROPIC_BASE_URL="http://127.0.0.1:3456"
export NO_PROXY="127.0.0.1"
`));
console.log('\n3. Reload your shell:');
console.log(chalk.gray(' source ~/.zshrc'));
console.log('\n4. Start the router:');
console.log(chalk.gray(' ccr start'));
console.log(chalk.gray(' ccr code'));
console.log(chalk.blue('\n📚 Documentation:'));
console.log(chalk.gray(' https://github.com/halilertekin/claude-code-router-config'));
console.log(chalk.blue('\n🔑 Get API keys:'));
console.log(chalk.gray(' OpenAI: https://platform.openai.com/api-keys'));
console.log(chalk.gray(' Anthropic: https://console.anthropic.com/settings/keys'));
console.log(chalk.gray(' Gemini: https://aistudio.google.com/apikey'));
console.log(chalk.gray(' Qwen: https://dashscope.console.aliyun.com/apiKey'));
console.log(chalk.gray(' GLM: https://open.bigmodel.cn/usercenter/apikeys'));
console.log(chalk.gray(' OpenRouter: https://openrouter.ai/keys'));
console.log(chalk.gray(' Copilot: https://github.com/settings/tokens'));
console.log(chalk.yellow('\n⭐ Info:'));
console.log(chalk.gray(' Unified router + config package'));
}
async function main() {
console.log(chalk.cyan.bold('\n🚀 Claude Code Router Config Installer\n'));
await checkRequirements();
await setupConfig();
await showNextSteps();
}
if (require.main === module) {
main().catch(console.error);
}
module.exports = { checkRequirements, setupConfig };