@daylenjeez/ccm-switch 1.2.3 → 1.2.6
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 +7 -1
- package/README.zh-CN.md +14 -8
- package/dist/claude.d.ts +1 -2
- package/dist/claude.js +1 -10
- package/dist/i18n/en.js +0 -2
- package/dist/i18n/zh.d.ts +0 -2
- package/dist/i18n/zh.js +0 -2
- package/dist/index.js +6 -17
- package/package.json +1 -1
- package/src/claude.ts +1 -9
- package/src/i18n/en.ts +0 -2
- package/src/i18n/zh.ts +0 -2
- package/src/index.ts +6 -18
package/README.md
CHANGED
|
@@ -64,6 +64,8 @@ Active: OpenRouter
|
|
|
64
64
|
|
|
65
65
|
You can also run `ccm sync` at any time to pull the latest cc-switch configurations into `~/.ccm/config.json`.
|
|
66
66
|
|
|
67
|
+
> ⚠️ **Known Issue**: After ccm modifies `~/.claude/settings.json`, cc-switch will automatically sync the content back to its database, overwriting the current provider's `settings_config`. If the configurations differ between the two tools, the original configuration stored in cc-switch will be modified.
|
|
68
|
+
|
|
67
69
|
## ➕ Adding Configurations
|
|
68
70
|
|
|
69
71
|
### Interactive wizard (recommended)
|
|
@@ -202,7 +204,11 @@ Use `ccm clear` to delete them automatically, or clean them up manually:
|
|
|
202
204
|
- `~/.ccm/config.json` — profiles
|
|
203
205
|
- `~/.claude/settings.json` — may still contain an active `env` profile written by ccm
|
|
204
206
|
|
|
205
|
-
|
|
207
|
+
Then remove the CLI:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npm uninstall -g @daylenjeez/ccm-switch
|
|
211
|
+
```
|
|
206
212
|
|
|
207
213
|
## 📄 License
|
|
208
214
|
|
package/README.zh-CN.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
[](https://github.com/daylenjeez/ccm-switch/blob/main/LICENSE)
|
|
11
11
|
[](https://nodejs.org)
|
|
12
12
|
|
|
13
|
-
English
|
|
13
|
+
[English](https://github.com/daylenjeez/ccm-switch/blob/main/README.md) | 中文文档
|
|
14
14
|
|
|
15
15
|
[安装](#-安装) · [快速开始](#-快速开始) · [命令一览](#-命令一览) · [工作原理](#%EF%B8%8F-工作原理)
|
|
16
16
|
|
|
@@ -20,12 +20,12 @@ English | [中文文档](https://github.com/daylenjeez/ccm-switch/blob/main/READ
|
|
|
20
20
|
|
|
21
21
|
## ✨ 亮点
|
|
22
22
|
|
|
23
|
-
- 🔌 **cc-switch
|
|
24
|
-
- 🧙
|
|
25
|
-
- ⚡
|
|
26
|
-
- 🛡️
|
|
27
|
-
- 🚀
|
|
28
|
-
- 🌍
|
|
23
|
+
- 🔌 **cc-switch Integration** — 直接读取 `cc-switch` 数据库,无需迁移
|
|
24
|
+
- 🧙 **Interactive Wizard** — `ccm add` 逐步引导,输入 `<` 可返回上一步
|
|
25
|
+
- ⚡ **One-command Switch** — `ccm use OpenRouter` 或 `ccm ls` 方向键选择
|
|
26
|
+
- 🛡️ **Safe Switching** — 自动保留 `language`、`permissions` 等个人设置
|
|
27
|
+
- 🚀 **Zero Config** — 直接 `ccm init`,跟着提示走,无需阅读文档
|
|
28
|
+
- 🌍 **i18n** — `ccm locale set zh/en` 切换界面语言
|
|
29
29
|
|
|
30
30
|
## 📦 安装
|
|
31
31
|
|
|
@@ -64,6 +64,8 @@ $ ccm init
|
|
|
64
64
|
|
|
65
65
|
你也可以随时运行 `ccm sync` 将最新的 cc-switch 配置同步到 `~/.ccm/config.json`。
|
|
66
66
|
|
|
67
|
+
> ⚠️ **已知问题**:ccm 修改 `~/.claude/settings.json` 后,cc-switch 会自动将该内容同步回数据库,覆盖当前 provider 的 `settings_config`。如果两个工具中的配置不一致,cc-switch 中存储的原始配置将被修改。
|
|
68
|
+
|
|
67
69
|
## ➕ 添加配置
|
|
68
70
|
|
|
69
71
|
### 交互式向导(推荐)
|
|
@@ -202,7 +204,11 @@ Claude Code 启动时读取 `~/.claude/settings.json`,`env` 字段控制 API
|
|
|
202
204
|
- `~/.ccm/config.json` — 配置方案
|
|
203
205
|
- `~/.claude/settings.json` — 可能仍包含 ccm 写入的 `env` 配置
|
|
204
206
|
|
|
205
|
-
|
|
207
|
+
然后移除 CLI:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npm uninstall -g @daylenjeez/ccm-switch
|
|
211
|
+
```
|
|
206
212
|
|
|
207
213
|
## 📄 License
|
|
208
214
|
|
package/dist/claude.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export declare function readClaudeSettings(): Record<string, unknown>;
|
|
2
|
-
export declare function applyProfile(settingsConfig: Record<string, unknown>): void;
|
|
3
|
-
export declare function clearEnvFromSettings(): void;
|
|
2
|
+
export declare function applyProfile(_name: string, settingsConfig: Record<string, unknown>): void;
|
|
4
3
|
export declare function getSettingsPath(): string;
|
package/dist/claude.js
CHANGED
|
@@ -7,7 +7,7 @@ export function readClaudeSettings() {
|
|
|
7
7
|
return {};
|
|
8
8
|
return JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
|
|
9
9
|
}
|
|
10
|
-
export function applyProfile(settingsConfig) {
|
|
10
|
+
export function applyProfile(_name, settingsConfig) {
|
|
11
11
|
const current = readClaudeSettings();
|
|
12
12
|
// 保留用户级字段,用 profile 的配置覆盖
|
|
13
13
|
const preserved = {};
|
|
@@ -20,15 +20,6 @@ export function applyProfile(settingsConfig) {
|
|
|
20
20
|
const merged = { ...preserved, ...settingsConfig };
|
|
21
21
|
writeFileSync(SETTINGS_PATH, JSON.stringify(merged, null, 2));
|
|
22
22
|
}
|
|
23
|
-
export function clearEnvFromSettings() {
|
|
24
|
-
if (!existsSync(SETTINGS_PATH))
|
|
25
|
-
return;
|
|
26
|
-
const current = readClaudeSettings();
|
|
27
|
-
if (!("env" in current))
|
|
28
|
-
return;
|
|
29
|
-
delete current.env;
|
|
30
|
-
writeFileSync(SETTINGS_PATH, JSON.stringify(current, null, 2));
|
|
31
|
-
}
|
|
32
23
|
export function getSettingsPath() {
|
|
33
24
|
return SETTINGS_PATH;
|
|
34
25
|
}
|
package/dist/i18n/en.js
CHANGED
|
@@ -121,8 +121,6 @@ const en = {
|
|
|
121
121
|
"clear.confirm": "Delete all ccm data files? (y/N) ",
|
|
122
122
|
"clear.cancelled": "Cancelled",
|
|
123
123
|
"clear.removed": "✓ Deleted {path}",
|
|
124
|
-
"clear.clear_env": "Also clear env config in ~/.claude/settings.json? (y/N) ",
|
|
125
|
-
"clear.env_cleared": "✓ Cleared env config",
|
|
126
124
|
"clear.done": "✓ Cleanup complete",
|
|
127
125
|
// store errors
|
|
128
126
|
"store.db_not_found": "cc-switch database not found: {path}",
|
package/dist/i18n/zh.d.ts
CHANGED
|
@@ -102,8 +102,6 @@ declare const zh: {
|
|
|
102
102
|
readonly "clear.confirm": "确认删除所有 ccm 数据文件?(y/N) ";
|
|
103
103
|
readonly "clear.cancelled": "已取消清理";
|
|
104
104
|
readonly "clear.removed": "✓ 已删除 {path}";
|
|
105
|
-
readonly "clear.clear_env": "是否同时清除 ~/.claude/settings.json 中的 env 配置?(y/N) ";
|
|
106
|
-
readonly "clear.env_cleared": "✓ 已清除 env 配置";
|
|
107
105
|
readonly "clear.done": "✓ 清理完成";
|
|
108
106
|
readonly "store.db_not_found": "cc-switch 数据库不存在: {path}";
|
|
109
107
|
};
|
package/dist/i18n/zh.js
CHANGED
|
@@ -121,8 +121,6 @@ const zh = {
|
|
|
121
121
|
"clear.confirm": "确认删除所有 ccm 数据文件?(y/N) ",
|
|
122
122
|
"clear.cancelled": "已取消清理",
|
|
123
123
|
"clear.removed": "✓ 已删除 {path}",
|
|
124
|
-
"clear.clear_env": "是否同时清除 ~/.claude/settings.json 中的 env 配置?(y/N) ",
|
|
125
|
-
"clear.env_cleared": "✓ 已清除 env 配置",
|
|
126
124
|
"clear.done": "✓ 清理完成",
|
|
127
125
|
// store errors
|
|
128
126
|
"store.db_not_found": "cc-switch 数据库不存在: {path}",
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Command } from "commander";
|
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { readRc, writeRc, getStore } from "./utils.js";
|
|
5
5
|
import { ccSwitchExists } from "./store/cc-switch.js";
|
|
6
|
-
import { readClaudeSettings, applyProfile
|
|
6
|
+
import { readClaudeSettings, applyProfile } from "./claude.js";
|
|
7
7
|
import { createInterface } from "readline";
|
|
8
8
|
import { spawnSync } from "child_process";
|
|
9
9
|
import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
|
|
@@ -240,17 +240,6 @@ program
|
|
|
240
240
|
unlinkSync(rcPath);
|
|
241
241
|
console.log(chalk.green(t("clear.removed", { path: rcPath })));
|
|
242
242
|
}
|
|
243
|
-
const settingsPath = getSettingsPath();
|
|
244
|
-
if (existsSync(settingsPath)) {
|
|
245
|
-
const settings = readClaudeSettings();
|
|
246
|
-
if ("env" in settings) {
|
|
247
|
-
const clearEnv = await ask(t("clear.clear_env"));
|
|
248
|
-
if (clearEnv.toLowerCase() === "y") {
|
|
249
|
-
clearEnvFromSettings();
|
|
250
|
-
console.log(chalk.green(t("clear.env_cleared")));
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
243
|
console.log(chalk.green(t("clear.done")));
|
|
255
244
|
});
|
|
256
245
|
// ccm list
|
|
@@ -271,8 +260,8 @@ program
|
|
|
271
260
|
if (name === current)
|
|
272
261
|
return;
|
|
273
262
|
const profile = store.get(name);
|
|
274
|
-
applyProfile(profile.settingsConfig);
|
|
275
263
|
store.setCurrent(profile.name);
|
|
264
|
+
applyProfile(profile.name, profile.settingsConfig);
|
|
276
265
|
const env = (profile.settingsConfig.env || {});
|
|
277
266
|
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
278
267
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
@@ -366,8 +355,8 @@ program
|
|
|
366
355
|
const profile = await resolveProfile(store, name);
|
|
367
356
|
if (!profile)
|
|
368
357
|
return;
|
|
369
|
-
applyProfile(profile.settingsConfig);
|
|
370
358
|
store.setCurrent(profile.name);
|
|
359
|
+
applyProfile(profile.name, profile.settingsConfig);
|
|
371
360
|
const env = (profile.settingsConfig.env || {});
|
|
372
361
|
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
373
362
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
@@ -425,8 +414,8 @@ async function saveAndSwitch(store, name, settingsConfig) {
|
|
|
425
414
|
console.log(chalk.green(t("add.done", { name })));
|
|
426
415
|
const switchChoice = await ask(t("add.switch_confirm"));
|
|
427
416
|
if (switchChoice.toLowerCase() !== "n") {
|
|
428
|
-
applyProfile(settingsConfig);
|
|
429
417
|
store.setCurrent(name);
|
|
418
|
+
applyProfile(name, settingsConfig);
|
|
430
419
|
console.log(chalk.green(t("use.done", { name: chalk.bold(name) })));
|
|
431
420
|
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
432
421
|
}
|
|
@@ -685,14 +674,14 @@ program
|
|
|
685
674
|
if (profile.name !== current) {
|
|
686
675
|
const switchChoice = await ask(t("add.switch_confirm"));
|
|
687
676
|
if (switchChoice.toLowerCase() !== "n") {
|
|
688
|
-
applyProfile(settingsConfig);
|
|
689
677
|
store.setCurrent(profile.name);
|
|
678
|
+
applyProfile(profile.name, settingsConfig);
|
|
690
679
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
691
680
|
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
692
681
|
}
|
|
693
682
|
}
|
|
694
683
|
else {
|
|
695
|
-
applyProfile(settingsConfig);
|
|
684
|
+
applyProfile(profile.name, settingsConfig);
|
|
696
685
|
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
697
686
|
}
|
|
698
687
|
});
|
package/package.json
CHANGED
package/src/claude.ts
CHANGED
|
@@ -9,7 +9,7 @@ export function readClaudeSettings(): Record<string, unknown> {
|
|
|
9
9
|
return JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function applyProfile(settingsConfig: Record<string, unknown>): void {
|
|
12
|
+
export function applyProfile(_name: string, settingsConfig: Record<string, unknown>): void {
|
|
13
13
|
const current = readClaudeSettings();
|
|
14
14
|
|
|
15
15
|
// 保留用户级字段,用 profile 的配置覆盖
|
|
@@ -25,14 +25,6 @@ export function applyProfile(settingsConfig: Record<string, unknown>): void {
|
|
|
25
25
|
writeFileSync(SETTINGS_PATH, JSON.stringify(merged, null, 2));
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export function clearEnvFromSettings(): void {
|
|
29
|
-
if (!existsSync(SETTINGS_PATH)) return;
|
|
30
|
-
const current = readClaudeSettings();
|
|
31
|
-
if (!("env" in current)) return;
|
|
32
|
-
delete current.env;
|
|
33
|
-
writeFileSync(SETTINGS_PATH, JSON.stringify(current, null, 2));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
28
|
export function getSettingsPath(): string {
|
|
37
29
|
return SETTINGS_PATH;
|
|
38
30
|
}
|
package/src/i18n/en.ts
CHANGED
|
@@ -141,8 +141,6 @@ const en: Record<TranslationKey, string> = {
|
|
|
141
141
|
"clear.confirm": "Delete all ccm data files? (y/N) ",
|
|
142
142
|
"clear.cancelled": "Cancelled",
|
|
143
143
|
"clear.removed": "✓ Deleted {path}",
|
|
144
|
-
"clear.clear_env": "Also clear env config in ~/.claude/settings.json? (y/N) ",
|
|
145
|
-
"clear.env_cleared": "✓ Cleared env config",
|
|
146
144
|
"clear.done": "✓ Cleanup complete",
|
|
147
145
|
|
|
148
146
|
// store errors
|
package/src/i18n/zh.ts
CHANGED
|
@@ -139,8 +139,6 @@ const zh = {
|
|
|
139
139
|
"clear.confirm": "确认删除所有 ccm 数据文件?(y/N) ",
|
|
140
140
|
"clear.cancelled": "已取消清理",
|
|
141
141
|
"clear.removed": "✓ 已删除 {path}",
|
|
142
|
-
"clear.clear_env": "是否同时清除 ~/.claude/settings.json 中的 env 配置?(y/N) ",
|
|
143
|
-
"clear.env_cleared": "✓ 已清除 env 配置",
|
|
144
142
|
"clear.done": "✓ 清理完成",
|
|
145
143
|
|
|
146
144
|
// store errors
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Command } from "commander";
|
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { readRc, writeRc, getStore } from "./utils.js";
|
|
6
6
|
import { ccSwitchExists } from "./store/cc-switch.js";
|
|
7
|
-
import { readClaudeSettings, applyProfile
|
|
7
|
+
import { readClaudeSettings, applyProfile } from "./claude.js";
|
|
8
8
|
import { createInterface } from "readline";
|
|
9
9
|
import { spawnSync } from "child_process";
|
|
10
10
|
import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
|
|
@@ -270,18 +270,6 @@ program
|
|
|
270
270
|
console.log(chalk.green(t("clear.removed", { path: rcPath })));
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
const settingsPath = getSettingsPath();
|
|
274
|
-
if (existsSync(settingsPath)) {
|
|
275
|
-
const settings = readClaudeSettings();
|
|
276
|
-
if ("env" in settings) {
|
|
277
|
-
const clearEnv = await ask(t("clear.clear_env"));
|
|
278
|
-
if (clearEnv.toLowerCase() === "y") {
|
|
279
|
-
clearEnvFromSettings();
|
|
280
|
-
console.log(chalk.green(t("clear.env_cleared")));
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
273
|
console.log(chalk.green(t("clear.done")));
|
|
286
274
|
});
|
|
287
275
|
|
|
@@ -304,8 +292,8 @@ program
|
|
|
304
292
|
const switchTo = (name: string) => {
|
|
305
293
|
if (name === current) return;
|
|
306
294
|
const profile = store.get(name)!;
|
|
307
|
-
applyProfile(profile.settingsConfig);
|
|
308
295
|
store.setCurrent(profile.name);
|
|
296
|
+
applyProfile(profile.name, profile.settingsConfig);
|
|
309
297
|
const env = (profile.settingsConfig.env || {}) as Record<string, string>;
|
|
310
298
|
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
311
299
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
@@ -406,8 +394,8 @@ program
|
|
|
406
394
|
const profile = await resolveProfile(store, name);
|
|
407
395
|
if (!profile) return;
|
|
408
396
|
|
|
409
|
-
applyProfile(profile.settingsConfig);
|
|
410
397
|
store.setCurrent(profile.name);
|
|
398
|
+
applyProfile(profile.name, profile.settingsConfig);
|
|
411
399
|
|
|
412
400
|
const env = (profile.settingsConfig.env || {}) as Record<string, string>;
|
|
413
401
|
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
@@ -469,8 +457,8 @@ async function saveAndSwitch(store: ReturnType<typeof ensureStore>, name: string
|
|
|
469
457
|
|
|
470
458
|
const switchChoice = await ask(t("add.switch_confirm"));
|
|
471
459
|
if (switchChoice.toLowerCase() !== "n") {
|
|
472
|
-
applyProfile(settingsConfig);
|
|
473
460
|
store.setCurrent(name);
|
|
461
|
+
applyProfile(name, settingsConfig);
|
|
474
462
|
console.log(chalk.green(t("use.done", { name: chalk.bold(name) })));
|
|
475
463
|
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
476
464
|
}
|
|
@@ -758,13 +746,13 @@ program
|
|
|
758
746
|
if (profile.name !== current) {
|
|
759
747
|
const switchChoice = await ask(t("add.switch_confirm"));
|
|
760
748
|
if (switchChoice.toLowerCase() !== "n") {
|
|
761
|
-
applyProfile(settingsConfig);
|
|
762
749
|
store.setCurrent(profile.name);
|
|
750
|
+
applyProfile(profile.name, settingsConfig);
|
|
763
751
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
764
752
|
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
765
753
|
}
|
|
766
754
|
} else {
|
|
767
|
-
applyProfile(settingsConfig);
|
|
755
|
+
applyProfile(profile.name, settingsConfig);
|
|
768
756
|
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
769
757
|
}
|
|
770
758
|
});
|