@cc-x/cc-x 0.4.3 → 0.4.5
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.en.md +170 -296
- package/README.md +131 -292
- package/dist/config/store.js +3 -1
- package/dist/i18n/messages.js +4 -0
- package/dist/ui/menus.js +25 -2
- package/dist/ui/select.js +3 -0
- package/dist/update/update.js +112 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,382 +1,221 @@
|
|
|
1
1
|
# ccx
|
|
2
2
|
|
|
3
|
+
> `xx` — Claude Code 多 API 切换,一个命令搞定。**不碰配置,不怕翻车。**
|
|
4
|
+
>
|
|
3
5
|
> 简体中文 | [English](README.en.md)
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
用 Claude Code 连第三方 API?每次手打环境变量太烦,换工具切又怕弄丢 MCP。
|
|
8
|
+
ccx 把这事儿做到了最简——切换只在环境变量层,**不读写任何 Claude Code 配置文件**。
|
|
9
|
+
你的 MCP、插件、hooks,它碰都不会碰。
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
```text
|
|
12
|
+
cc-x v0.4.4 · Claude Code API 切换器 (默认 = 新终端裸敲 claude 用的)
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
▶ 官方 (默认)[登录态]
|
|
15
|
+
DeepSeek [密钥已设] — 公司
|
|
16
|
+
智谱GLM [密钥未填]
|
|
17
|
+
小米MiMo [密钥未填]
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## 目录
|
|
18
|
-
|
|
19
|
-
- [它解决什么问题](#它解决什么问题)
|
|
20
|
-
- [和 cc-switch 怎么选](#和-cc-switch-怎么选)
|
|
21
|
-
- [安全说明](#安全说明)
|
|
22
|
-
- [环境要求](#环境要求)
|
|
23
|
-
- [安装](#安装)
|
|
24
|
-
- [快速上手](#快速上手)
|
|
25
|
-
- [两种启用方式(核心概念)](#两种启用方式核心概念)
|
|
26
|
-
- [菜单操作详解](#菜单操作详解)
|
|
27
|
-
- [命令行用法](#命令行用法)
|
|
28
|
-
- [配置字段说明](#配置字段说明)
|
|
29
|
-
- [模型映射与 effort](#模型映射与-effort)
|
|
30
|
-
- [认证字段:AUTH_TOKEN vs API_KEY](#认证字段auth_token-vs-api_key)
|
|
31
|
-
- [多账号怎么管](#多账号怎么管)
|
|
32
|
-
- [维护供应商预设](#维护供应商预设)
|
|
33
|
-
- [首次使用:跳过登录 / 引导](#首次使用跳过登录--引导)
|
|
34
|
-
- [数据与文件位置](#数据与文件位置)
|
|
35
|
-
- [常见问题(FAQ)](#常见问题faq)
|
|
36
|
-
- [卸载](#卸载)
|
|
37
|
-
- [设计原则与初心](#设计原则与初心)
|
|
38
|
-
- [许可](#许可)
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 它解决什么问题
|
|
43
|
-
|
|
44
|
-
Claude Code 支持通过环境变量接入不同的 API 后端。但手动切换很麻烦:
|
|
45
|
-
|
|
46
|
-
- 每次都要去改 `settings.json` 或敲一长串 `export`;
|
|
47
|
-
- 第三方 API 还需要配套设置**模型映射**(它们只认自己的模型名);
|
|
48
|
-
- 开多个终端并行干活时,想让每个终端用不同的 API 更是没有顺手的办法。
|
|
49
|
-
|
|
50
|
-
ccx 把这些收进一个命令 `xx`:选一下,要么**仅当前终端临时启用**,要么**设为以后默认**。
|
|
51
|
-
|
|
52
|
-
## 和 cc-switch 怎么选
|
|
53
|
-
|
|
54
|
-
cc-switch 是优秀的**全能型 GUI**——想要图形界面、想统一管理 MCP、还要同时切
|
|
55
|
-
Codex / Gemini 等多个 CLI,它更合适。ccx 走相反的**极简路线**,两者定位不同:
|
|
56
|
-
|
|
57
|
-
| | ccx(命令 `xx`) | cc-switch |
|
|
58
|
-
|---|---|---|
|
|
59
|
-
| 形态 | 终端命令(轻量) | 桌面 GUI(全能) |
|
|
60
|
-
| 职责 | 只切 API,一件事做到位 | API + MCP + 多 CLI + 提示词… |
|
|
61
|
-
| 改不改配置文件 | **完全不碰**(纯环境变量) | 以自有数据库为准,重写配置文件 |
|
|
62
|
-
| 会不会弄丢 MCP / 插件 | **设计上不可能** | 有用户反馈被覆盖丢失 |
|
|
63
|
-
| 多终端并行不同 API | **原生支持**(进程级隔离) | 全局切换,易相互影响 |
|
|
64
|
-
|
|
65
|
-
**这些情况下,更推荐用 ccx:**
|
|
66
|
-
- 你是命令行党,喜欢敲一下就切;
|
|
67
|
-
- 经常**同时开多个终端、各跑不同 API** 并行工作;
|
|
68
|
-
- 被“切换把配置 / MCP 弄坏”坑过,想要**零风险**;
|
|
69
|
-
- 只想要“切 API”这一件事,不想要一堆用不上的功能。
|
|
70
|
-
|
|
71
|
-
**这些情况下,更推荐用 cc-switch:** 想要图形界面、需要在一个工具里统管 MCP 和多个 AI CLI、喜欢一站式。
|
|
19
|
+
新增配置 · 切换到 English · 更新检查:关闭 · 退出
|
|
72
20
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
- **不写任何 Claude Code 配置文件**:不碰 `~/.claude/settings.json`,更不会打开 `~/.claude.json`
|
|
76
|
-
(你的 MCP 配置就在这个文件里)。MCP / 插件 / hooks / 权限**物理上不可能**被它影响。
|
|
77
|
-
- 只通过环境变量工作,且只动这 7 个“受管”变量,其它一律不碰:
|
|
78
|
-
`ANTHROPIC_BASE_URL`、`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_API_KEY`、
|
|
79
|
-
`ANTHROPIC_DEFAULT_OPUS_MODEL`、`ANTHROPIC_DEFAULT_SONNET_MODEL`、
|
|
80
|
-
`ANTHROPIC_DEFAULT_HAIKU_MODEL`、`CLAUDE_CODE_EFFORT_LEVEL`。
|
|
81
|
-
- 切换时自动清除目标配置没用到的受管变量,避免上一个的残留(含两种认证字段互斥)。
|
|
82
|
-
|
|
83
|
-
> 💡 **关于 `settings.json` 等 Claude Code 配置文件**:不建议用第三方工具去管理它(ccx 也刻意
|
|
84
|
-
> 不碰)。需要修改时,直接用 Claude Code 官方的 `/update-config`,用自然语言说出你的需求(例如
|
|
85
|
-
> “允许运行 npm 命令”“换成深色主题”),Claude Code 会自己安全地维护这个文件——比让外部工具乱改更可靠。
|
|
21
|
+
↑↓ 选择 · Enter 进入 · Shift+↑↓ 排序 · q 退出
|
|
22
|
+
```
|
|
86
23
|
|
|
87
|
-
|
|
24
|
+
> **两个版本**:推荐 **Go 原生版**——GitHub Release 提供轻量 `xx` / `xx.exe`,无需 Node.js,
|
|
25
|
+
> 覆盖 Windows x64、macOS Intel / Apple Silicon、Linux x64 / arm64。npm 用户可装
|
|
26
|
+
> `@cc-x/cc-x`(命令仍是 `xx`)。两版功能一致。
|
|
88
27
|
|
|
89
|
-
|
|
90
|
-
- **npm 全平台版**:Node.js ≥ 18(包名 `@cc-x/cc-x`)。
|
|
91
|
-
- **已安装 Claude Code(`claude` 命令在 PATH 中)**:「本次启用」会直接调用 `claude`。
|
|
28
|
+
---
|
|
92
29
|
|
|
93
30
|
## 安装
|
|
94
31
|
|
|
95
|
-
|
|
32
|
+
> 先装好 [Claude Code](https://claude.ai/code)(`claude` 在 PATH 中)。装完**新开一个终端**。
|
|
33
|
+
|
|
34
|
+
**Windows(推荐原生版)**
|
|
96
35
|
|
|
97
36
|
```powershell
|
|
98
37
|
irm https://github.com/becomeless/cc-x/releases/latest/download/install.ps1 | iex
|
|
99
38
|
```
|
|
100
39
|
|
|
101
|
-
|
|
102
|
-
`%LOCALAPPDATA%\Programs\ccx`,并把该目录加入用户 PATH。安装后新开终端,运行:
|
|
103
|
-
|
|
104
|
-
```powershell
|
|
105
|
-
xx --version
|
|
106
|
-
```
|
|
40
|
+
安装器会自动选择用户级目录并写入用户 PATH,无需管理员权限,也无需手动配置。
|
|
107
41
|
|
|
108
|
-
**macOS / Linux
|
|
42
|
+
**macOS / Linux(推荐原生版)**
|
|
109
43
|
|
|
110
44
|
```bash
|
|
111
45
|
curl -fsSL https://github.com/becomeless/cc-x/releases/latest/download/install.sh | sh
|
|
112
46
|
```
|
|
113
47
|
|
|
114
|
-
|
|
115
|
-
`~/.local/bin`(可用 `CCX_INSTALL_DIR` 或 `--install-dir` 改目录),并校验 `checksums.txt`。
|
|
116
|
-
如果该目录不在 PATH,按提示加入后新开终端,运行:
|
|
48
|
+
安装器会放到用户级命令目录;若该目录不在 PATH 中,会打印一行提示(Unix 版刻意不自动改 shell 配置)。
|
|
117
49
|
|
|
118
|
-
|
|
119
|
-
xx --version
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
**npm 全平台版**
|
|
50
|
+
**npm(全平台,需 Node.js ≥ 18)**
|
|
123
51
|
|
|
124
52
|
```bash
|
|
125
53
|
npm install -g @cc-x/cc-x
|
|
126
54
|
```
|
|
127
55
|
|
|
128
|
-
|
|
129
|
-
(npm 包名是 `@cc-x/cc-x`,终端命令是 `xx`。)
|
|
56
|
+
---
|
|
130
57
|
|
|
131
|
-
|
|
58
|
+
## 60 秒上手
|
|
59
|
+
|
|
60
|
+
首次运行 `xx` 会在 `~/.cc-mini/providers.json` 生成 4 个预设配置(官方 + DeepSeek + 智谱GLM + 小米MiMo),**密钥为空**。
|
|
61
|
+
|
|
62
|
+
1. `xx` → ↑↓ 选中要用的配置 → Enter → 「编辑」→「API 密钥」→ 填入你的 key
|
|
63
|
+
2. 配好后二选一:
|
|
64
|
+
- **本次启用** — 即刻在当前终端启动 Claude(临时,多开互不干扰)
|
|
65
|
+
- **设为默认** — 以后新终端裸敲 `claude` 就用它
|
|
132
66
|
|
|
133
67
|
```bash
|
|
134
|
-
|
|
135
|
-
|
|
68
|
+
xx # 打开菜单
|
|
69
|
+
xx DeepSeek # 设为默认
|
|
70
|
+
xx DeepSeek -s # 本次启用,立即启动 Claude(--session 同义)
|
|
71
|
+
xx -l # 列出所有配置及状态(--list 同义)
|
|
72
|
+
xx --help # 全部参数
|
|
136
73
|
```
|
|
137
74
|
|
|
138
|
-
|
|
75
|
+
---
|
|
139
76
|
|
|
140
|
-
|
|
141
|
-
.\scripts\build-release.ps1 -Version 0.4.2
|
|
142
|
-
.\dist\release\ccx_0.4.2_windows_amd64\xx.exe --version
|
|
143
|
-
```
|
|
77
|
+
## 两种模式(核心概念)
|
|
144
78
|
|
|
145
|
-
|
|
79
|
+
Claude 用哪个 API 由**环境变量**决定。ccx 提供两种作用范围:
|
|
146
80
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
81
|
+
| | 本次启用 (`-s`) | 设为默认 |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| 机制 | 给当前进程设环境变量,启动 `claude` | 写入**用户环境变量** |
|
|
84
|
+
| 作用范围 | 仅当前终端,**关了就没** | 之后**新开**的终端默认用它 |
|
|
85
|
+
| 对正在跑的会话 | 零影响 | 零影响(进程启动时已定型) |
|
|
86
|
+
| 适合 | 多终端并行,各跑各的 API | 定好主力 API,不用老切 |
|
|
152
87
|
|
|
153
|
-
|
|
88
|
+
**并行示例**:开 4 个终端分别 `xx 官方 -s`、`xx DeepSeek -s`、`xx 智谱GLM -s`、`xx 小米MiMo -s`——四个 Claude 同时干活、各用各的 API、互不打架。
|
|
154
89
|
|
|
155
|
-
|
|
90
|
+
**为什么不用配置文件?** `settings.json` 全局共享,改它会波及正在跑的会话(典型症状:另一终端突然报 `cannot be parsed as a URL`)。环境变量天然进程隔离,避开了这个坑。
|
|
156
91
|
|
|
157
|
-
|
|
158
|
-
(官方 + DeepSeek + 智谱GLM + 小米MiMo),**密钥为空**。
|
|
159
|
-
2. 用 ↑↓ 选中要配置的配置 → Enter → 选「编辑」→ 按序号填入你的 **API 密钥**(在本机操作)。
|
|
160
|
-
3. 配好后:
|
|
161
|
-
- 想让以后新终端**默认**用它 → 选「设为默认」,然后**新开终端**敲 `claude`。
|
|
162
|
-
- 想在当前终端**临时/并行**用它 → 选「本次启用」,它会立即启动 Claude。
|
|
92
|
+
---
|
|
163
93
|
|
|
164
|
-
##
|
|
94
|
+
## 和 cc-switch 怎么选
|
|
165
95
|
|
|
166
|
-
|
|
96
|
+
cc-switch 是优秀的全能 GUI;ccx 走相反的极简路线。
|
|
167
97
|
|
|
168
|
-
| |
|
|
98
|
+
| | ccx (`xx`) | cc-switch |
|
|
169
99
|
|---|---|---|
|
|
170
|
-
|
|
|
171
|
-
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
175
|
-
**并行多终端示例**:你可以同时开 4 个终端,分别 `xx 官方 -s`、`xx DeepSeek -s`、
|
|
176
|
-
`xx 智谱GLM -s`、`xx 小米MiMo -s`,得到 4 个同时运行、各用各 API、互不干扰的 Claude。
|
|
100
|
+
| 形态 | 终端命令(轻量) | 桌面 GUI(全能) |
|
|
101
|
+
| 职责 | 只切 API | API + MCP + 多 CLI + 提示词… |
|
|
102
|
+
| 改配置文件? | **不碰**(纯环境变量) | 会重写 |
|
|
103
|
+
| 能弄丢 MCP? | **不可能** | 有用户反馈被覆盖 |
|
|
104
|
+
| 多终端并行 | **原生支持**(进程隔离) | 全局切换,容易互扰 |
|
|
177
105
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
变量避开了这个坑:进程级隔离 + 用户级默认,互不打架。
|
|
106
|
+
- → **ccx**:命令行党、常多开终端、被切配置坑过、只想要「切 API」一件事
|
|
107
|
+
- → **cc-switch**:要 GUI、要一站式管 MCP 和多 CLI
|
|
181
108
|
|
|
182
|
-
|
|
109
|
+
---
|
|
183
110
|
|
|
184
|
-
|
|
185
|
-
在主菜单选中某个配置时,按 **`Shift+↑↓`(或 `PgUp`/`PgDn`)可直接把它上/下移动来排序**,改完即时保存:
|
|
111
|
+
## 设计哲学
|
|
186
112
|
|
|
187
|
-
|
|
188
|
-
- **本次启用** — 仅当前终端设环境变量并立刻启动 Claude。退出 Claude 后回到命令行。
|
|
189
|
-
- **设为默认** — 写用户环境变量;**需新开终端**裸敲 `claude` 才生效,不影响运行中的会话。
|
|
190
|
-
- **编辑** — 进入表单(见下)。
|
|
191
|
-
- **删除** — 删除该配置(会二次确认;建议保留「官方」)。
|
|
192
|
-
- **返回**。
|
|
193
|
-
- **+ 新增配置** — 新建一个空配置并进入编辑表单。
|
|
194
|
-
- **语言 / Language** — 中英文界面即时切换(选择会记住,写回 `~/.cc-mini/providers.json` 的 `lang`)。
|
|
195
|
-
- **退出**。
|
|
113
|
+
> ccx 的边界比功能更重要。
|
|
196
114
|
|
|
197
|
-
|
|
198
|
-
进入某项后**直接回车 = 不修改**、输入 `-` = 清空、`Esc` = 取消该项不改。
|
|
199
|
-
其中第一项是**「供应商」**:选一个供应商(来自预设目录)后,会**自动填入** API 地址、三档模型映射、
|
|
200
|
-
认证字段(多 API 地址的供应商,如小米 MiMo 的按量付费 API 与 TokenPlan,会让你先选一个);「备注」随你写。
|
|
201
|
-
「API 地址」也可单独打开列表(预设 + 已有地址 + 手动输入)覆盖。
|
|
115
|
+
Claude Code 已经有自己的配置系统、MCP 生态和会话状态。ccx 不想再造一个“上层控制台”,也不想把用户的配置收编进自己的数据库。它只站在 Claude Code 进程启动前的那一小步:把 7 个受管环境变量准备好,然后让 Claude Code 自己工作。
|
|
202
116
|
|
|
203
|
-
|
|
117
|
+
所以它的取舍是有意的:不写 Claude Code 配置文件,不接管 MCP,不做自动迁移,不做后台常驻管理。能用进程环境变量解决,就不碰全局文件;能让用户显式选择,就不替用户自动决定。少做一点,是为了把风险面压到足够小。
|
|
204
118
|
|
|
205
|
-
|
|
119
|
+
欢迎 Issue / PR,但方向很明确:**让切换更稳、更清楚、更不打扰用户**,比堆更多管理能力更重要。任何会写 Claude Code 配置文件的改动都不会被接受。
|
|
206
120
|
|
|
207
|
-
|
|
208
|
-
xx # 打开交互菜单
|
|
209
|
-
xx DeepSeek # 直接「设为默认」到名为 DeepSeek 的配置
|
|
210
|
-
xx DeepSeek -s # 「本次启用」DeepSeek 并立即启动 Claude(--session 同义)
|
|
211
|
-
xx -l # 列出所有配置及状态(--list 同义)
|
|
212
|
-
xx --lang en # 本次界面用英文(zh / en)
|
|
213
|
-
xx --help # 查看全部参数
|
|
214
|
-
```
|
|
121
|
+
---
|
|
215
122
|
|
|
216
|
-
|
|
217
|
-
- 加 `-s` / `--session`:改为「本次启用」(进程级 + 启动 Claude)。
|
|
123
|
+
## 配置说明
|
|
218
124
|
|
|
219
|
-
|
|
125
|
+
### 字段一览
|
|
220
126
|
|
|
221
127
|
| 字段 | 对应环境变量 | 说明 |
|
|
222
128
|
|---|---|---|
|
|
223
|
-
|
|
|
224
|
-
|
|
|
225
|
-
| API 地址 | `ANTHROPIC_BASE_URL` | 第三方的接入点;官方留空=走登录态 |
|
|
226
|
-
| 认证字段 | — | 选择密钥放进 `AUTH_TOKEN` 还是 `API_KEY`(见下) |
|
|
129
|
+
| API 地址 | `ANTHROPIC_BASE_URL` | 第三方接入点;官方留空=登录态 |
|
|
130
|
+
| 认证字段 | — | 密钥放 `AUTH_TOKEN`(默认)还是 `API_KEY`;**放错会 401** |
|
|
227
131
|
| API 密钥 | `ANTHROPIC_AUTH_TOKEN` 或 `ANTHROPIC_API_KEY` | 对应认证字段的值 |
|
|
228
|
-
| opus → 模型 | `ANTHROPIC_DEFAULT_OPUS_MODEL` |
|
|
229
|
-
| sonnet → 模型 | `ANTHROPIC_DEFAULT_SONNET_MODEL` |
|
|
230
|
-
| haiku → 模型 | `ANTHROPIC_DEFAULT_HAIKU_MODEL` |
|
|
231
|
-
| effort 思考档 | `CLAUDE_CODE_EFFORT_LEVEL` |
|
|
232
|
-
|
|
233
|
-
> ccx **刻意不设** `ANTHROPIC_MODEL`、也不碰 `settings.json` 的 `model` 字段。
|
|
234
|
-
> 你在会话里用 `/model opus|sonnet|haiku` 现场选档,映射表负责把它翻译成对应供应商的模型。
|
|
235
|
-
|
|
236
|
-
## 模型映射与 effort
|
|
237
|
-
|
|
238
|
-
**为什么第三方必须配模型映射?** 第三方端点只认它自己的模型名(如 `deepseek-v4-pro`),
|
|
239
|
-
而 Claude Code 默认会去叫 `claude-*`;不映射就会报错。而且后台任务走 `haiku` 档,
|
|
240
|
-
所以 `haiku → 模型` 也必须填(否则后台请求失败,表现为“主对话能用但时不时报错”)。
|
|
132
|
+
| opus → 模型 | `ANTHROPIC_DEFAULT_OPUS_MODEL` | 三档模型映射;后台任务走 haiku 档,**必须填** |
|
|
133
|
+
| sonnet → 模型 | `ANTHROPIC_DEFAULT_SONNET_MODEL` | |
|
|
134
|
+
| haiku → 模型 | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | |
|
|
135
|
+
| effort 思考档 | `CLAUDE_CODE_EFFORT_LEVEL` | `low` ~ `max`;`auto`=模型默认;留空=不设。第三方不一定生效 |
|
|
241
136
|
|
|
242
|
-
|
|
243
|
-
`auto` = 回到模型默认;留空 = 不设。注意 **effort 是 Claude 模型的特性,第三方是否真生效取决于各家实现**。
|
|
137
|
+
> ccx **刻意不设** `ANTHROPIC_MODEL`。在会话里用 `/model opus|sonnet|haiku` 选档,映射表负责翻译成对应供应商的模型名。
|
|
244
138
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
| 配置 | BASE_URL | OPUS / SONNET | HAIKU(含后台) | effort |
|
|
248
|
-
|---|---|---|---|---|
|
|
249
|
-
| 官方 | (留空=登录态) | — | — | 留空 / `auto` |
|
|
250
|
-
| DeepSeek | `https://api.deepseek.com/anthropic` | `deepseek-v4-pro` | `deepseek-v4-flash` | `max`(官方文档推荐) |
|
|
251
|
-
| 智谱GLM | `https://open.bigmodel.cn/api/anthropic` | `GLM-4.7` | `glm-4.5-air` | 留空 |
|
|
252
|
-
| 小米MiMo | `https://api.xiaomimimo.com/anthropic`(按量付费)<br>`https://token-plan-cn.xiaomimimo.com/anthropic`(TokenPlan) | `mimo-v2.5-pro` | `mimo-v2.5-pro` | 留空 |
|
|
253
|
-
|
|
254
|
-
> 模型名会随各家更新而变化,请以各供应商官方接入文档为准。
|
|
255
|
-
|
|
256
|
-
## 认证字段:AUTH_TOKEN vs API_KEY
|
|
257
|
-
|
|
258
|
-
密钥放进哪个变量,决定了发出的请求头不同:
|
|
139
|
+
### 认证字段:AUTH_TOKEN vs API_KEY
|
|
259
140
|
|
|
260
141
|
| 选项 | 实际请求头 | 谁用 |
|
|
261
142
|
|---|---|---|
|
|
262
|
-
| `
|
|
263
|
-
| `
|
|
264
|
-
|
|
265
|
-
有些端点只认其中一种,放错会 401。编辑时可在「认证字段」里切换;切换配置时 ccx 会自动
|
|
266
|
-
清掉另一个,避免残留导致认证冲突。
|
|
267
|
-
|
|
268
|
-
## 多账号怎么管
|
|
269
|
-
|
|
270
|
-
同一家有多个账号(如个人 / 公司各一个 DeepSeek Key):**直接建多份配置即可**——
|
|
271
|
-
选同一个供应商建第二份时,名称会自动变成 `DeepSeek 2`,再用**备注**写明「个人 / 公司」加以区分,
|
|
272
|
-
列表里显示成「供应商 — 备注」,一眼可辨。
|
|
143
|
+
| `AUTH_TOKEN`(默认) | `Authorization: Bearer <key>` | 绝大多数第三方中转 |
|
|
144
|
+
| `API_KEY` | `x-api-key: <key>` | 官方 API,及少数中转 |
|
|
273
145
|
|
|
274
|
-
|
|
146
|
+
### 预置配置
|
|
275
147
|
|
|
276
|
-
|
|
277
|
-
|
|
148
|
+
| 配置 | BASE_URL | OPUS / SONNET | HAIKU(含后台任务) | effort |
|
|
149
|
+
|---|---|---|---|---|
|
|
150
|
+
| 官方 | 留空=登录态 | — | — | — |
|
|
151
|
+
| DeepSeek | `https://api.deepseek.com/anthropic` | `deepseek-v4-pro` | `deepseek-v4-flash` | `max`(官方推荐) |
|
|
152
|
+
| 智谱GLM | `https://open.bigmodel.cn/api/anthropic` | `GLM-4.7` | `glm-4.5-air` | — |
|
|
153
|
+
| 小米MiMo | `https://api.xiaomimimo.com/anthropic` | `mimo-v2.5-pro` | `mimo-v2.5-pro` | — |
|
|
278
154
|
|
|
279
|
-
|
|
280
|
-
[
|
|
281
|
-
{
|
|
282
|
-
"name": "DeepSeek",
|
|
283
|
-
"auth": "AUTH_TOKEN",
|
|
284
|
-
"effort": "max",
|
|
285
|
-
"urls": [ { "label": "Anthropic 兼容", "url": "https://api.deepseek.com/anthropic" } ],
|
|
286
|
-
"models": { "opus": "deepseek-v4-pro", "sonnet": "deepseek-v4-pro", "haiku": "deepseek-v4-flash" }
|
|
287
|
-
}
|
|
288
|
-
]
|
|
289
|
-
```
|
|
155
|
+
> 模型名随各家更新而变,以供应商官方接入文档为准。小米有按量付费和 TokenPlan 两个地址,选供应商时会让你挑。
|
|
290
156
|
|
|
291
|
-
|
|
292
|
-
- `models` 是该供应商三档(opus/sonnet/haiku)的**推荐映射**,选供应商时自动填入,之后仍可手动改。
|
|
293
|
-
- `auth`(`AUTH_TOKEN`/`API_KEY`)、`effort` 为可选,选供应商时一并带出。
|
|
157
|
+
### 进阶
|
|
294
158
|
|
|
295
|
-
|
|
159
|
+
- **多账号**:同一家建多份配置,名称自动追加「 2」「 3」…用**备注**区分,列表显示为「供应商 — 备注」。
|
|
160
|
+
- **自定义供应商**:`presets.json` 是供应商目录,加一个 JSON 条目就多一个供应商,无需改代码。可在 `~/.cc-mini/presets.json` 放自定义版覆盖随工具发布的版本。
|
|
161
|
+
- **第三方首次弹登录**:在 `~/.claude.json` 最外层加 `"hasCompletedOnboarding": true`(**只加这个键**,别覆盖整个文件——里面还有你的 MCP 配置)。
|
|
162
|
+
- **更新检查**:主菜单可切「提醒」模式,新版本出现时菜单顶部黄字提示升级命令。每天最多查一次,不自动升级。
|
|
296
163
|
|
|
297
|
-
|
|
164
|
+
---
|
|
298
165
|
|
|
299
|
-
|
|
300
|
-
因为它没记录“已完成引导”。一次性修复:在 `~/.claude.json` 里加一个键
|
|
301
|
-
`"hasCompletedOnboarding": true`。
|
|
166
|
+
## 数据与文件
|
|
302
167
|
|
|
303
|
-
|
|
168
|
+
- **配置(含明文密钥,勿外传)**:`~/.cc-mini/providers.json`(也存界面语言 `lang`、更新检查 `update`)
|
|
169
|
+
- **供应商目录**:随工具发布的 `presets.json`;`~/.cc-mini/presets.json` 可覆盖
|
|
170
|
+
- **「设为默认」写的是用户环境变量**(不是 Claude 配置文件):
|
|
171
|
+
- Windows → 注册表 `HKCU\Environment` + 广播一次变更
|
|
172
|
+
- Unix → shell 启动文件 `# >>> xx >>>` … `# <<< xx <<<` 标记块(幂等重写,按 `$SHELL` 选文件)
|
|
173
|
+
- 语义一致:**只影响新终端**;切到「官方」会清除全部受管变量
|
|
174
|
+
- **不修改任何 Claude Code 配置文件。**
|
|
304
175
|
|
|
305
|
-
|
|
306
|
-
|
|
176
|
+
ccx 只动这 7 个「受管」环境变量,切换时清掉目标不用的:
|
|
177
|
+
`ANTHROPIC_BASE_URL`、`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_API_KEY`、`ANTHROPIC_DEFAULT_OPUS_MODEL`、`ANTHROPIC_DEFAULT_SONNET_MODEL`、`ANTHROPIC_DEFAULT_HAIKU_MODEL`、`CLAUDE_CODE_EFFORT_LEVEL`。
|
|
307
178
|
|
|
308
|
-
|
|
179
|
+
> 💡 需要改 `settings.json`?直接用 Claude Code 的 `/update-config` 说需求(如"允许 npm 命令"),比让外部工具改可靠。
|
|
309
180
|
|
|
310
|
-
|
|
311
|
-
```json
|
|
312
|
-
{
|
|
313
|
-
"hasCompletedOnboarding": true
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
- 文件**不存在**:新建一个,内容就是上面这段。
|
|
181
|
+
---
|
|
317
182
|
|
|
318
|
-
|
|
319
|
-
> 这一步只需做一次(个别版本可能还需其它设置,以官方为准)。
|
|
183
|
+
## FAQ
|
|
320
184
|
|
|
321
|
-
|
|
185
|
+
**一个终端切了,影响另一个吗?** 不影响。「本次启用」进程级,「设为默认」只对新终端生效。
|
|
322
186
|
|
|
323
|
-
|
|
324
|
-
- 供应商目录:随工具发布的 `presets.json`;也可在 `~/.cc-mini/presets.json` 放一份**自定义目录**覆盖它(优先级最高)。
|
|
325
|
-
- 「设为默认」写的是**用户环境变量**(不是 Claude 配置文件):
|
|
326
|
-
- **Windows** → 注册表 `HKCU\Environment` + 广播一次变更;
|
|
327
|
-
- **macOS / Linux** → shell 启动文件(按 `$SHELL` 选 `~/.zshrc` / `~/.bash_profile` / `~/.bashrc` / `~/.profile`)里的
|
|
328
|
-
`# >>> xx >>>` … `# <<< xx <<<` 标记块(幂等重写)。
|
|
329
|
-
- 两者语义一致:**只影响新开终端**;切到「官方」会清除全部受管变量。
|
|
330
|
-
- **不修改任何 Claude 配置文件。**
|
|
187
|
+
**设为默认了,当前终端敲 `claude` 还是旧的?** 正常——当前终端是旧环境,新开即可。
|
|
331
188
|
|
|
332
|
-
|
|
189
|
+
**报 `cannot be parsed as a URL`?** 某配置的 API 地址填了无效值,编辑改正或删除。
|
|
333
190
|
|
|
334
|
-
|
|
335
|
-
不会。「本次启用」是进程级的;「设为默认」写的是用户环境变量,只对**新开**的进程生效,
|
|
336
|
-
运行中的会话在启动时就已定型,不受影响。
|
|
191
|
+
**第三方 effort 没效果?** effort 是 Claude 模型特性,第三方不一定支持。DeepSeek 推荐 `max`,其余留空。
|
|
337
192
|
|
|
338
|
-
|
|
339
|
-
正常。当前终端是旧环境,请**新开一个终端**再敲 `claude`。
|
|
193
|
+
**密钥安全吗?** 明文存本机用户目录,受账户权限保护。别把 `providers.json` 提交到仓库。
|
|
340
194
|
|
|
341
|
-
|
|
342
|
-
那是某个配置的 API 地址填成了无效值(如随手输入的测试串)。进「编辑」改正或删除该配置即可。
|
|
195
|
+
**能指定安装目录吗?** 可以。Windows 安装脚本支持 `-InstallDir`;macOS / Linux 可用 `CCX_INSTALL_DIR` 或 `--install-dir`。只有少数用户需要改,默认安装最省心;如果改过目录,卸载时也传同一个目录。
|
|
343
196
|
|
|
344
|
-
|
|
345
|
-
effort 是 Claude 模型特性,第三方端点未必支持。DeepSeek 官方推荐 `max`,其余各家未必生效,
|
|
346
|
-
留空即可。
|
|
197
|
+
**能手动下载二进制吗?** 可以,到 [GitHub Releases](https://github.com/becomeless/cc-x/releases/latest) 下载对应系统的 zip / tar.gz,解压后把 `xx` / `xx.exe` 放到 PATH 里的目录。普通用户建议用上面的安装命令:会自动选平台、做校验,并处理 PATH / 卸载。
|
|
347
198
|
|
|
348
|
-
|
|
349
|
-
保存在本机用户目录、受账户权限保护。注意别把 `providers.json` 提交到仓库。
|
|
199
|
+
---
|
|
350
200
|
|
|
351
201
|
## 卸载
|
|
352
202
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
ccx 的诞生,源于我自己用 cc-switch 时反复遇到的不顺。这不是批评——cc-switch 很强大、很全能,
|
|
370
|
-
我只是想走另一条更轻的路。
|
|
371
|
-
|
|
372
|
-
所以 ccx 只信奉一条原则:**越简单越好。**
|
|
373
|
-
|
|
374
|
-
- 只做“切 API”这一件事,把它做到位;
|
|
375
|
-
- 能不碰的就不碰——尤其**绝不写 Claude Code 配置文件**(`~/.claude/settings.json`、`~/.claude.json`);
|
|
376
|
-
- 每加一个功能前,先问一句:能不能不加。
|
|
377
|
-
|
|
378
|
-
欢迎 Issue / PR。但请记得:**让它更简单的改动,比让它更强大的改动更受欢迎**;
|
|
379
|
-
任何会写 Claude Code 配置文件的改动都不会被接受。
|
|
203
|
+
1. 先清环境变量:`xx` → 选「官方」→ 设为默认
|
|
204
|
+
2. 卸载本体:
|
|
205
|
+
- Windows 原生版:
|
|
206
|
+
```powershell
|
|
207
|
+
$s = irm https://github.com/becomeless/cc-x/releases/latest/download/install.ps1
|
|
208
|
+
& ([scriptblock]::Create($s)) -Uninstall
|
|
209
|
+
```
|
|
210
|
+
会删除安装文件,并自动清理对应的用户 PATH 条目。
|
|
211
|
+
- macOS / Linux 原生版:
|
|
212
|
+
```bash
|
|
213
|
+
curl -fsSL https://github.com/becomeless/cc-x/releases/latest/download/install.sh | sh -s -- --uninstall
|
|
214
|
+
```
|
|
215
|
+
- npm:`npm uninstall -g @cc-x/cc-x`
|
|
216
|
+
3. 删数据:`rm -rf ~/.cc-mini`
|
|
217
|
+
|
|
218
|
+
---
|
|
380
219
|
|
|
381
220
|
## 许可
|
|
382
221
|
|
package/dist/config/store.js
CHANGED
|
@@ -76,7 +76,9 @@ function normalizeStore(raw, file) {
|
|
|
76
76
|
const providers = obj.providers.map((p) => normalizeProvider(p, file));
|
|
77
77
|
const lang = obj.lang === 'en' ? 'en' : obj.lang === 'zh' ? 'zh' : undefined;
|
|
78
78
|
const current = typeof obj.current === 'string' ? obj.current : (providers[0]?.name ?? '');
|
|
79
|
-
|
|
79
|
+
// 只认已知模式,未知值视为关闭(不回写)。字段顺序须与 Go 版一致:…providers, update?
|
|
80
|
+
const update = obj.update === 'notify' || obj.update === 'auto' ? obj.update : undefined;
|
|
81
|
+
return { current, ...(lang ? { lang } : {}), providers, ...(update ? { update } : {}) };
|
|
80
82
|
}
|
|
81
83
|
function normalizeProvider(raw, file) {
|
|
82
84
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
package/dist/i18n/messages.js
CHANGED
|
@@ -40,6 +40,10 @@ export const messages = {
|
|
|
40
40
|
'menu.exit': { zh: '退出', en: 'Exit' },
|
|
41
41
|
'menu.default': { zh: '(默认)', en: '(default)' },
|
|
42
42
|
'menu.comingSoon': { zh: '(该功能下一步实现)', en: '(coming in the next step)' },
|
|
43
|
+
// 更新检查:菜单开关两态 + 有新版时的横幅({0}=新版本号,{1}=升级命令)
|
|
44
|
+
'menu.updateOff': { zh: '更新检查:关闭', en: 'Update check: off' },
|
|
45
|
+
'menu.updateNotify': { zh: '更新检查:提醒', en: 'Update check: notify' },
|
|
46
|
+
'menu.updateAvailable': { zh: '有新版本 {0} · 升级:{1}', en: 'New version {0} · upgrade: {1}' },
|
|
43
47
|
// —— 动作菜单 ——
|
|
44
48
|
'action.titlePrefix': { zh: '配置:', en: 'Profile: ' },
|
|
45
49
|
'action.session': {
|
package/dist/ui/menus.js
CHANGED
|
@@ -10,6 +10,7 @@ import { launchSession } from '../actions.js';
|
|
|
10
10
|
import { isOfficial, reconcileCurrent, saveStore } from '../config/store.js';
|
|
11
11
|
import { setDefault } from '../env/default.js';
|
|
12
12
|
import { getLang, providerDisplayName, setLang, T } from '../i18n/index.js';
|
|
13
|
+
import { banner as updateBanner, maybeRefresh, MODE_NOTIFY, upgradeCommand } from '../update/update.js';
|
|
13
14
|
import { padDisplay } from '../utils/display.js';
|
|
14
15
|
import { editForm } from './edit.js';
|
|
15
16
|
import { noteSuffix, stateLabel } from './format.js';
|
|
@@ -23,14 +24,27 @@ async function readLine(prompt) {
|
|
|
23
24
|
/** 一级 · 主菜单。布局:[profiles…] '' 新增 语言 '' 退出。 */
|
|
24
25
|
export async function openMenu(paths, store, scope, version, catalog) {
|
|
25
26
|
let sel = 0;
|
|
27
|
+
let refreshed = false;
|
|
26
28
|
for (;;) {
|
|
27
29
|
const n = store.providers.length;
|
|
30
|
+
// 更新检查(仅 notify 模式):首轮触发一次后台刷新;横幅永远读缓存(瞬时、不阻塞)。
|
|
31
|
+
let notice;
|
|
32
|
+
if (store.update === MODE_NOTIFY) {
|
|
33
|
+
if (!refreshed) {
|
|
34
|
+
maybeRefresh(paths.dir);
|
|
35
|
+
refreshed = true;
|
|
36
|
+
}
|
|
37
|
+
const latest = updateBanner(paths.dir, version);
|
|
38
|
+
if (latest)
|
|
39
|
+
notice = T('menu.updateAvailable', latest, upgradeCommand());
|
|
40
|
+
}
|
|
41
|
+
const updLabel = store.update === MODE_NOTIFY ? T('menu.updateNotify') : T('menu.updateOff');
|
|
28
42
|
const buildItems = () => {
|
|
29
43
|
const labels = store.providers.map((p) => {
|
|
30
44
|
const dft = p.name === store.current ? T('menu.default') : '';
|
|
31
45
|
return `${padDisplay(providerDisplayName(p), 16)}${padDisplay(dft, 8)}[${stateLabel(p)}]${noteSuffix(p)}`;
|
|
32
46
|
});
|
|
33
|
-
return [...labels, '', T('menu.newProfile'), T('menu.language'), '', T('menu.exit')];
|
|
47
|
+
return [...labels, '', T('menu.newProfile'), T('menu.language'), updLabel, '', T('menu.exit')];
|
|
34
48
|
};
|
|
35
49
|
const onMove = (from, to) => {
|
|
36
50
|
const ps = store.providers;
|
|
@@ -45,6 +59,7 @@ export async function openMenu(paths, store, scope, version, catalog) {
|
|
|
45
59
|
};
|
|
46
60
|
sel = await selectMenu({
|
|
47
61
|
title: T('menu.mainTitle', version),
|
|
62
|
+
...(notice ? { notice } : {}),
|
|
48
63
|
items: buildItems(),
|
|
49
64
|
colors: { [n + 1]: 'yellow' },
|
|
50
65
|
start: sel,
|
|
@@ -53,7 +68,7 @@ export async function openMenu(paths, store, scope, version, catalog) {
|
|
|
53
68
|
hint: T('menu.mainHint'),
|
|
54
69
|
noNumber: true,
|
|
55
70
|
});
|
|
56
|
-
if (sel < 0 || sel === n +
|
|
71
|
+
if (sel < 0 || sel === n + 5)
|
|
57
72
|
return; // 退出 / Esc / q
|
|
58
73
|
if (sel === n + 1) {
|
|
59
74
|
// 新增配置
|
|
@@ -71,6 +86,14 @@ export async function openMenu(paths, store, scope, version, catalog) {
|
|
|
71
86
|
store.lang = next;
|
|
72
87
|
saveStore(paths, store);
|
|
73
88
|
}
|
|
89
|
+
else if (sel === n + 3) {
|
|
90
|
+
// 更新检查开关:关闭 <-> 提醒(关闭=删字段,与 Go 的 omitempty 对齐)
|
|
91
|
+
if (store.update === MODE_NOTIFY)
|
|
92
|
+
delete store.update;
|
|
93
|
+
else
|
|
94
|
+
store.update = MODE_NOTIFY;
|
|
95
|
+
saveStore(paths, store);
|
|
96
|
+
}
|
|
74
97
|
else if (sel < n) {
|
|
75
98
|
const target = store.providers[sel];
|
|
76
99
|
if (target)
|
package/dist/ui/select.js
CHANGED
|
@@ -41,6 +41,9 @@ export async function selectMenu(opts) {
|
|
|
41
41
|
if (opts.title) {
|
|
42
42
|
lines.push(` ${paint(opts.title, 'cyan')}`, '');
|
|
43
43
|
}
|
|
44
|
+
if (opts.notice) {
|
|
45
|
+
lines.push(` ${paint(opts.notice, 'yellow')}`, '');
|
|
46
|
+
}
|
|
44
47
|
if (opts.status) {
|
|
45
48
|
lines.push(` ${paint(opts.status, 'green')}`, '');
|
|
46
49
|
}
|