@cc-x/cc-x 0.4.8 → 0.4.10

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
@@ -29,7 +29,7 @@ different path: **switching happens purely at the environment-variable layer.**
29
29
  reads or writes any Claude Code config file. Your MCP, plugins, hooks — it won't touch them.
30
30
 
31
31
  ```text
32
- CC-X v0.4.7 · Claude Code API switcher Default: Official
32
+ CC-X v0.4.8 · Claude Code API switcher Default: Official
33
33
 
34
34
  ▶ Official (default)[Logged in]
35
35
  DeepSeek [Key set] — work
@@ -178,7 +178,7 @@ cc-switch is an excellent full-featured GUI; CC-X takes the opposite, minimal ap
178
178
 
179
179
  > CC-X cares more about boundaries than features.
180
180
 
181
- Claude Code already has its own config system, MCP ecosystem, and session state. CC-X is not trying to become a control panel above it, or to copy user config into another database. It stands at one narrow point before Claude Code starts: prepare the 7 managed environment variables, then let Claude Code run.
181
+ Claude Code already has its own config system, MCP ecosystem, and session state. CC-X is not trying to become a control panel above it, or to copy user config into another database. It stands at one narrow point before Claude Code starts: prepare the 9 managed environment variables, then let Claude Code run.
182
182
 
183
183
  That constraint is deliberate: no writes to Claude Code config files, no MCP management, no automatic migration, no resident background controller. If process environment variables can solve it, CC-X avoids global files; if a choice matters, the user makes it explicitly. Doing less keeps the failure surface small.
184
184
 
@@ -199,6 +199,8 @@ Issues / PRs are welcome, but the direction is clear: **make switching steadier,
199
199
  | sonnet → model | `ANTHROPIC_DEFAULT_SONNET_MODEL` | |
200
200
  | haiku → model | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | |
201
201
  | effort level | `CLAUDE_CODE_EFFORT_LEVEL` | `low`–`max`; `auto` = model default; empty = unset. Third parties may not honor it |
202
+ | Disable nonessential traffic | `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | `1` disables nonessential Claude Code traffic; empty = unset. Zhipu GLM defaults to `1` |
203
+ | Context window | `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | Fill with a Claude Code-supported window value; empty = unset |
202
204
 
203
205
  > CC-X **deliberately does not set** `ANTHROPIC_MODEL`. Use `/model opus|sonnet|haiku` in-session;
204
206
  > the mapping table translates to the provider's real model name.
@@ -212,12 +214,12 @@ Issues / PRs are welcome, but the direction is clear: **make switching steadier,
212
214
 
213
215
  ### Pre-seeded profiles
214
216
 
215
- | Profile | BASE_URL | OPUS / SONNET | HAIKU (incl. background) | effort |
216
- |---|---|---|---|---|
217
- | Official | empty (logged-in) | — | — | — |
218
- | DeepSeek | `https://api.deepseek.com/anthropic` | `deepseek-v4-pro` | `deepseek-v4-flash` | `max` (recommended) |
219
- | Zhipu GLM | `https://open.bigmodel.cn/api/anthropic` | `GLM-4.7` | `glm-4.5-air` | — |
220
- | Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` | `mimo-v2.5-pro` | `mimo-v2.5-pro` | — |
217
+ | Profile | BASE_URL | OPUS / SONNET | HAIKU (incl. background) | effort | Extra env |
218
+ |---|---|---|---|---|---|
219
+ | Official | empty (logged-in) | — | — | — | — |
220
+ | DeepSeek | `https://api.deepseek.com/anthropic` | `deepseek-v4-pro` | `deepseek-v4-flash` | `max` (recommended) | — |
221
+ | Zhipu GLM | `https://open.bigmodel.cn/api/anthropic` | `GLM-4.7` | `glm-4.5-air` | — | `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` |
222
+ | Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` | `mimo-v2.5-pro` | `mimo-v2.5-pro` | — | — |
221
223
 
222
224
  > Model names change as providers update. Xiaomi MiMo has both pay-as-you-go and TokenPlan
223
225
  > endpoints; you pick one when selecting the provider.
@@ -228,9 +230,9 @@ Issues / PRs are welcome, but the direction is clear: **make switching steadier,
228
230
  with ` 2`, ` 3`… Use **Note** to tell them apart, shown as "Provider — Note".
229
231
  - **Custom providers**: `presets.json` is the provider catalog; add a JSON entry to offer a new
230
232
  one, no code change. Drop `~/.cc-mini/presets.json` to override the shipped catalog.
231
- - **First-launch login prompt**: third-party APIs may still show onboarding. Add
232
- `"hasCompletedOnboarding": true` to `~/.claude.json` (**only this key** don't overwrite
233
- the file; it also holds your MCP config).
233
+ - **First-launch login prompt**: before launching a third-party profile, CC-X reads
234
+ `hasCompletedOnboarding` from `~/.claude.json` and prints a non-blocking hint when onboarding
235
+ is unfinished. It does not write the file; dismiss or skip the Claude Code prompt if it appears.
234
236
  - **Update check**: toggle to "notify" in the menu — a yellow one-liner appears atop the menu
235
237
  when a new release is out. At most one check per day; never auto-upgrades.
236
238
 
@@ -244,11 +246,13 @@ Issues / PRs are welcome, but the direction is clear: **make switching steadier,
244
246
  - Windows → registry `HKCU\Environment` + one change broadcast
245
247
  - Unix → `# >>> xx >>>` … `# <<< xx <<<` marker block in shell startup file (idempotent rewrite, chosen by `$SHELL`)
