@daylenjeez/ccm-switch 1.2.0
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 +195 -0
- package/README.zh-CN.md +195 -0
- package/dist/claude.d.ts +3 -0
- package/dist/claude.js +25 -0
- package/dist/i18n/en.d.ts +3 -0
- package/dist/i18n/en.js +124 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/index.js +35 -0
- package/dist/i18n/zh.d.ts +107 -0
- package/dist/i18n/zh.js +124 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +872 -0
- package/dist/store/cc-switch.d.ts +13 -0
- package/dist/store/cc-switch.js +91 -0
- package/dist/store/interface.d.ts +1 -0
- package/dist/store/interface.js +1 -0
- package/dist/store/standalone.d.ts +9 -0
- package/dist/store/standalone.js +65 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +34 -0
- package/package.json +32 -0
- package/src/claude.ts +30 -0
- package/src/i18n/en.ts +144 -0
- package/src/i18n/index.ts +44 -0
- package/src/i18n/zh.ts +143 -0
- package/src/index.ts +949 -0
- package/src/store/cc-switch.ts +114 -0
- package/src/store/interface.ts +1 -0
- package/src/store/standalone.ts +79 -0
- package/src/types.ts +20 -0
- package/src/utils.ts +37 -0
- package/tsconfig.json +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ccm
|
|
4
|
+
|
|
5
|
+
**Claude Code Model Switcher**
|
|
6
|
+
|
|
7
|
+
Switch Claude Code custom model configurations from the terminal in seconds.
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@daylenjeez/ccm-switch)
|
|
10
|
+
[](https://github.com/daylenjeez/ccm-switch/blob/main/LICENSE)
|
|
11
|
+
[](https://nodejs.org)
|
|
12
|
+
|
|
13
|
+
[中文文档](./README.zh-CN.md) | English
|
|
14
|
+
|
|
15
|
+
[Install](#-install) · [Quick Start](#-quick-start) · [Commands](#-commands) · [How It Works](#%EF%B8%8F-how-it-works)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ✨ Highlights
|
|
22
|
+
|
|
23
|
+
- 🔌 **cc-switch Integration** — Reads [cc-switch](https://github.com/farion1231/cc-switch) database directly, zero migration
|
|
24
|
+
- 🧙 **Interactive Wizard** — `ccm add` guides you step by step, type `<` to go back
|
|
25
|
+
- ⚡ **One-command Switch** — `ccm use OpenRouter` or `ccm ls` with arrow keys
|
|
26
|
+
- 🛡️ **Safe Switching** — Preserves `language`, `permissions` and other personal settings
|
|
27
|
+
- 🚀 **Zero Config** — Just `ccm init` and follow the prompts, no docs needed
|
|
28
|
+
- 🌍 **i18n** — English / 中文 (`ccm locale set en/zh`)
|
|
29
|
+
|
|
30
|
+
## 📦 Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g @daylenjeez/ccm-switch
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or build from source:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git clone git@github.com:daylenjeez/ccm-switch.git
|
|
40
|
+
cd ccm && npm install && npm run build && npm link
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 🚀 Quick Start
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
ccm init # Auto-detects cc-switch or initializes standalone mode
|
|
47
|
+
ccm add # Interactive wizard to add a provider
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> **Without ccm**: Manually edit `~/.claude/settings.json`, copy-paste API keys, restart, hope the JSON isn't broken.
|
|
51
|
+
> **With ccm**: `ccm use OpenRouter` — done.
|
|
52
|
+
|
|
53
|
+
## 🔌 cc-switch Integration
|
|
54
|
+
|
|
55
|
+
Already using [cc-switch](https://github.com/farion1231/cc-switch)? ccm reads its SQLite database directly:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
$ ccm init
|
|
59
|
+
cc-switch detected. Import configurations from it? (Y/n)
|
|
60
|
+
✓ Initialized in cc-switch mode
|
|
61
|
+
✓ Imported 4 configurations
|
|
62
|
+
Active: OpenRouter
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
All configs sync both ways — add in ccm, see it in cc-switch UI, and vice versa.
|
|
66
|
+
|
|
67
|
+
## ➕ Adding Configurations
|
|
68
|
+
|
|
69
|
+
### Interactive wizard (recommended)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
$ ccm add
|
|
73
|
+
Provider name (e.g. OpenRouter): OpenRouter
|
|
74
|
+
|
|
75
|
+
Choose how to add:
|
|
76
|
+
1) Step by step # guided prompts, type < to go back
|
|
77
|
+
2) Write JSON # opens $EDITOR
|
|
78
|
+
|
|
79
|
+
ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
|
|
80
|
+
ANTHROPIC_AUTH_TOKEN: sk-or-xxx
|
|
81
|
+
ANTHROPIC_MODEL: anthropic/claude-opus-4.6
|
|
82
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL (optional):
|
|
83
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL (optional):
|
|
84
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL (optional):
|
|
85
|
+
|
|
86
|
+
✓ Saved configuration "OpenRouter"
|
|
87
|
+
Switch to this configuration now? (Y/n)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Edit JSON directly
|
|
91
|
+
|
|
92
|
+
<details>
|
|
93
|
+
<summary>Standalone mode: <code>~/.ccm/config.json</code></summary>
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"profiles": {
|
|
98
|
+
"OpenRouter": {
|
|
99
|
+
"env": {
|
|
100
|
+
"ANTHROPIC_BASE_URL": "https://openrouter.ai/api/v1",
|
|
101
|
+
"ANTHROPIC_AUTH_TOKEN": "sk-or-...",
|
|
102
|
+
"ANTHROPIC_MODEL": "anthropic/claude-opus-4.6"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
Aliases are stored in `~/.ccm/rc.json`:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"aliases": {
|
|
115
|
+
"or": "OpenRouter"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 📖 Commands
|
|
121
|
+
|
|
122
|
+
### Core
|
|
123
|
+
|
|
124
|
+
| Command | Alias | Description |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `ccm init` | | Initialize, auto-detect cc-switch |
|
|
127
|
+
| `ccm list` | `ls` | Interactive list & switch |
|
|
128
|
+
| `ccm use <name>` | | Switch by name |
|
|
129
|
+
| `ccm add` | `new` | Interactive add wizard |
|
|
130
|
+
| `ccm save <name>` | | Save current settings as profile |
|
|
131
|
+
| `ccm show [name]` | | View config details |
|
|
132
|
+
| `ccm modify [name]` | `edit` | Edit existing configuration |
|
|
133
|
+
| `ccm remove [name]` | `rm` | Interactive or named delete |
|
|
134
|
+
| `ccm current` | | Show active configuration |
|
|
135
|
+
| `ccm config` | | Switch storage mode |
|
|
136
|
+
|
|
137
|
+
### Aliases
|
|
138
|
+
|
|
139
|
+
| Command | Description |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `ccm alias set <short> <name>` | Create alias, e.g. `ccm alias set or OpenRouter` |
|
|
142
|
+
| `ccm alias rm <short>` | Remove alias |
|
|
143
|
+
| `ccm alias list` / `ls` | List all aliases |
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
ccm alias set or OpenRouter
|
|
147
|
+
ccm use or # same as: ccm use OpenRouter
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Locale
|
|
151
|
+
|
|
152
|
+
| Command | Description |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `ccm locale` / `ls` | List & switch language |
|
|
155
|
+
| `ccm locale set <lang>` | Set language (`zh` / `en`) |
|
|
156
|
+
|
|
157
|
+
### Examples
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Switch provider
|
|
161
|
+
$ ccm use OpenRouter
|
|
162
|
+
✓ Switched to OpenRouter
|
|
163
|
+
Model: anthropic/claude-opus-4.6
|
|
164
|
+
Restart Claude Code to apply
|
|
165
|
+
|
|
166
|
+
# View current config
|
|
167
|
+
$ ccm current
|
|
168
|
+
Current configuration: OpenRouter
|
|
169
|
+
ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
|
|
170
|
+
ANTHROPIC_MODEL: anthropic/claude-opus-4.6
|
|
171
|
+
ANTHROPIC_AUTH_TOKEN: sk-or-v1...a3f2
|
|
172
|
+
|
|
173
|
+
# Save current settings.json as a new profile
|
|
174
|
+
$ ccm save my-backup
|
|
175
|
+
✓ Saved current configuration as "my-backup"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## ⚙️ How It Works
|
|
179
|
+
|
|
180
|
+
Claude Code reads `~/.claude/settings.json` on startup. The `env` field controls the API provider and model:
|
|
181
|
+
|
|
182
|
+
| Variable | Description |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `ANTHROPIC_BASE_URL` | API endpoint URL |
|
|
185
|
+
| `ANTHROPIC_AUTH_TOKEN` | Authentication token |
|
|
186
|
+
| `ANTHROPIC_MODEL` | Default model |
|
|
187
|
+
| `ANTHROPIC_DEFAULT_OPUS_MODEL` | Model used when selecting Opus via `/model` |
|
|
188
|
+
| `ANTHROPIC_DEFAULT_SONNET_MODEL` | Model used when selecting Sonnet via `/model` |
|
|
189
|
+
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | Model used when selecting Haiku via `/model` |
|
|
190
|
+
|
|
191
|
+
`ccm use` writes the selected profile into `settings.json` while preserving personal settings (`language`, `permissions`, etc.). Restart Claude Code to apply.
|
|
192
|
+
|
|
193
|
+
## 📄 License
|
|
194
|
+
|
|
195
|
+
[MIT](./LICENSE)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ccm
|
|
4
|
+
|
|
5
|
+
**Claude Code Model Switcher**
|
|
6
|
+
|
|
7
|
+
在终端几秒内完成 Claude Code 自定义模型配置的管理和切换。
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@daylenjeez/ccm-switch)
|
|
10
|
+
[](https://github.com/daylenjeez/ccm-switch/blob/main/LICENSE)
|
|
11
|
+
[](https://nodejs.org)
|
|
12
|
+
|
|
13
|
+
English | [中文文档](./README.zh-CN.md)
|
|
14
|
+
|
|
15
|
+
[安装](#-安装) · [快速开始](#-快速开始) · [命令一览](#-命令一览) · [工作原理](#%EF%B8%8F-工作原理)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ✨ 亮点
|
|
22
|
+
|
|
23
|
+
- 🔌 **cc-switch 无缝对接** — 直接读取 [cc-switch](https://github.com/farion1231/cc-switch) 数据库,无需迁移
|
|
24
|
+
- 🧙 **交互式向导** — `ccm add` 逐步引导,输入 `<` 可返回上一步
|
|
25
|
+
- ⚡ **一键切换** — `ccm use OpenRouter` 或 `ccm ls` 方向键选择
|
|
26
|
+
- 🛡️ **安全切换** — 自动保留 `language`、`permissions` 等个人设置
|
|
27
|
+
- 🚀 **零配置上手** — 直接 `ccm init`,跟着提示走,无需阅读文档
|
|
28
|
+
- 🌍 **中英双语** — `ccm locale set zh/en` 切换界面语言
|
|
29
|
+
|
|
30
|
+
## 📦 安装
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g @daylenjeez/ccm-switch
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
或从源码构建:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git clone git@github.com:daylenjeez/ccm-switch.git
|
|
40
|
+
cd ccm && npm install && npm run build && npm link
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 🚀 快速开始
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
ccm init # 自动检测 cc-switch 或初始化独立模式
|
|
47
|
+
ccm add # 交互式向导添加供应商
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> **没有 ccm**: 手动编辑 `~/.claude/settings.json`,复制粘贴 API key,重启,祈祷 JSON 没写错。
|
|
51
|
+
> **使用 ccm**: `ccm use OpenRouter` — 搞定。
|
|
52
|
+
|
|
53
|
+
## 🔌 cc-switch 集成
|
|
54
|
+
|
|
55
|
+
已经在用 [cc-switch](https://github.com/farion1231/cc-switch)?ccm 直接读取它的 SQLite 数据库:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
$ ccm init
|
|
59
|
+
检测到 cc-switch 已安装,是否从中导入配置?(Y/n)
|
|
60
|
+
✓ 已初始化为 cc-switch 模式
|
|
61
|
+
✓ 已导入 4 个配置
|
|
62
|
+
当前激活: OpenRouter
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
双向同步 — 在 ccm 中添加的配置在 cc-switch UI 中也能看到,反之亦然。
|
|
66
|
+
|
|
67
|
+
## ➕ 添加配置
|
|
68
|
+
|
|
69
|
+
### 交互式向导(推荐)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
$ ccm add
|
|
73
|
+
供应商名称 (如 OpenRouter): OpenRouter
|
|
74
|
+
|
|
75
|
+
选择添加方式:
|
|
76
|
+
1) 逐步填写 # 按步骤输入,输入 < 返回上一步
|
|
77
|
+
2) 直接编写 JSON # 打开 $EDITOR 编辑
|
|
78
|
+
|
|
79
|
+
ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
|
|
80
|
+
ANTHROPIC_AUTH_TOKEN: sk-or-xxx
|
|
81
|
+
ANTHROPIC_MODEL: anthropic/claude-opus-4.6
|
|
82
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL (可选):
|
|
83
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL (可选):
|
|
84
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL (可选):
|
|
85
|
+
|
|
86
|
+
✓ 已保存配置 "OpenRouter"
|
|
87
|
+
是否立即切换到此配置?(Y/n)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 直接编辑 JSON
|
|
91
|
+
|
|
92
|
+
<details>
|
|
93
|
+
<summary>独立模式:<code>~/.ccm/config.json</code></summary>
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"profiles": {
|
|
98
|
+
"OpenRouter": {
|
|
99
|
+
"env": {
|
|
100
|
+
"ANTHROPIC_BASE_URL": "https://openrouter.ai/api/v1",
|
|
101
|
+
"ANTHROPIC_AUTH_TOKEN": "sk-or-...",
|
|
102
|
+
"ANTHROPIC_MODEL": "anthropic/claude-opus-4.6"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
别名存储在 `~/.ccm/rc.json` 中:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"aliases": {
|
|
115
|
+
"or": "OpenRouter"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 📖 命令一览
|
|
121
|
+
|
|
122
|
+
### 核心命令
|
|
123
|
+
|
|
124
|
+
| 命令 | 缩写 | 说明 |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `ccm init` | | 初始化,自动检测 cc-switch |
|
|
127
|
+
| `ccm list` | `ls` | 交互式列表 & 切换 |
|
|
128
|
+
| `ccm use <name>` | | 按名称切换 |
|
|
129
|
+
| `ccm add` | `new` | 交互式添加向导 |
|
|
130
|
+
| `ccm save <name>` | | 将当前设置保存为方案 |
|
|
131
|
+
| `ccm show [name]` | | 查看配置详情 |
|
|
132
|
+
| `ccm modify [name]` | `edit` | 修改已有配置 |
|
|
133
|
+
| `ccm remove [name]` | `rm` | 交互式或指定名称删除 |
|
|
134
|
+
| `ccm current` | | 显示当前激活配置 |
|
|
135
|
+
| `ccm config` | | 切换存储模式 |
|
|
136
|
+
|
|
137
|
+
### 别名管理
|
|
138
|
+
|
|
139
|
+
| 命令 | 说明 |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `ccm alias set <short> <name>` | 创建别名,如 `ccm alias set or OpenRouter` |
|
|
142
|
+
| `ccm alias rm <short>` | 删除别名 |
|
|
143
|
+
| `ccm alias list` / `ls` | 列出所有别名 |
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
ccm alias set or OpenRouter
|
|
147
|
+
ccm use or # 等同于: ccm use OpenRouter
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 语言设置
|
|
151
|
+
|
|
152
|
+
| 命令 | 说明 |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `ccm locale` / `ls` | 列出并切换语言 |
|
|
155
|
+
| `ccm locale set <lang>` | 设置语言(`zh` / `en`) |
|
|
156
|
+
|
|
157
|
+
### 使用示例
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# 切换供应商
|
|
161
|
+
$ ccm use OpenRouter
|
|
162
|
+
✓ 已切换到 OpenRouter
|
|
163
|
+
模型: anthropic/claude-opus-4.6
|
|
164
|
+
重启 Claude Code 生效
|
|
165
|
+
|
|
166
|
+
# 查看当前配置
|
|
167
|
+
$ ccm current
|
|
168
|
+
当前配置: OpenRouter
|
|
169
|
+
ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
|
|
170
|
+
ANTHROPIC_MODEL: anthropic/claude-opus-4.6
|
|
171
|
+
ANTHROPIC_AUTH_TOKEN: sk-or-v1...a3f2
|
|
172
|
+
|
|
173
|
+
# 将当前 settings.json 保存为新方案
|
|
174
|
+
$ ccm save my-backup
|
|
175
|
+
✓ 已保存当前配置为 "my-backup"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## ⚙️ 工作原理
|
|
179
|
+
|
|
180
|
+
Claude Code 启动时读取 `~/.claude/settings.json`,`env` 字段控制 API 供应商和模型:
|
|
181
|
+
|
|
182
|
+
| 变量 | 说明 |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `ANTHROPIC_BASE_URL` | API 端点地址 |
|
|
185
|
+
| `ANTHROPIC_AUTH_TOKEN` | 认证令牌 |
|
|
186
|
+
| `ANTHROPIC_MODEL` | 默认模型 |
|
|
187
|
+
| `ANTHROPIC_DEFAULT_OPUS_MODEL` | 在 Claude Code 中通过 `/model` 选择 Opus 时使用的模型 |
|
|
188
|
+
| `ANTHROPIC_DEFAULT_SONNET_MODEL` | 选择 Sonnet 时使用的模型 |
|
|
189
|
+
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | 选择 Haiku 时使用的模型 |
|
|
190
|
+
|
|
191
|
+
`ccm use` 将选中配置写入 `settings.json`,同时保留 `language`、`permissions` 等个人设置。重启 Claude Code 后生效。
|
|
192
|
+
|
|
193
|
+
## 📄 License
|
|
194
|
+
|
|
195
|
+
[MIT](./LICENSE)
|
package/dist/claude.d.ts
ADDED
package/dist/claude.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
4
|
+
const SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
5
|
+
export function readClaudeSettings() {
|
|
6
|
+
if (!existsSync(SETTINGS_PATH))
|
|
7
|
+
return {};
|
|
8
|
+
return JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
|
|
9
|
+
}
|
|
10
|
+
export function applyProfile(settingsConfig) {
|
|
11
|
+
const current = readClaudeSettings();
|
|
12
|
+
// 保留用户级字段,用 profile 的配置覆盖
|
|
13
|
+
const preserved = {};
|
|
14
|
+
const USER_FIELDS = ["language", "permissions"];
|
|
15
|
+
for (const key of USER_FIELDS) {
|
|
16
|
+
if (key in current) {
|
|
17
|
+
preserved[key] = current[key];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const merged = { ...preserved, ...settingsConfig };
|
|
21
|
+
writeFileSync(SETTINGS_PATH, JSON.stringify(merged, null, 2));
|
|
22
|
+
}
|
|
23
|
+
export function getSettingsPath() {
|
|
24
|
+
return SETTINGS_PATH;
|
|
25
|
+
}
|
package/dist/i18n/en.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const en = {
|
|
2
|
+
// program
|
|
3
|
+
"program.description": "Claude Code Model Switcher - Quickly switch Claude Code custom model configurations",
|
|
4
|
+
// common
|
|
5
|
+
"common.not_init": "Not initialized yet. Run: ccm init",
|
|
6
|
+
"common.model": "Model",
|
|
7
|
+
"common.model_default": "default",
|
|
8
|
+
"common.source": "Source",
|
|
9
|
+
// error
|
|
10
|
+
"error.not_found": 'Configuration "{name}" not found',
|
|
11
|
+
"error.alias_target_missing": 'Alias "{alias}" points to "{target}", but it does not exist',
|
|
12
|
+
"error.invalid_choice": "Invalid choice",
|
|
13
|
+
// suggest
|
|
14
|
+
"suggest.did_you_mean": "Did you mean: {name}?",
|
|
15
|
+
"suggest.did_you_mean_header": "Did you mean:",
|
|
16
|
+
"suggest.use_list": "Use ccm list to see all available configurations",
|
|
17
|
+
// init
|
|
18
|
+
"init.description": "Initialize ccm",
|
|
19
|
+
"init.cc_switch_found": "cc-switch detected. Import configurations from it? (Y/n) ",
|
|
20
|
+
"init.imported": "✓ Imported {count} configurations",
|
|
21
|
+
"init.current": "Active: {name}",
|
|
22
|
+
"init.no_current": "No active configuration",
|
|
23
|
+
"init.done_cc_switch": "✓ Initialized in cc-switch mode",
|
|
24
|
+
"init.done_standalone": "✓ Initialized in standalone mode",
|
|
25
|
+
// config
|
|
26
|
+
"config.description": "View or switch data source mode",
|
|
27
|
+
"config.current_mode": "Current mode: {mode}",
|
|
28
|
+
"config.switch_confirm": "Switch mode? (y/N) ",
|
|
29
|
+
"config.cc_switch_not_installed": "cc-switch is not installed",
|
|
30
|
+
"config.switched": "✓ Switched to {mode} mode",
|
|
31
|
+
// list
|
|
32
|
+
"list.description": "List and select configurations",
|
|
33
|
+
"list.empty": "No configurations yet. Use ccm save <name> to save current config",
|
|
34
|
+
"list.header": "Available configurations:",
|
|
35
|
+
"list.select": "Select configuration:",
|
|
36
|
+
"list.current_marker": "(current)",
|
|
37
|
+
"list.cancelled": "Cancelled",
|
|
38
|
+
"list.choose_number": "Enter number to switch (Enter to skip): ",
|
|
39
|
+
// current
|
|
40
|
+
"current.description": "Show the currently active configuration",
|
|
41
|
+
"current.none": "No active configuration",
|
|
42
|
+
"current.settings_header": "Current settings.json:",
|
|
43
|
+
"current.not_exist": 'Current configuration "{name}" no longer exists',
|
|
44
|
+
"current.header": "Current configuration: {name}",
|
|
45
|
+
// use
|
|
46
|
+
"use.description": "Switch to a specified configuration",
|
|
47
|
+
"use.done": "✓ Switched to {name}",
|
|
48
|
+
"use.restart": "Restart Claude Code to apply",
|
|
49
|
+
// save
|
|
50
|
+
"save.description": "Save current settings.json as a new configuration",
|
|
51
|
+
"save.overwrite": 'Configuration "{name}" already exists, will overwrite',
|
|
52
|
+
"save.done": '✓ Saved current configuration as "{name}"',
|
|
53
|
+
// show
|
|
54
|
+
"show.description": "View configuration details (defaults to current)",
|
|
55
|
+
"show.no_current": "No active configuration. Specify a name: ccm show <name>",
|
|
56
|
+
// remove
|
|
57
|
+
"remove.description": "Delete a configuration",
|
|
58
|
+
"remove.select": "Select configuration to delete:",
|
|
59
|
+
"remove.confirm": 'Delete "{name}"? (y/N) ',
|
|
60
|
+
"remove.done": '✓ Deleted "{name}"',
|
|
61
|
+
// alias
|
|
62
|
+
"alias.description": "Manage aliases",
|
|
63
|
+
"alias.set_description": "Set alias, e.g.: ccm alias set or openrouter-opus4.6",
|
|
64
|
+
"alias.set_done": "✓ Alias set: {short} → {name}",
|
|
65
|
+
"alias.rm_description": "Remove an alias",
|
|
66
|
+
"alias.rm_not_found": 'Alias "{short}" not found',
|
|
67
|
+
"alias.rm_done": '✓ Removed alias "{short}"',
|
|
68
|
+
"alias.list_description": "List all aliases",
|
|
69
|
+
"alias.list_empty": "No aliases yet. Use ccm alias set <short> <name> to add one",
|
|
70
|
+
"alias.list_header": "Aliases:",
|
|
71
|
+
// locale
|
|
72
|
+
"locale.description": "Manage interface language",
|
|
73
|
+
"locale.current": "Current language: {locale}",
|
|
74
|
+
"locale.set_description": "Set language (zh/en)",
|
|
75
|
+
"locale.set_done": "✓ Language set to {locale}",
|
|
76
|
+
"locale.set_invalid": "Unsupported language: {locale}. Available: zh, en",
|
|
77
|
+
"locale.list_description": "List and select language",
|
|
78
|
+
"locale.list_header": "Supported languages:",
|
|
79
|
+
"locale.list_current_marker": "(current)",
|
|
80
|
+
"locale.select": "Select language:",
|
|
81
|
+
"locale.choose_number": "Enter number to switch (Enter to skip): ",
|
|
82
|
+
// add
|
|
83
|
+
"add.description": "Interactively add a new configuration",
|
|
84
|
+
"add.prompt_name": "Provider name (e.g. OpenRouter): ",
|
|
85
|
+
"add.prompt_base_url": "ANTHROPIC_BASE_URL: ",
|
|
86
|
+
"add.prompt_auth_token": "ANTHROPIC_AUTH_TOKEN: ",
|
|
87
|
+
"add.prompt_model": "ANTHROPIC_MODEL: ",
|
|
88
|
+
"add.prompt_default_opus": "ANTHROPIC_DEFAULT_OPUS_MODEL (press Enter to skip): ",
|
|
89
|
+
"add.prompt_default_sonnet": "ANTHROPIC_DEFAULT_SONNET_MODEL (press Enter to skip): ",
|
|
90
|
+
"add.prompt_default_haiku": "ANTHROPIC_DEFAULT_HAIKU_MODEL (press Enter to skip): ",
|
|
91
|
+
"add.mode_select": "Choose how to add:",
|
|
92
|
+
"add.mode_interactive": "Step by step",
|
|
93
|
+
"add.mode_json": "Write JSON directly",
|
|
94
|
+
"add.mode_choose": "Choose (1/2): ",
|
|
95
|
+
"add.json_template_hint": "Fill in the configuration in editor, save and exit",
|
|
96
|
+
"add.json_parse_error": "JSON parse error, please check format",
|
|
97
|
+
"add.back_hint": "Type < to go back",
|
|
98
|
+
"add.name_required": "Provider name cannot be empty",
|
|
99
|
+
"add.field_required": "{field} cannot be empty",
|
|
100
|
+
"add.already_exists": 'Configuration "{name}" already exists. Overwrite? (y/N) ',
|
|
101
|
+
"add.edit_confirm": "Edit configuration in editor? (y/N) ",
|
|
102
|
+
"add.preview_header": "Configuration preview:",
|
|
103
|
+
"add.done": '✓ Saved configuration "{name}"',
|
|
104
|
+
"add.switch_confirm": "Switch to this configuration now? (Y/n) ",
|
|
105
|
+
"add.cancelled": "Cancelled",
|
|
106
|
+
// modify
|
|
107
|
+
"modify.description": "Modify an existing configuration",
|
|
108
|
+
"modify.select": "Select configuration to modify:",
|
|
109
|
+
"modify.done": '✓ Updated configuration "{name}"',
|
|
110
|
+
"modify.no_change": "No changes made",
|
|
111
|
+
// alias conflict
|
|
112
|
+
"alias.is_alias": '"{name}" is an alias for "{target}"',
|
|
113
|
+
"alias.conflict": '"{name}" is both an alias (→ {target}) and a config name. Which one?',
|
|
114
|
+
"alias.conflict_alias": "Alias (→ {target})",
|
|
115
|
+
"alias.conflict_config": "Config {name}",
|
|
116
|
+
"alias.choose_conflict": "Choose (1/2): ",
|
|
117
|
+
"alias.rm_which": "Which one to delete?",
|
|
118
|
+
"alias.rm_alias": "Alias {name}",
|
|
119
|
+
"alias.rm_config": "Config {target}",
|
|
120
|
+
"alias.rm_choose": "Choose (1/2): ",
|
|
121
|
+
// store errors
|
|
122
|
+
"store.db_not_found": "cc-switch database not found: {path}",
|
|
123
|
+
};
|
|
124
|
+
export default en;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import zh from "./zh.js";
|
|
2
|
+
import en from "./en.js";
|
|
3
|
+
import { readRc } from "../utils.js";
|
|
4
|
+
const locales = { zh, en };
|
|
5
|
+
function detectLocale() {
|
|
6
|
+
// 1. rc.json locale setting takes priority
|
|
7
|
+
const rc = readRc();
|
|
8
|
+
if (rc?.locale && rc.locale in locales)
|
|
9
|
+
return rc.locale;
|
|
10
|
+
// 2. Fallback to system LANG/LC_ALL
|
|
11
|
+
const lang = process.env.LC_ALL || process.env.LANG || "";
|
|
12
|
+
if (lang.startsWith("en"))
|
|
13
|
+
return "en";
|
|
14
|
+
// 3. Default to Chinese
|
|
15
|
+
return "zh";
|
|
16
|
+
}
|
|
17
|
+
let currentLocale;
|
|
18
|
+
function getLocale() {
|
|
19
|
+
if (!currentLocale)
|
|
20
|
+
currentLocale = detectLocale();
|
|
21
|
+
return currentLocale;
|
|
22
|
+
}
|
|
23
|
+
export function setLocale(locale) {
|
|
24
|
+
currentLocale = locale;
|
|
25
|
+
}
|
|
26
|
+
export function t(key, vars) {
|
|
27
|
+
const locale = getLocale();
|
|
28
|
+
let text = locales[locale][key] ?? locales.zh[key] ?? key;
|
|
29
|
+
if (vars) {
|
|
30
|
+
for (const [k, v] of Object.entries(vars)) {
|
|
31
|
+
text = text.replace(new RegExp(`\\{${k}\\}`, "g"), v);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return text;
|
|
35
|
+
}
|