@cc-x/cc-x 0.3.0 → 0.4.3

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 CHANGED
@@ -11,9 +11,10 @@ purely through environment variables, so it is **physically incapable of clobber
11
11
  plugins, or hooks** — and it lets **multiple terminals each run a different API at the
12
12
  same time, without interfering with one another**.
13
13
 
14
- > 🌍 **Cross-platform:** one `npm install -g @cc-x/cc-x` installs it on **Windows / macOS / Linux**
15
- > (the command is still `xx`; the npm package is `@cc-x/cc-x`), with a built-in **English / Chinese
16
- > UI toggle**. A PowerShell edition is still available on Windows (see [Install](#install)).
14
+ > **Native Go build:** GitHub Releases provide a lightweight `xx` / `xx.exe` with no
15
+ > Node.js requirement for Windows x64, macOS Intel / Apple Silicon, and Linux x64 / arm64.
16
+ > If you prefer npm, `npm install -g @cc-x/cc-x` is still available (the terminal command
17
+ > is still `xx`).
17
18
 
18
19
  ---
19
20
 
@@ -67,18 +68,43 @@ place, or prefer an all-in-one tool.
67
68
 
68
69
  ## Requirements
69
70
 
70
- - **Node.js 18** needed by the cross-platform npm edition (`cc-x`). Claude Code itself
71
- depends on Node, so you most likely already have it.
71
+ - **Native Go build:** Windows 10/11 x64, macOS Intel / Apple Silicon, Linux x64 / arm64;
72
+ no Node.js required.
73
+ - **Cross-platform npm build:** Node.js ≥ 18 (package `@cc-x/cc-x`).
72
74
  - **Claude Code installed (`claude` on PATH)** — "Use this session" launches `claude`.
73
- - *(optional, legacy)* PowerShell 7+ — the PowerShell edition is still offered on Windows.
74
-
75
- > Fully verified on **Windows**; "Set as default" on **macOS / Linux** (writing the shell
76
- > startup file) is the new cross-platform capability, while "Use this session" is identical
77
- > everywhere. Feedback on other platforms is welcome.
78
75
 
79
76
  ## Install
80
77
 
81
- **Option 1: npm (recommended, cross-platform)**
78
+ **Native Windows build (recommended)**
79
+
80
+ ```powershell
81
+ irm https://github.com/becomeless/cc-x/releases/latest/download/install.ps1 | iex
82
+ ```
83
+
84
+ The installer downloads the latest GitHub Release asset named `ccx_*_windows_amd64.zip`,
85
+ installs it to `%LOCALAPPDATA%\Programs\ccx`, and adds that directory to the user PATH.
86
+ Open a new terminal afterwards and run:
87
+
88
+ ```powershell
89
+ xx --version
90
+ ```
91
+
92
+ **Native macOS / Linux build (recommended)**
93
+
94
+ ```bash
95
+ curl -fsSL https://github.com/becomeless/cc-x/releases/latest/download/install.sh | sh
96
+ ```
97
+
98
+ The installer downloads the matching `ccx_*_darwin_*.tar.gz` or `ccx_*_linux_*.tar.gz`
99
+ asset, installs `xx` to `~/.local/bin` (override with `CCX_INSTALL_DIR` or
100
+ `--install-dir`), and verifies `checksums.txt` when available. If that directory is not
101
+ on PATH, add it as prompted, open a new terminal, and run:
102
+
103
+ ```bash
104
+ xx --version
105
+ ```
106
+
107
+ **Cross-platform npm build**
82
108
 
83
109
  ```bash
84
110
  npm install -g @cc-x/cc-x
@@ -87,24 +113,26 @@ npm install -g @cc-x/cc-x
87
113
  Then type `xx` in any terminal. Update with `npm update -g @cc-x/cc-x`; remove with
88
114
  `npm uninstall -g @cc-x/cc-x`. (The npm package is `@cc-x/cc-x`; the terminal command is `xx`.)
89
115
 
90
- **Option 2: PowerShell Gallery (Windows, legacy)**
116
+ **From source (dev / custom)**
91
117
 
92
- ```powershell
93
- Install-Module ccx
118
+ ```bash
119
+ git clone https://github.com/becomeless/cc-x
120
+ cd cc-x
94
121
  ```
95
122
 
96
- Then type `xx` in any terminal (the module auto-loads). Update with `Update-Module ccx`;
97
- remove with `Uninstall-Module ccx`.
123
+ Native Go release build with version injection and multi-platform assets:
98
124
 
99
- **Option 3: from source (dev / custom)**
125
+ ```powershell
126
+ .\scripts\build-release.ps1 -Version 0.4.2
127
+ .\dist\release\ccx_0.4.2_windows_amd64\xx.exe --version
128
+ ```
100
129
 
101
- ```bash
102
- # npm edition
103
- git clone https://github.com/becomeless/cc-x
104
- cd ccx && npm install && npm run build && npm link # then `xx` is available
130
+ npm build:
105
131
 
106
- # or the PowerShell edition
107
- pwsh -ExecutionPolicy Bypass -File .\ccx\install.ps1 # registers an xx function in $PROFILE (idempotent)
132
+ ```bash
133
+ npm install
134
+ npm run build
135
+ npm link # then `xx` is available
108
136
  ```
109
137
 
110
138
  **Open a new terminal afterwards.**
@@ -130,8 +158,8 @@ scopes:
130
158
  | Effect on other / running sessions | **None** | **None** (env is fixed at process start) |
131
159
  | Typical use | Parallel terminals, each on a different API | Your usual "main" API |
132
160
 
133
- **Parallel example:** open 4 terminals and run `xx 官方 -Session`, `xx DeepSeek -Session`,
134
- `xx 智谱GLM -Session`, `xx 小米MiMo -Session` — four Claude sessions running at once, each
161
+ **Parallel example:** open 4 terminals and run `xx 官方 -s`, `xx DeepSeek -s`,
162
+ `xx 智谱GLM -s`, `xx 小米MiMo -s` — four Claude sessions running at once, each
135
163
  on its own API, independent.
136
164
 
137
165
  **Why not switch via a global config file?** Because `settings.json` is global and editing
@@ -153,7 +181,7 @@ up/down and reorder** — saved instantly:
153
181
  - **Delete** — removes the profile (with confirmation; keep "官方").
154
182
  - **Back**.
155
183
  - **+ New profile**.
156
- - **🌐 语言 / Language** — toggle the UI between English and Chinese instantly (remembered;
184
+ - **语言 / Language** — toggle the UI between English and Chinese instantly (remembered;
157
185
  written back to `lang` in `~/.cc-mini/providers.json`).
158
186
  - **Quit**.
159
187
 
@@ -179,9 +207,6 @@ xx --lang en # UI in English for this run (zh / en)
179
207
  xx --help # show all options
180
208
  ```
181
209
 
182
- - The **npm edition** uses `-s/--session`, `-l/--list`, `--lang`, `--help`; the **PowerShell
183
- edition** uses `-Session`, `-List` (no `--lang`).
184
-
185
210
  ## Profile fields
186
211
 
187
212
  | Field | Env var | Notes |
@@ -312,9 +337,16 @@ not support it. DeepSeek recommends `max`; leave others empty.
312
337
 
313
338
  - **Clear env vars first**: run `xx` → Set as default → 官方 to clear all managed variables.
314
339
  - Remove the tool itself:
315
- - npm edition `npm uninstall -g @cc-x/cc-x`;
316
- - PowerShell edition `Uninstall-Module ccx`, or delete the `# >>> xx >>>` … `# <<< xx <<<`
317
- block from your `$PROFILE`;
340
+ - native Windows build: delete `%LOCALAPPDATA%\Programs\ccx` and remove that directory
341
+ from the user PATH, or run:
342
+ ```powershell
343
+ powershell -NoProfile -ExecutionPolicy Bypass -Command "$s = irm https://github.com/becomeless/cc-x/releases/latest/download/install.ps1; & ([scriptblock]::Create($s)) -Uninstall"
344
+ ```
345
+ - native macOS / Linux build:
346
+ ```bash
347
+ curl -fsSL https://github.com/becomeless/cc-x/releases/latest/download/install.sh | sh -s -- --uninstall
348
+ ```
349
+ - npm build: `npm uninstall -g @cc-x/cc-x`;
318
350
  - on macOS / Linux, also remove the `# >>> xx >>>` marker block from your shell startup file
319
351
  if you ever used "Set as default".
320
352
  - Delete the data dir `~/.cc-mini/`.
package/README.md CHANGED
@@ -8,8 +8,9 @@ Anthropic 兼容 API(DeepSeek、智谱 GLM、小米 MiMo 等)之间快速切
8
8
  它最大的不同:**不写任何 Claude Code 配置文件**,切换只靠环境变量——所以从设计上**不可能弄丢你的
9
9
  MCP / 插件 / hooks**;并且支持**多个终端同时各用各的 API、互不干扰**。
10
10
 
11
- > 🌍 **全平台版**:一条 `npm install -g @cc-x/cc-x` 即可在 **Windows / macOS / Linux** 安装(命令仍是 `xx`,
12
- > npm 包名是 `@cc-x/cc-x`),并内建**中英文界面切换**。Windows 上还保留了 PowerShell 版(见[安装](#安装))。
11
+ > **Go 原生版**:GitHub Release 提供轻量 `xx` / `xx.exe`,不需要 Node.js,覆盖
12
+ > Windows x64、macOS Intel / Apple Silicon、Linux x64 / arm64。偏好 npm 的用户仍可使用
13
+ > `npm install -g @cc-x/cc-x`(命令仍是 `xx`)。
13
14
 
14
15
  ---
15
16
 
@@ -85,16 +86,40 @@ Codex / Gemini 等多个 CLI,它更合适。ccx 走相反的**极简路线**
85
86
 
86
87
  ## 环境要求
87
88
 
88
- - **Node.js 18**:npm 全平台版(`cc-x`)需要它。Claude Code 本身就依赖 Node,通常你已具备。
89
+ - **Go 原生版**:Windows 10/11 x64、macOS Intel / Apple Silicon、Linux x64 / arm64;不需要 Node.js。
90
+ - **npm 全平台版**:Node.js ≥ 18(包名 `@cc-x/cc-x`)。
89
91
  - **已安装 Claude Code(`claude` 命令在 PATH 中)**:「本次启用」会直接调用 `claude`。
90
- - *(可选,旧版)* PowerShell 7+:Windows 上仍保留 PowerShell 版。
91
-
92
- > 当前在 **Windows** 上完整验证;**macOS / Linux** 的「设为默认」(写 shell 启动文件)是跨平台新增能力,
93
- > 「本次启用」全平台一致。欢迎在其它平台试用并反馈。
94
92
 
95
93
  ## 安装
96
94
 
97
- **方式一:npm(推荐,全平台)**
95
+ **Windows 原生版(推荐)**
96
+
97
+ ```powershell
98
+ irm https://github.com/becomeless/cc-x/releases/latest/download/install.ps1 | iex
99
+ ```
100
+
101
+ 安装器会下载最新 GitHub Release 里的 `ccx_*_windows_amd64.zip`,安装到
102
+ `%LOCALAPPDATA%\Programs\ccx`,并把该目录加入用户 PATH。安装后新开终端,运行:
103
+
104
+ ```powershell
105
+ xx --version
106
+ ```
107
+
108
+ **macOS / Linux 原生版(推荐)**
109
+
110
+ ```bash
111
+ curl -fsSL https://github.com/becomeless/cc-x/releases/latest/download/install.sh | sh
112
+ ```
113
+
114
+ 安装器会按当前系统下载 `ccx_*_darwin_*.tar.gz` 或 `ccx_*_linux_*.tar.gz`,安装到
115
+ `~/.local/bin`(可用 `CCX_INSTALL_DIR` 或 `--install-dir` 改目录),并校验 `checksums.txt`。
116
+ 如果该目录不在 PATH,按提示加入后新开终端,运行:
117
+
118
+ ```bash
119
+ xx --version
120
+ ```
121
+
122
+ **npm 全平台版**
98
123
 
99
124
  ```bash
100
125
  npm install -g @cc-x/cc-x
@@ -103,23 +128,26 @@ npm install -g @cc-x/cc-x
103
128
  装好后在任意终端敲 `xx` 即可。升级:`npm update -g @cc-x/cc-x`;卸载:`npm uninstall -g @cc-x/cc-x`。
104
129
  (npm 包名是 `@cc-x/cc-x`,终端命令是 `xx`。)
105
130
 
106
- **方式二:PowerShell Gallery(Windows 旧版)**
131
+ **从源码(开发 / 自定义)**
107
132
 
108
- ```powershell
109
- Install-Module ccx
133
+ ```bash
134
+ git clone https://github.com/becomeless/cc-x
135
+ cd cc-x
110
136
  ```
111
137
 
112
- 之后在任意终端敲 `xx`(模块会自动加载)。升级:`Update-Module ccx`;卸载:`Uninstall-Module ccx`。
138
+ Go 原生 Release 构建(注入版本号并生成多平台资产):
139
+
140
+ ```powershell
141
+ .\scripts\build-release.ps1 -Version 0.4.2
142
+ .\dist\release\ccx_0.4.2_windows_amd64\xx.exe --version
143
+ ```
113
144
 
114
- **方式三:从源码(开发 / 自定义)**
145
+ npm 版开发:
115
146
 
116
147
  ```bash
117
- # npm
118
- git clone https://github.com/becomeless/cc-x
119
- cd ccx && npm install && npm run build && npm link # 之后 xx 可用
120
-
121
- # 或 PowerShell 旧版
122
- pwsh -ExecutionPolicy Bypass -File .\ccx\install.ps1 # 在 $PROFILE 注册 xx 函数(幂等)
148
+ npm install
149
+ npm run build
150
+ npm link # 之后 xx 可用
123
151
  ```
124
152
 
125
153
  **安装后请新开一个终端。**
@@ -144,8 +172,8 @@ pwsh -ExecutionPolicy Bypass -File .\ccx\install.ps1 # 在 $PROFILE 注册 xx
144
172
  | 对其它 / 运行中会话 | **零影响** | **零影响**(环境变量在进程启动时定型,运行中不会变) |
145
173
  | 典型场景 | 多终端并行,各用各 API 互不干扰 | 设定你最常用的“主力 API” |
146
174
 
147
- **并行多终端示例**:你可以同时开 4 个终端,分别 `xx 官方 -Session`、`xx DeepSeek -Session`、
148
- `xx 智谱GLM -Session`、`xx 小米MiMo -Session`,得到 4 个同时运行、各用各 API、互不干扰的 Claude。
175
+ **并行多终端示例**:你可以同时开 4 个终端,分别 `xx 官方 -s`、`xx DeepSeek -s`、
176
+ `xx 智谱GLM -s`、`xx 小米MiMo -s`,得到 4 个同时运行、各用各 API、互不干扰的 Claude。
149
177
 
150
178
  **为什么不用全局配置文件来切?** 因为 `settings.json` 是全局共享的,改它会波及**正在运行**
151
179
  的其它会话(典型表现:另一个终端突然报 `... cannot be parsed as a URL` 之类)。ccx 用环境
@@ -163,7 +191,7 @@ pwsh -ExecutionPolicy Bypass -File .\ccx\install.ps1 # 在 $PROFILE 注册 xx
163
191
  - **删除** — 删除该配置(会二次确认;建议保留「官方」)。
164
192
  - **返回**。
165
193
  - **+ 新增配置** — 新建一个空配置并进入编辑表单。
166
- - **🌐 语言 / Language** — 中英文界面即时切换(选择会记住,写回 `~/.cc-mini/providers.json` 的 `lang`)。
194
+ - **语言 / Language** — 中英文界面即时切换(选择会记住,写回 `~/.cc-mini/providers.json` 的 `lang`)。
167
195
  - **退出**。
168
196
 
169
197
  **编辑表单**:`↑↓` 选要改的字段,`Enter` 进入修改;继续往下可选「保存并返回」/「放弃修改」。
@@ -187,7 +215,6 @@ xx --help # 查看全部参数
187
215
 
188
216
  - `xx <名称>`:默认是「设为默认」(写用户环境变量)。
189
217
  - 加 `-s` / `--session`:改为「本次启用」(进程级 + 启动 Claude)。
190
- - **npm 版**用 `-s/--session`、`-l/--list`、`--lang`、`--help`;**PowerShell 旧版**用 `-Session`、`-List`(无 `--lang`)。
191
218
 
192
219
  ## 配置字段说明
193
220
 
@@ -325,8 +352,15 @@ effort 是 Claude 模型特性,第三方端点未必支持。DeepSeek 官方
325
352
 
326
353
  - **先清环境变量**:在 `xx` 里执行「设为默认 → 官方」一次清除全部受管变量(比手删干净)。
327
354
  - 卸载命令本体:
328
- - npm `npm uninstall -g @cc-x/cc-x`;
329
- - PowerShell 旧版 → `Uninstall-Module ccx`,或从 `$PROFILE` 删掉 `# >>> xx >>>` … `# <<< xx <<<` 之间的内容;
355
+ - Windows 原生版:删除 `%LOCALAPPDATA%\Programs\ccx`,并从用户 PATH 移除这个目录;或运行:
356
+ ```powershell
357
+ powershell -NoProfile -ExecutionPolicy Bypass -Command "$s = irm https://github.com/becomeless/cc-x/releases/latest/download/install.ps1; & ([scriptblock]::Create($s)) -Uninstall"
358
+ ```
359
+ - macOS / Linux 原生版:
360
+ ```bash
361
+ curl -fsSL https://github.com/becomeless/cc-x/releases/latest/download/install.sh | sh -s -- --uninstall
362
+ ```
363
+ - npm 版:`npm uninstall -g @cc-x/cc-x`;
330
364
  - macOS / Linux 若用过「设为默认」→ 顺手删掉 shell 启动文件里的 `# >>> xx >>>` 标记块。
331
365
  - 删除数据目录 `~/.cc-mini/`。
332
366
 
@@ -62,7 +62,7 @@ export function defaultStore() {
62
62
  /**
63
63
  * 把任意解析结果规整为合法 Store。
64
64
  *
65
- * 字段级**宽松容错**(缺 lang / 缺 note / 缺 builtin / 缺 env 都不报错),保证老用户文件零迁移;
65
+ * 字段级**宽松容错**(缺 lang / 缺 note / 缺 builtin / 缺 env 都不报错),保持既有数据格式兼容;
66
66
  * 但结构级**严格校验**:顶层必须是对象、`providers` 必须是数组、每个配置的 name/env 结构必须合法
67
67
  * —— 否则抛 StoreError('format')。
68
68
  * 这是为了堵住「语法合法但结构损坏的 JSON 被静默规整成空 providers、用户一保存就覆盖丢数据」的坑([P1])。
@@ -2,7 +2,6 @@
2
2
  * 数据层共享类型与常量。
3
3
  *
4
4
  * 数据格式必须与现版 PowerShell 完全兼容(老用户的 ~/.cc-mini/providers.json 能直接读)。
5
- * 详见 docs/npm-rewrite-plan.md §3。
6
5
  */
7
6
  /** 受管的 7 个环境变量(工具只动这些,其它一律不碰)。详见 plan §2。 */
8
7
  export const KNOWN_KEYS = [
@@ -36,7 +36,7 @@ export const messages = {
36
36
  zh: '↑↓ 选择 · Enter 进入 · Shift+↑↓(或 PgUp/PgDn)排序 · q 退出',
37
37
  en: '↑↓ move · Enter open · Shift+↑↓ (or PgUp/PgDn) reorder · q quit',
38
38
  },
39
- 'menu.newProfile': { zh: '新增配置', en: '+ New profile' },
39
+ 'menu.newProfile': { zh: '新增配置', en: 'New profile' },
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)' },
@@ -56,7 +56,7 @@ export const messages = {
56
56
  'action.hint': { zh: '↑↓ 选择 · Enter 确认 · q 返回', en: '↑↓ move · Enter select · q back' },
57
57
  'action.deleteConfirm': { zh: '确认删除 [{0}]? (y/N): ', en: 'Delete [{0}]? (y/N): ' },
58
58
  'action.deleteOfficialWarn': { zh: '建议保留『官方』。', en: 'Keeping "Official" is recommended.' },
59
- 'menu.language': { zh: '🌐 切换到 English', en: '🌐 切换到中文' },
59
+ 'menu.language': { zh: '切换到 English', en: '切换到中文' },
60
60
  // —— 通用占位 ——
61
61
  'empty.paren': { zh: '(空)', en: '(empty)' },
62
62
  // —— 编辑表单 ——
@@ -76,8 +76,8 @@ export const messages = {
76
76
  'edit.field.sonnet': { zh: 'sonnet→ 模型 ', en: 'sonnet→ model ' },
77
77
  'edit.field.haiku': { zh: 'haiku → 模型 ', en: 'haiku → model ' },
78
78
  'edit.field.effort': { zh: 'effort 思考档 ', en: 'effort level ' },
79
- 'edit.toggleSecretShow': { zh: '👁 显示密钥明文(当前隐藏)', en: '👁 Show key in plaintext (now hidden)' },
80
- 'edit.toggleSecretHide': { zh: '🙈 隐藏密钥(当前明文)', en: '🙈 Hide key (now shown)' },
79
+ 'edit.toggleSecretShow': { zh: '显示密钥明文(当前隐藏)', en: 'Show key in plaintext (now hidden)' },
80
+ 'edit.toggleSecretHide': { zh: '隐藏密钥(当前明文)', en: 'Hide key (now shown)' },
81
81
  'edit.save': { zh: '保存并返回', en: 'Save & back' },
82
82
  'edit.discard': { zh: '放弃修改', en: 'Discard' },
83
83
  'edit.nameEmpty': { zh: '还没选供应商(或自定义名称),未保存。', en: 'No provider/name chosen yet; not saved.' },
package/dist/ui/edit.js CHANGED
@@ -42,12 +42,13 @@ export async function editForm(prov, store, catalog) {
42
42
  { action: 'sonnet', label: `${T('edit.field.sonnet')}: ${v(W.sonnet)}` },
43
43
  { action: 'haiku', label: `${T('edit.field.haiku')}: ${v(W.haiku)}` },
44
44
  { action: 'effort', label: `${T('edit.field.effort')}: ${v(W.effort)}` },
45
+ { action: 'sep', label: '' },
45
46
  { action: 'toggle', label: showSecret ? T('edit.toggleSecretHide') : T('edit.toggleSecretShow') },
46
47
  { action: 'sep', label: '' },
47
48
  { action: 'save', label: T('edit.save') },
48
49
  { action: 'discard', label: T('edit.discard') },
49
50
  ];
50
- const sel = await selectMenu({ title: T('edit.title'), items: rows.map((r) => r.label), start, hint: T('edit.hint') });
51
+ const sel = await selectMenu({ title: T('edit.title'), items: rows.map((r) => r.label), start, hint: T('edit.hint'), noNumber: true });
51
52
  if (sel < 0)
52
53
  return false; // Esc / q = 放弃
53
54
  start = sel;
package/dist/ui/menus.js CHANGED
@@ -51,6 +51,7 @@ export async function openMenu(paths, store, scope, version, catalog) {
51
51
  movableCount: n,
52
52
  onMove,
53
53
  hint: T('menu.mainHint'),
54
+ noNumber: true,
54
55
  });
55
56
  if (sel < 0 || sel === n + 4)
56
57
  return; // 退出 / Esc / q
@@ -87,7 +88,7 @@ async function actionMenu(paths, store, p, scope, catalog) {
87
88
  const dft = p.name === store.current ? T('menu.default') : '';
88
89
  const title = `${T('action.titlePrefix')}${providerDisplayName(p)}${dft}${noteSuffix(p)} [${stateLabel(p)}]`;
89
90
  const items = [T('action.session'), T('action.setDefault'), T('action.edit'), T('action.delete'), T('action.back')];
90
- sel = await selectMenu({ title, items, start: sel, ...(flash ? { status: flash } : {}), hint: T('action.hint') });
91
+ sel = await selectMenu({ title, items, start: sel, ...(flash ? { status: flash } : {}), hint: T('action.hint'), noNumber: true });
91
92
  flash = undefined;
92
93
  if (sel === 0) {
93
94
  launchSession(p);
@@ -14,6 +14,7 @@ export async function pickProvider(catalog, current) {
14
14
  title: T('pick.provider.title', current || T('pick.provider.none')),
15
15
  items,
16
16
  hint: T('pick.hint'),
17
+ noNumber: true,
17
18
  });
18
19
  if (sel < 0 || sel === items.length - 1)
19
20
  return null;
@@ -30,7 +31,7 @@ export async function pickProviderUrl(preset, current) {
30
31
  return urls[0]?.url ?? current;
31
32
  const labels = urls.map((u) => `${padDisplay(u.label, 12)} ${u.url || T('empty.paren')}`);
32
33
  const items = [...labels, T('pick.noChange')];
33
- const sel = await selectMenu({ title: T('pick.providerUrl.title', preset.name), items, hint: T('pick.hint') });
34
+ const sel = await selectMenu({ title: T('pick.providerUrl.title', preset.name), items, hint: T('pick.hint'), noNumber: true });
34
35
  if (sel < 0 || sel === items.length - 1)
35
36
  return current;
36
37
  return urls[sel]?.url ?? current;
@@ -54,7 +55,7 @@ export async function pickBaseUrl(current, store, catalog) {
54
55
  }
55
56
  }
56
57
  const items = [...entries.map((e) => e.label), T('pick.manual'), T('pick.noChange')];
57
- const sel = await selectMenu({ title: T('pick.base.title', current || T('empty.paren')), items, hint: T('pick.hint') });
58
+ const sel = await selectMenu({ title: T('pick.base.title', current || T('empty.paren')), items, hint: T('pick.hint'), noNumber: true });
58
59
  if (sel < 0 || sel === items.length - 1)
59
60
  return current;
60
61
  if (sel < entries.length)
@@ -69,7 +70,7 @@ export async function pickBaseUrl(current, store, catalog) {
69
70
  /** 选认证字段:AUTH_TOKEN / API_KEY / 不改。 */
70
71
  export async function pickAuth(current) {
71
72
  const items = [T('pick.auth.token'), T('pick.auth.apikey'), T('pick.noChange')];
72
- const sel = await selectMenu({ title: T('pick.auth.title', current), items, hint: T('pick.hint') });
73
+ const sel = await selectMenu({ title: T('pick.auth.title', current), items, hint: T('pick.hint'), noNumber: true });
73
74
  if (sel === 0)
74
75
  return 'AUTH_TOKEN';
75
76
  if (sel === 1)
@@ -84,6 +85,7 @@ export async function pickEffort(current) {
84
85
  title: T('pick.effort.title', current || T('empty.paren')),
85
86
  items,
86
87
  hint: T('pick.effort.hint'),
88
+ noNumber: true,
87
89
  });
88
90
  if (sel < 0 || sel === items.length - 1)
89
91
  return current;
package/dist/ui/select.js CHANGED
@@ -50,10 +50,11 @@ export async function selectMenu(opts) {
50
50
  lines.push('');
51
51
  continue;
52
52
  }
53
+ const num = opts.noNumber ? '' : `${i + 1}. `; // 行首序号,与数字键直选对应
53
54
  if (i === idx)
54
- lines.push(paint(` ▶ ${it}`, 'green'));
55
+ lines.push(paint(` ▶ ${num}${it}`, 'green'));
55
56
  else
56
- lines.push(paint(` ${it}`, opts.colors?.[i] ?? 'none'));
57
+ lines.push(paint(` ${num}${it}`, opts.colors?.[i] ?? 'none'));
57
58
  }
58
59
  lines.push('');
59
60
  if (opts.hint)
@@ -114,7 +115,7 @@ export async function selectMenu(opts) {
114
115
  break;
115
116
  }
116
117
  const ch = str ?? '';
117
- if (/^[0-9]$/.test(ch)) {
118
+ if (!opts.noNumber && /^[0-9]$/.test(ch)) {
118
119
  const n = Number.parseInt(ch, 10);
119
120
  if (n >= 1 && n <= items.length && items[n - 1] !== '')
120
121
  cleanup(n - 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cc-x/cc-x",
3
- "version": "0.3.0",
3
+ "version": "0.4.3",
4
4
  "description": "Claude Code API 切换器(命令 xx):在官方账号与第三方 Anthropic 兼容 API 间切换,纯环境变量、不碰 Claude Code 配置文件。",
5
5
  "keywords": [
6
6
  "claude",
@@ -27,7 +27,14 @@
27
27
  "xx": "dist/index.js"
28
28
  },
29
29
  "files": [
30
- "dist",
30
+ "dist/**/*.js",
31
+ "!dist/release/**",
32
+ "!dist/**/*.exe",
33
+ "!dist/**/*.zip",
34
+ "!dist/**/*.md",
35
+ "!dist/**/*.txt",
36
+ "!dist/**/LICENSE",
37
+ "!dist/**/presets.json",
31
38
  "presets.json",
32
39
  "README.md",
33
40
  "README.en.md"