246
248
  - Same semantics either way: **only affects new terminals**; switching to "Official" clears all managed vars
247
- - **No Claude Code config file is ever modified.**
249
+ - **No Claude Code config file is ever modified.** Before third-party launches, CC-X only reads
250
+ the onboarding field in `~/.claude.json` to decide whether to print a hint.
248
251
 
249
- CC-X only touches these 7 "managed" variables (and clears the ones a target profile doesn't use):
252
+ CC-X only touches these 9 "managed" variables (and clears the ones a target profile doesn't use):
250
253
  `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY`, `ANTHROPIC_DEFAULT_OPUS_MODEL`,
251
- `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL`, `CLAUDE_CODE_EFFORT_LEVEL`.
254
+ `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL`, `CLAUDE_CODE_EFFORT_LEVEL`,
255
+ `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, `CLAUDE_CODE_AUTO_COMPACT_WINDOW`.
252
256
 
253
257
  > 💡 To change `settings.json`, use Claude Code's own `/update-config` and describe what you want
254
258
  > in natural language (e.g. "allow npm commands") — safer than letting an external tool rewrite it.
package/README.md CHANGED
@@ -28,7 +28,7 @@ CC-X 把这事儿做到了最简——切换只在环境变量层,**不读写
28
28
  你的 MCP、插件、hooks,它碰都不会碰。
29
29
 
30
30
  ```text
31
- CC-X v0.4.7 · Claude Code API 切换器 默认:官方
31
+ CC-X v0.4.8 · Claude Code API 切换器 默认:官方
32
32
 
33
33
  ▶ 官方 (默认)[登录态]
34
34
  DeepSeek [密钥已设] — 公司
@@ -168,7 +168,7 @@ cc-switch 是优秀的全能 GUI;CC-X 走相反的极简路线。
168
168
 
169
169
  > CC-X 的边界比功能更重要。
170
170
 
171
- Claude Code 已经有自己的配置系统、MCP 生态和会话状态。CC-X 不想再造一个"上层控制台",也不想把用户的配置收编进自己的数据库。它只站在 Claude Code 进程启动前的那一小步:把 7 个受管环境变量准备好,然后让 Claude Code 自己工作。
171
+ Claude Code 已经有自己的配置系统、MCP 生态和会话状态。CC-X 不想再造一个"上层控制台",也不想把用户的配置收编进自己的数据库。它只站在 Claude Code 进程启动前的那一小步:把 9 个受管环境变量准备好,然后让 Claude Code 自己工作。
172
172
 
173
173
  所以它的取舍是有意的:不写 Claude Code 配置文件,不接管 MCP,不做自动迁移,不做后台常驻管理。能用进程环境变量解决,就不碰全局文件;能让用户显式选择,就不替用户自动决定。少做一点,是为了把风险面压到足够小。
174
174
 
@@ -189,6 +189,8 @@ Claude Code 已经有自己的配置系统、MCP 生态和会话状态。CC-X
189
189
  | sonnet → 模型 | `ANTHROPIC_DEFAULT_SONNET_MODEL` | |
190
190
  | haiku → 模型 | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | |
191
191
  | effort 思考档 | `CLAUDE_CODE_EFFORT_LEVEL` | `low` ~ `max`;`auto`=模型默认;留空=不设。第三方不一定生效 |
192
+ | 禁用非核心流量 | `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | `1`=禁用 Claude Code 非核心流量;留空=不设。GLM 预置为 `1` |
193
+ | 上下文窗口大小 | `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | 按 Claude Code 支持的窗口值填写;留空=不设 |
192
194
 
193
195
  > CC-X **刻意不设** `ANTHROPIC_MODEL`。在会话里用 `/model opus|sonnet|haiku` 选档,映射表负责翻译成对应供应商的模型名。
194
196
 
@@ -201,12 +203,12 @@ Claude Code 已经有自己的配置系统、MCP 生态和会话状态。CC-X
201
203
 
202
204
  ### 预置配置
203
205
 
204
- | 配置 | BASE_URL | OPUS / SONNET | HAIKU(含后台任务) | effort |
205
- |---|---|---|---|---|
206
- | 官方 | 留空=登录态 | — | — | — |
207
- | DeepSeek | `https://api.deepseek.com/anthropic` | `deepseek-v4-pro` | `deepseek-v4-flash` | `max`(官方推荐) |
208
- | 智谱GLM | `https://open.bigmodel.cn/api/anthropic` | `GLM-4.7` | `glm-4.5-air` | — |
209
- | 小米MiMo | `https://api.xiaomimimo.com/anthropic` | `mimo-v2.5-pro` | `mimo-v2.5-pro` | — |
206
+ | 配置 | BASE_URL | OPUS / SONNET | HAIKU(含后台任务) | effort | 额外 env |
207
+ |---|---|---|---|---|---|
208
+ | 官方 | 留空=登录态 | — | — | — | — |
209
+ | DeepSeek | `https://api.deepseek.com/anthropic` | `deepseek-v4-pro` | `deepseek-v4-flash` | `max`(官方推荐) | — |
210
+ | 智谱GLM | `https://open.bigmodel.cn/api/anthropic` | `GLM-4.7` | `glm-4.5-air` | — | `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` |
211
+ | 小米MiMo | `https://api.xiaomimimo.com/anthropic` | `mimo-v2.5-pro` | `mimo-v2.5-pro` | — | — |
210
212
 
211
213
  > 模型名随各家更新而变,以供应商官方接入文档为准。小米有按量付费和 TokenPlan 两个地址,选供应商时会让你挑。
212
214
 
@@ -214,7 +216,7 @@ Claude Code 已经有自己的配置系统、MCP 生态和会话状态。CC-X
214
216
 
215
217
  - **多账号**:同一家建多份配置,名称自动追加「 2」「 3」…用**备注**区分,列表显示为「供应商 — 备注」。
216
218
  - **自定义供应商**:`presets.json` 是供应商目录,加一个 JSON 条目就多一个供应商,无需改代码。可在 `~/.cc-mini/presets.json` 放自定义版覆盖随工具发布的版本。
217
- - **第三方首次弹登录**:在 `~/.claude.json` 最外层加 `"hasCompletedOnboarding": true`(**只加这个键**,别覆盖整个文件——里面还有你的 MCP 配置)。
219
+ - **第三方首次弹登录**:CC-X 启动第三方前会只读检测 `~/.claude.json` `hasCompletedOnboarding`,未完成时只打印提示,不阻断、不写文件;若 Claude Code 仍显示引导,按提示跳过或关闭即可。
218
220
  - **更新检查**:主菜单可切「提醒」模式,新版本出现时菜单顶部黄字提示升级命令。每天最多查一次,不自动升级。
219
221
 
220
222
  ---
@@ -227,10 +229,10 @@ Claude Code 已经有自己的配置系统、MCP 生态和会话状态。CC-X
227
229
  - Windows → 注册表 `HKCU\Environment` + 广播一次变更
228
230
  - Unix → shell 启动文件 `# >>> xx >>>` … `# <<< xx <<<` 标记块(幂等重写,按 `$SHELL` 选文件)
229
231
  - 语义一致:**只影响新终端**;切到「官方」会清除全部受管变量
230
- - **不修改任何 Claude Code 配置文件。**
232
+ - **不修改任何 Claude Code 配置文件。** 启动第三方前只读探测一次 `~/.claude.json` 的 onboarding 字段,用于提示。
231
233
 
232
- CC-X 只动这 7 个「受管」环境变量,切换时清掉目标不用的:
233
- `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`。
234
+ CC-X 只动这 9 个「受管」环境变量,切换时清掉目标不用的:
235
+ `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`、`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`、`CLAUDE_CODE_AUTO_COMPACT_WINDOW`。
234
236
 
235
237
  > 💡 需要改 `settings.json`?直接用 Claude Code 的 `/update-config` 说需求(如"允许 npm 命令"),比让外部工具改可靠。
236
238
 
package/dist/actions.js CHANGED
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * 共享动作:本次启用(CLI 路径与菜单都用,避免 index ↔ menus 循环依赖)。
3
3
  */
4
- import { getProviderState } from './config/store.js';
4
+ import { hasCompletedOnboarding } from './claudecfg.js';
5
+ import { isOfficial, getProviderState } from './config/store.js';
5
6
  import { sessionLaunch } from './env/session.js';
6
7
  import { providerDisplayName, T } from './i18n/index.js';
7
8
  /** 非官方且未填密钥时给黄字提示(对齐现版)。 */
@@ -13,6 +14,9 @@ export function warnIfNoKey(p) {
13
14
  /** 本次启用:缺密钥提示 + banner + 套环境启动 claude,阻塞至其退出。 */
14
15
  export function launchSession(p) {
15
16
  warnIfNoKey(p);
17
+ if (!isOfficial(p) && !hasCompletedOnboarding()) {
18
+ console.log(` ${T('session.onboardingHint')}`);
19
+ }
16
20
  console.log('');
17
21
  console.log(` ${T('session.launch', providerDisplayName(p))}`);
18
22
  console.log(` ${T('session.starting')}`);
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 对 ~/.claude.json 的只读访问。
3
+ * 铁律:只读不写,任何写操作都在 ccx 范围之外。
4
+ */
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { join } from 'node:path';
8
+ /**
9
+ * 只读检测 ~/.claude.json 的 hasCompletedOnboarding 字段。
10
+ * 文件不存在、解析失败或字段缺失,均返回 false(视为未完成)。
11
+ */
12
+ export function hasCompletedOnboarding() {
13
+ const path = join(homedir(), '.claude.json');
14
+ if (!existsSync(path))
15
+ return false;
16
+ try {
17
+ const data = JSON.parse(readFileSync(path, 'utf-8'));
18
+ return data.hasCompletedOnboarding === true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
@@ -26,6 +26,9 @@ export const BUILTIN_PRESETS = [
26
26
  auth: 'AUTH_TOKEN',
27
27
  urls: [{ label: 'Anthropic 兼容', url: 'https://open.bigmodel.cn/api/anthropic' }],
28
28
  models: { opus: 'GLM-4.7', sonnet: 'GLM-4.7', haiku: 'glm-4.5-air' },
29
+ env: {
30
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
31
+ },
29
32
  },
30
33
  {
31
34
  name: '小米MiMo',
@@ -59,6 +62,16 @@ function normalizeModels(raw) {
59
62
  models.haiku = m.haiku;
60
63
  return models;
61
64
  }
65
+ const PRESET_ENV_KEYS = ['CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC'];
66
+ function normalizeEnv(raw) {
67
+ const m = (raw && typeof raw === 'object' ? raw : {});
68
+ const env = {};
69
+ for (const key of PRESET_ENV_KEYS) {
70
+ if (typeof m[key] === 'string')
71
+ env[key] = m[key];
72
+ }
73
+ return Object.keys(env).length > 0 ? env : undefined;
74
+ }
62
75
  function normalizePreset(raw) {
63
76
  const p = (raw && typeof raw === 'object' ? raw : {});
64
77
  const name = asString(p.name).trim();
@@ -69,6 +82,9 @@ function normalizePreset(raw) {
69
82
  const preset = { name, auth, urls, models: normalizeModels(p.models) };
70
83
  if (typeof p.effort === 'string' && p.effort.trim())
71
84
  preset.effort = p.effort.trim();
85
+ const env = normalizeEnv(p.env);
86
+ if (env)
87
+ preset.env = env;
72
88
  return preset;
73
89
  }
74
90
  /** 把任意解析结果规整为 Preset[];非数组或全空则返回 undefined(让调用方跌落兜底)。 */
@@ -44,6 +44,7 @@ export function defaultStore() {
44
44
  ANTHROPIC_DEFAULT_OPUS_MODEL: 'GLM-4.7',
45
45
  ANTHROPIC_DEFAULT_SONNET_MODEL: 'GLM-4.7',
46
46
  ANTHROPIC_DEFAULT_HAIKU_MODEL: 'glm-4.5-air',
47
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
47
48
  },
48
49
  },
49
50
  {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 数据格式必须与现版 PowerShell 完全兼容(老用户的 ~/.cc-mini/providers.json 能直接读)。
5
5
  */
6
- /** 受管的 7 个环境变量(工具只动这些,其它一律不碰)。详见 plan §2。 */
6
+ /** 受管的 8 个环境变量(工具只动这些,其它一律不碰)。详见 plan §2。 */
7
7
  export const KNOWN_KEYS = [
8
8
  'ANTHROPIC_BASE_URL',
9
9
  'ANTHROPIC_AUTH_TOKEN',
@@ -12,4 +12,5 @@ export const KNOWN_KEYS = [
12
12
  'ANTHROPIC_DEFAULT_SONNET_MODEL',
13
13
  'ANTHROPIC_DEFAULT_HAIKU_MODEL',
14
14
  'CLAUDE_CODE_EFFORT_LEVEL',
15
+ 'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC',
15
16
  ];
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 设为默认(Set-Default)—— 持久化用户环境变量,仅影响新开终端、不动运行中会话。
3
3
  *
4
- * 对 7 个受管键:目标配置有值的写值,没值的清除(vals 里记 null)。然后 store.current=name 并存盘。
4
+ * 对 9 个受管键:目标配置有值的写值,没值的清除(vals 里记 null)。然后 store.current=name 并存盘。
5
5
  * 平台分叉是唯一有平台差异的地方:Windows 走注册表+广播,Unix 走 rc 文件 marker 块。
6
6
  * `--default-scope process` = 不落盘 dry-run(评审⑥):照常算 vals、更新 store,但跳过系统持久化。
7
7
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 评审③:钉 `powershell.exe`(5.1,Windows 必然存在),不用 `pwsh`(7+,可能没装)。
5
5
  * 逻辑搬自现版 Set-UserEnv-Fast + Invoke-EnvBroadcast:注册表瞬时写入、最后只广播一次(100ms 短超时、
6
- * SMTO_ABORTIFHUNG 跳过挂死窗口),避免「逐个 setx 广播 7 次、每窗口等 1s」的拖慢。
6
+ * SMTO_ABORTIFHUNG 跳过挂死窗口),避免「逐个 setx 广播 9 次、每窗口等 1s」的拖慢。
7
7
  *
8
8
  * 键值通过环境变量传 JSON 给子进程、用 ConvertFrom-Json 解析 —— 彻底避开命令行注入/引号转义。
9
9
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 本次启用(Session-Launch)—— 进程级、阅后即焚。
3
3
  *
4
- * 1) 对 7 个受管键:有值 set,没值 delete(只动这 7 个)。
4
+ * 1) 对 9 个受管键:有值 set,没值 delete(只动这 9 个)。
5
5
  * 2) 找到 claude(which;Windows 上是 claude.cmd,评审②)。
6
6
  * 3) spawn 且 stdio:inherit —— 子进程继承真实控制台句柄,天然没有现版 PowerShell 的
7
7
  * 「stdin 被包成管道 → claude 误判非交互」问题。
@@ -10,7 +10,7 @@
10
10
  import { spawnSync } from 'node:child_process';
11
11
  import which from 'which';
12
12
  import { KNOWN_KEYS, getProviderEnvMap } from '../config/store.js';
13
- /** 把目标配置的受管环境变量套到当前进程(有值 set、没值 delete,只动这 7 个)。 */
13
+ /** 把目标配置的受管环境变量套到当前进程(有值 set、没值 delete,只动这 9 个)。 */
14
14
  export function applyManagedEnv(p) {
15
15
  const map = getProviderEnvMap(p);
16
16
  for (const key of KNOWN_KEYS) {
@@ -90,6 +90,7 @@ export const messages = {
90
90
  'edit.field.sonnet': { zh: 'sonnet→ 模型 ', en: 'sonnet→ model ' },
91
91
  'edit.field.haiku': { zh: 'haiku → 模型 ', en: 'haiku → model ' },
92
92
  'edit.field.effort': { zh: 'effort 思考档 ', en: 'effort level ' },
93
+ 'edit.field.disableTraffic': { zh: '禁用非核心流量 ', en: 'Disable traffic ' },
93
94
  'edit.toggleSecretShow': { zh: '显示密钥明文(当前隐藏)', en: 'Show key in plaintext (now hidden)' },
94
95
  'edit.toggleSecretHide': { zh: '隐藏密钥(当前明文)', en: 'Hide key (now shown)' },
95
96
  'edit.save': { zh: '保存并返回', en: 'Save & back' },
@@ -114,6 +115,9 @@ export const messages = {
114
115
  'pick.effort.title': { zh: 'effort 思考档(当前:{0})', en: 'effort level (current: {0})' },
115
116
  'pick.effort.empty': { zh: '留空(不设)', en: 'Leave empty' },
116
117
  'pick.effort.hint': { zh: '越往后越深入;auto=模型默认 · q 不改', en: 'deeper to the right; auto=model default · q keep' },
118
+ 'pick.disableTraffic.title': { zh: '禁用非核心流量(当前:{0})', en: 'Disable nonessential traffic (current: {0})' },
119
+ 'pick.disableTraffic.yes': { zh: '是(值=1,GLM 等要求禁用)', en: 'Yes (value=1, required by GLM etc.)' },
120
+ 'pick.disableTraffic.no': { zh: '否(留空,不设置)', en: 'No (leave empty)' },
117
121
  // —— 错误 ——
118
122
  'error.notFound': { zh: '找不到配置:{0}', en: 'Profile not found: {0}' },
119
123
  'error.existing': { zh: '现有:{0}', en: 'Existing: {0}' },
@@ -139,6 +143,10 @@ export const messages = {
139
143
  },
140
144
  'session.noClaude': { zh: '未找到 claude 命令,请确认它在 PATH 中。', en: 'claude not found on PATH.' },
141
145
  'session.noClaudeHint': { zh: '下一步:安装 Claude Code 后新开终端;npm 用户可运行 `npm install -g @anthropic-ai/claude-code`。', en: 'Next: install Claude Code and open a new terminal; npm users can run `npm install -g @anthropic-ai/claude-code`.' },
146
+ 'session.onboardingHint': {
147
+ zh: '提示:若 Claude Code 首次启动出现登录引导,选择跳过或关闭引导后第三方 API 会自动生效。',
148
+ en: 'Tip: if Claude Code shows a login prompt on first launch, dismiss or skip it — the third-party API will take effect regardless.',
149
+ },
142
150
  // —— 配置自检(只读网络探测)——
143
151
  'check.noUrl': { zh: '官方登录态 / 未设置 API 地址,无需自检。', en: 'Official login / no API URL set; nothing to probe.' },
144
152
  'check.noKey': { zh: '还没填密钥,无法自检。', en: 'No key set; cannot probe.' },
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * 入口:解析 CLI 参数 → 分派到 CLI 路径(--list / xx <name> / -s)或交互菜单(TUI)。
6
6
  *
7
- * 铁律:绝不写 Claude Code 配置文件;API 切换只动 7 个受管环境变量。详见 CLAUDE.md / plan §2。
7
+ * 铁律:绝不写 Claude Code 配置文件;API 切换只动 9 个受管环境变量。详见 CLAUDE.md / plan §2。
8
8
  */
9
9
  import { createRequire } from 'node:module';
10
10
  import { Command, Option } from 'commander';
package/dist/ui/edit.js CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { buildProviderEnv, getProviderEnvMap, reconcileBuiltin, resolveUniqueName, } from '../config/store.js';
8
8
  import { T } from '../i18n/index.js';
9
- import { pickAuth, pickBaseUrl, pickEffort, pickProvider, pickProviderUrl } from './pickers.js';
9
+ import { pickAuth, pickBaseUrl, pickDisableTraffic, pickEffort, pickProvider, pickProviderUrl } from './pickers.js';
10
10
  import { selectMenu } from './select.js';
11
11
  import { readText, readValue } from './text.js';
12
12
  function fromProvider(p) {
@@ -22,6 +22,7 @@ function fromProvider(p) {
22
22
  sonnet: m.ANTHROPIC_DEFAULT_SONNET_MODEL ?? '',
23
23
  haiku: m.ANTHROPIC_DEFAULT_HAIKU_MODEL ?? '',
24
24
  effort: m.CLAUDE_CODE_EFFORT_LEVEL ?? '',
25
+ disableTraffic: m.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC ?? '',
25
26
  };
26
27
  }
27
28
  /**
@@ -46,6 +47,7 @@ export async function editForm(prov, store, catalog, focusKey = false) {
46
47
  { action: 'sonnet', label: `${T('edit.field.sonnet')}: ${v(W.sonnet)}` },
47
48
  { action: 'haiku', label: `${T('edit.field.haiku')}: ${v(W.haiku)}` },
48
49
  { action: 'effort', label: `${T('edit.field.effort')}: ${v(W.effort)}` },
50
+ { action: 'disableTraffic', label: `${T('edit.field.disableTraffic')}: ${v(W.disableTraffic)}` },
49
51
  { action: 'sep', label: '' },
50
52
  { action: 'toggle', label: showSecret ? T('edit.toggleSecretHide') : T('edit.toggleSecretShow') },
51
53
  { action: 'sep', label: '' },
@@ -76,6 +78,9 @@ export async function editForm(prov, store, catalog, focusKey = false) {
76
78
  W.haiku = pp.models.haiku;
77
79
  if (pp.effort)
78
80
  W.effort = pp.effort;
81
+ if (pp.env && Object.prototype.hasOwnProperty.call(pp.env, 'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC')) {
82
+ W.disableTraffic = pp.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC ?? '';
83
+ }
79
84
  }
80
85
  break;
81
86
  }
@@ -120,6 +125,9 @@ export async function editForm(prov, store, catalog, focusKey = false) {
120
125
  case 'effort':
121
126
  W.effort = await pickEffort(W.effort);
122
127
  break;
128
+ case 'disableTraffic':
129
+ W.disableTraffic = await pickDisableTraffic(W.disableTraffic);
130
+ break;
123
131
  case 'toggle':
124
132
  showSecret = !showSecret; // 仅切换显示,不改数据、不持久化
125
133
  break;
@@ -134,6 +142,7 @@ export async function editForm(prov, store, catalog, focusKey = false) {
134
142
  ANTHROPIC_DEFAULT_SONNET_MODEL: W.sonnet,
135
143
  ANTHROPIC_DEFAULT_HAIKU_MODEL: W.haiku,
136
144
  CLAUDE_CODE_EFFORT_LEVEL: W.effort,
145
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: W.disableTraffic,
137
146
  };
138
147
  if (W.auth === 'API_KEY')
139
148
  fields.ANTHROPIC_API_KEY = W.token;
@@ -78,6 +78,19 @@ export async function pickAuth(current) {
78
78
  return current;
79
79
  }
80
80
  const EFFORT_OPTS = ['low', 'medium', 'high', 'xhigh', 'max', 'auto'];
81
+ /** 选是否禁用非核心流量:是("1")/ 否("")/ 不改。 */
82
+ export async function pickDisableTraffic(current) {
83
+ const items = [T('pick.disableTraffic.yes'), T('pick.disableTraffic.no'), T('pick.noChange')];
84
+ const sel = await selectMenu({
85
+ title: T('pick.disableTraffic.title', current || T('empty.paren')),
86
+ items,
87
+ hint: T('pick.hint'),
88
+ noNumber: true,
89
+ });
90
+ if (sel < 0 || sel === 2)
91
+ return current;
92
+ return sel === 0 ? '1' : '';
93
+ }
81
94
  /** 选 effort 思考档:low…auto / 留空 / 不改。 */
82
95
  export async function pickEffort(current) {
83
96
  const items = [...EFFORT_OPTS, T('pick.effort.empty'), T('pick.noChange')];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cc-x/cc-x",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Claude Code API 切换器(命令 xx):在官方账号与第三方 Anthropic 兼容 API 间切换,纯环境变量、不碰 Claude Code 配置文件。",
5
5
  "keywords": [
6
6
  "claude",
package/presets.json CHANGED
@@ -14,7 +14,10 @@
14
14
  "urls": [
15
15
  { "label": "Anthropic 兼容", "url": "https://open.bigmodel.cn/api/anthropic" }
16
16
  ],
17
- "models": { "opus": "GLM-4.7", "sonnet": "GLM-4.7", "haiku": "glm-4.5-air" }
17
+ "models": { "opus": "GLM-4.7", "sonnet": "GLM-4.7", "haiku": "glm-4.5-air" },
18
+ "env": {
19
+ "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
20
+ }
18
21
  },
19
22
  {
20
23
  "name": "小米MiMo",