claude-code-model-switch 2.1.0 → 2.2.1
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/README.md +13 -2
- package/README_CN.md +13 -2
- package/example-config.json +6 -3
- package/index.js +113 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ A CLI tool for switching between different AI models in Claude Code.
|
|
|
7
7
|
- Launch Claude Code with a preconfigured model in one command (yolo mode)
|
|
8
8
|
- Support for multiple pre-configured model environments
|
|
9
9
|
- `start` injects model config as env vars; `config` persists to settings.json
|
|
10
|
+
- `shared` env vars apply to all models (model-specific values override shared)
|
|
10
11
|
- Automatic handling of model-related environment variables and defaults
|
|
11
12
|
- Simple command-line interface
|
|
12
13
|
- `unset` removes model-related entries from settings.json
|
|
@@ -39,6 +40,11 @@ ccms config-path
|
|
|
39
40
|
|
|
40
41
|
# Remove model-related configuration from settings.json
|
|
41
42
|
ccms unset
|
|
43
|
+
|
|
44
|
+
# Manage shared environment variables for all models
|
|
45
|
+
ccms shared list
|
|
46
|
+
ccms shared set API_TIMEOUT_MS 600000
|
|
47
|
+
ccms shared unset API_TIMEOUT_MS
|
|
42
48
|
```
|
|
43
49
|
|
|
44
50
|
### Model Configuration
|
|
@@ -47,6 +53,10 @@ Edit the configuration file `~/.claude-code-model-switch/settings.json`:
|
|
|
47
53
|
|
|
48
54
|
```json
|
|
49
55
|
{
|
|
56
|
+
"shared": {
|
|
57
|
+
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
58
|
+
"API_TIMEOUT_MS": "600000"
|
|
59
|
+
},
|
|
50
60
|
"models": {
|
|
51
61
|
"deepseek-chat": {
|
|
52
62
|
"ANTHROPIC_AUTH_TOKEN": "sk-your-token-here",
|
|
@@ -91,11 +101,12 @@ Edit the configuration file `~/.claude-code-model-switch/settings.json`:
|
|
|
91
101
|
|
|
92
102
|
1. **start command**: `ccms start <model>` injects model config as environment variables and launches `claude` with `--dangerously-skip-permissions` (yolo mode)
|
|
93
103
|
2. **config command**: `ccms config <model>` writes model config to `~/.claude/settings.json` for persistent configuration
|
|
94
|
-
3. **
|
|
104
|
+
3. **shared env vars**: variables in `shared` apply to every model; model-specific values override shared ones
|
|
105
|
+
4. **Default Values**:
|
|
95
106
|
- `CLAUDE_CODE_MAX_OUTPUT_TOKENS` defaults to `8192`
|
|
96
107
|
- `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` defaults to `1`
|
|
97
108
|
- Unset model fields automatically use the value of `ANTHROPIC_MODEL`
|
|
98
|
-
4. **Configuration File**: Empty configuration file `{"models": {}}` is automatically created on first run
|
|
109
|
+
4. **Configuration File**: Empty configuration file `{"shared": {}, "models": {}}` is automatically created on first run
|
|
99
110
|
5. **Unset Command**: `ccms unset` removes only model-specific variables from `settings.json` and restores official models
|
|
100
111
|
|
|
101
112
|
## 📁 File Locations
|
package/README_CN.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- 一条命令启动 Claude Code 并加载指定模型配置(yolo 模式)
|
|
8
8
|
- 支持多个预配置模型环境
|
|
9
9
|
- `start` 将模型配置注入环境变量,`config` 可持久化写入 settings.json
|
|
10
|
+
- 支持 `shared` 公共环境变量,所有模型自动继承(模型配置可覆盖)
|
|
10
11
|
- 自动处理模型相关环境变量及默认值
|
|
11
12
|
- 命令行界面,操作简单
|
|
12
13
|
- `unset` 可清除 settings.json 中的模型相关配置
|
|
@@ -39,6 +40,11 @@ ccms config-path
|
|
|
39
40
|
|
|
40
41
|
# 清除 settings.json 中的模型相关配置,恢复使用官方模型
|
|
41
42
|
ccms unset
|
|
43
|
+
|
|
44
|
+
# 管理所有模型共享的环境变量
|
|
45
|
+
ccms shared list
|
|
46
|
+
ccms shared set API_TIMEOUT_MS 600000
|
|
47
|
+
ccms shared unset API_TIMEOUT_MS
|
|
42
48
|
```
|
|
43
49
|
|
|
44
50
|
### 配置模型
|
|
@@ -47,6 +53,10 @@ ccms unset
|
|
|
47
53
|
|
|
48
54
|
```json
|
|
49
55
|
{
|
|
56
|
+
"shared": {
|
|
57
|
+
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
58
|
+
"API_TIMEOUT_MS": "600000"
|
|
59
|
+
},
|
|
50
60
|
"models": {
|
|
51
61
|
"deepseek-chat": {
|
|
52
62
|
"ANTHROPIC_AUTH_TOKEN": "sk-your-token-here",
|
|
@@ -91,11 +101,12 @@ ccms unset
|
|
|
91
101
|
|
|
92
102
|
1. **start 命令**:`ccms start <model>` 将模型配置注入环境变量并启动 `claude`,默认附带 `--dangerously-skip-permissions`(yolo 模式)
|
|
93
103
|
2. **config 命令**:`ccms config <model>` 将模型配置写入 `~/.claude/settings.json`,适合需要持久化配置的场景
|
|
94
|
-
3.
|
|
104
|
+
3. **shared 公共变量**:`shared` 中的环境变量会应用到所有模型;单个模型里同名变量会覆盖 shared
|
|
105
|
+
4. **默认值处理**:
|
|
95
106
|
- `CLAUDE_CODE_MAX_OUTPUT_TOKENS` 默认为 `8192`
|
|
96
107
|
- `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` 默认为 `1`
|
|
97
108
|
- 未设置的模型字段会自动使用 `ANTHROPIC_MODEL` 的值
|
|
98
|
-
4. **配置文件**:首次运行时会自动创建空的配置文件 `{"models": {}}`
|
|
109
|
+
4. **配置文件**:首次运行时会自动创建空的配置文件 `{"shared": {}, "models": {}}`
|
|
99
110
|
5. **Unset 命令**:`ccms unset` 只删除 `settings.json` 中的模型相关变量,恢复使用官方模型
|
|
100
111
|
|
|
101
112
|
## 📁 文件位置
|
package/example-config.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"shared": {
|
|
3
|
+
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
4
|
+
"API_TIMEOUT_MS": "600000"
|
|
5
|
+
},
|
|
2
6
|
"models": {
|
|
3
7
|
"deepseek-chat": {
|
|
4
8
|
"ANTHROPIC_AUTH_TOKEN": "sk-caf695360e7f4b018bb1b308cbf992eb",
|
|
@@ -7,8 +11,7 @@
|
|
|
7
11
|
"ANTHROPIC_SMALL_FAST_MODEL": "deepseek-chat",
|
|
8
12
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "deepseek-chat",
|
|
9
13
|
"ANTHROPIC_DEFAULT_OPUS_MODEL": "deepseek-chat",
|
|
10
|
-
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "8192"
|
|
11
|
-
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
|
|
14
|
+
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "8192"
|
|
12
15
|
},
|
|
13
16
|
"claude-3-5-sonnet": {
|
|
14
17
|
"ANTHROPIC_AUTH_TOKEN": "your-anthropic-token-here",
|
|
@@ -21,4 +24,4 @@
|
|
|
21
24
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "0"
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
|
-
}
|
|
27
|
+
}
|
package/index.js
CHANGED
|
@@ -61,7 +61,7 @@ function loadModelConfig() {
|
|
|
61
61
|
ensureConfigDir();
|
|
62
62
|
|
|
63
63
|
if (!fs.existsSync(MODEL_CONFIG_PATH)) {
|
|
64
|
-
const defaultConfig = { models: {} };
|
|
64
|
+
const defaultConfig = { shared: {}, models: {} };
|
|
65
65
|
fs.writeFileSync(MODEL_CONFIG_PATH, JSON.stringify(defaultConfig, null, 2));
|
|
66
66
|
return defaultConfig;
|
|
67
67
|
}
|
|
@@ -118,9 +118,25 @@ function reportUnknownModel(model) {
|
|
|
118
118
|
process.exit(1);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
function
|
|
122
|
-
|
|
121
|
+
function saveModelConfig(config) {
|
|
122
|
+
ensureConfigDir();
|
|
123
|
+
try {
|
|
124
|
+
fs.writeFileSync(MODEL_CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error('Error: Failed to save model configuration file');
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
123
130
|
|
|
131
|
+
function getSharedEnv(config = loadModelConfig()) {
|
|
132
|
+
const shared = config.shared;
|
|
133
|
+
if (!shared || typeof shared !== 'object' || Array.isArray(shared)) {
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
return shared;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function getRawModelConfig(modelName, config = loadModelConfig()) {
|
|
124
140
|
if (!config.models || !config.models[modelName]) {
|
|
125
141
|
reportUnknownModel(modelName);
|
|
126
142
|
}
|
|
@@ -136,6 +152,14 @@ function getModelConfig(modelName) {
|
|
|
136
152
|
return modelConfig;
|
|
137
153
|
}
|
|
138
154
|
|
|
155
|
+
function mergeModelConfig(modelName) {
|
|
156
|
+
const config = loadModelConfig();
|
|
157
|
+
const shared = getSharedEnv(config);
|
|
158
|
+
const modelConfig = getRawModelConfig(modelName, config);
|
|
159
|
+
|
|
160
|
+
return { ...shared, ...modelConfig };
|
|
161
|
+
}
|
|
162
|
+
|
|
139
163
|
function normalizeModelConfig(modelConfig) {
|
|
140
164
|
const normalized = { ...modelConfig };
|
|
141
165
|
|
|
@@ -154,9 +178,9 @@ function buildModelEnv(modelConfig) {
|
|
|
154
178
|
const normalized = normalizeModelConfig(modelConfig);
|
|
155
179
|
const env = { ...process.env };
|
|
156
180
|
|
|
157
|
-
for (const key of
|
|
158
|
-
if (
|
|
159
|
-
env[key] = String(
|
|
181
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
182
|
+
if (value !== undefined && value !== null) {
|
|
183
|
+
env[key] = String(value);
|
|
160
184
|
}
|
|
161
185
|
}
|
|
162
186
|
|
|
@@ -234,11 +258,11 @@ function launchClaude(env, claudeArgs = []) {
|
|
|
234
258
|
}
|
|
235
259
|
|
|
236
260
|
function startClaudeWithModel(modelName) {
|
|
237
|
-
const modelConfig =
|
|
261
|
+
const modelConfig = mergeModelConfig(modelName);
|
|
238
262
|
const env = buildModelEnv(modelConfig);
|
|
239
263
|
const claudeArgs = buildStartArgs(getStartArgsFromArgv());
|
|
240
264
|
|
|
241
|
-
console.log(`[ccms]
|
|
265
|
+
console.log(`[ccms] model: ${env.ANTHROPIC_MODEL}, endpoint: ${env.ANTHROPIC_BASE_URL} (yolo mode)\n`);
|
|
242
266
|
launchClaude(env, claudeArgs);
|
|
243
267
|
}
|
|
244
268
|
|
|
@@ -250,9 +274,9 @@ function applyModelConfig(modelConfig) {
|
|
|
250
274
|
settings.env = {};
|
|
251
275
|
}
|
|
252
276
|
|
|
253
|
-
for (const key of
|
|
254
|
-
if (
|
|
255
|
-
settings.env[key] =
|
|
277
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
278
|
+
if (value !== undefined && value !== null) {
|
|
279
|
+
settings.env[key] = String(value);
|
|
256
280
|
}
|
|
257
281
|
}
|
|
258
282
|
|
|
@@ -276,10 +300,51 @@ function applyModelConfig(modelConfig) {
|
|
|
276
300
|
}
|
|
277
301
|
|
|
278
302
|
function configModel(modelName) {
|
|
279
|
-
const modelConfig =
|
|
303
|
+
const modelConfig = mergeModelConfig(modelName);
|
|
280
304
|
applyModelConfig(modelConfig);
|
|
281
305
|
}
|
|
282
306
|
|
|
307
|
+
function listSharedEnv() {
|
|
308
|
+
const shared = getSharedEnv();
|
|
309
|
+
const keys = Object.keys(shared);
|
|
310
|
+
|
|
311
|
+
if (keys.length === 0) {
|
|
312
|
+
console.log('No shared environment variables configured');
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
console.log('Shared environment variables:');
|
|
317
|
+
keys.forEach((key) => {
|
|
318
|
+
console.log(` ${key}=${shared[key]}`);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function setSharedEnv(key, value) {
|
|
323
|
+
const config = loadModelConfig();
|
|
324
|
+
|
|
325
|
+
if (!config.shared || typeof config.shared !== 'object' || Array.isArray(config.shared)) {
|
|
326
|
+
config.shared = {};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
config.shared[key] = value;
|
|
330
|
+
saveModelConfig(config);
|
|
331
|
+
console.log(`[ccms] shared env set: ${key}=${value}`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function unsetSharedEnv(key) {
|
|
335
|
+
const config = loadModelConfig();
|
|
336
|
+
const shared = getSharedEnv(config);
|
|
337
|
+
|
|
338
|
+
if (!Object.prototype.hasOwnProperty.call(shared, key)) {
|
|
339
|
+
console.log(`No shared environment variable found: ${key}`);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
delete config.shared[key];
|
|
344
|
+
saveModelConfig(config);
|
|
345
|
+
console.log(`[ccms] shared env removed: ${key}`);
|
|
346
|
+
}
|
|
347
|
+
|
|
283
348
|
function unsetModelConfig() {
|
|
284
349
|
const settings = loadClaudeSettings();
|
|
285
350
|
|
|
@@ -325,7 +390,7 @@ function listModels() {
|
|
|
325
390
|
program
|
|
326
391
|
.name('ccms')
|
|
327
392
|
.description('Claude Code Model Switch - Manage and launch Claude Code with configured models')
|
|
328
|
-
.version('2.
|
|
393
|
+
.version('2.2.0');
|
|
329
394
|
|
|
330
395
|
program
|
|
331
396
|
.command('start <model> [claude-args...]')
|
|
@@ -365,6 +430,41 @@ program
|
|
|
365
430
|
unsetModelConfig();
|
|
366
431
|
});
|
|
367
432
|
|
|
433
|
+
program
|
|
434
|
+
.command('shared')
|
|
435
|
+
.description('Manage shared environment variables for all models')
|
|
436
|
+
.argument('[action]', 'list, set, or unset')
|
|
437
|
+
.argument('[key]', 'Environment variable name')
|
|
438
|
+
.argument('[value]', 'Environment variable value')
|
|
439
|
+
.action((action, key, value) => {
|
|
440
|
+
if (!action || action === 'list') {
|
|
441
|
+
listSharedEnv();
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (action === 'set') {
|
|
446
|
+
if (!key || value === undefined) {
|
|
447
|
+
console.error('Usage: ccms shared set <key> <value>');
|
|
448
|
+
process.exit(1);
|
|
449
|
+
}
|
|
450
|
+
setSharedEnv(key, value);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (action === 'unset') {
|
|
455
|
+
if (!key) {
|
|
456
|
+
console.error('Usage: ccms shared unset <key>');
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
459
|
+
unsetSharedEnv(key);
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
console.error(`Unknown shared action: ${action}`);
|
|
464
|
+
console.log('Usage: ccms shared [list|set <key> <value>|unset <key>]');
|
|
465
|
+
process.exit(1);
|
|
466
|
+
});
|
|
467
|
+
|
|
368
468
|
program.parse();
|
|
369
469
|
|
|
370
470
|
if (!process.argv.slice(2).length) {
|