cc-cast 1.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daylen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ <div align="center">
2
+
3
+ # cc-cast
4
+
5
+ **Claude Code Model Switcher**
6
+
7
+ Switch Claude Code custom model configurations from the terminal in seconds.
8
+
9
+ [![npm version](https://img.shields.io/npm/v/@daylenjeez/cc-cast.svg?style=flat-square)](https://www.npmjs.com/package/@daylenjeez/cc-cast)
10
+ [![license](https://img.shields.io/github/license/daylenjeez/cc-cast?style=flat-square)](https://github.com/daylenjeez/cc-cast/blob/main/LICENSE)
11
+ [![node](https://img.shields.io/badge/node-%3E%3D18-brightgreen?style=flat-square)](https://nodejs.org)
12
+
13
+ [中文文档](https://github.com/daylenjeez/cc-cast/blob/main/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** — `cc-cast add` guides you step by step, type `<` to go back
25
+ - ⚡ **One-command Switch** — `cc-cast use OpenRouter` or `cc-cast ls` with arrow keys
26
+ - 🛡️ **Safe Switching** — Preserves `language`, `permissions` and other personal settings
27
+ - 🪶 **Lightweight** — No extra features, just model switching. Tiny footprint, fast startup, no background processes
28
+ - 🚀 **Zero Config** — Just `cc-cast init` and follow the prompts, no docs needed
29
+ - 🌍 **i18n** — English / 中文 (`cc-cast locale set en/zh`)
30
+
31
+ ## 📦 Install
32
+
33
+ ```bash
34
+ npm install -g @daylenjeez/cc-cast
35
+ ```
36
+
37
+ ## 🚀 Quick Start
38
+
39
+ ```bash
40
+ cc-cast init # Auto-detects cc-switch or initializes standalone mode
41
+ cc-cast add # Interactive wizard to add a provider
42
+ ```
43
+
44
+ ## 🔌 cc-switch Integration
45
+
46
+ Already using [cc-switch](https://github.com/farion1231/cc-switch)? When the cc-switch database is detected, cc-cast works directly with it instead of using standalone storage:
47
+
48
+ ```bash
49
+ $ cc-cast init
50
+ ✓ Initialized
51
+ ✓ cc-switch detected — cc-cast will use cc-switch's configuration store directly
52
+ ```
53
+
54
+ You can also run `cc-cast sync` at any time to pull the latest cc-switch configurations into standalone mode.
55
+
56
+ ## ➕ Adding Configurations
57
+
58
+ ### Interactive wizard (recommended)
59
+
60
+ ```bash
61
+ $ cc-cast add
62
+ Provider name (e.g. OpenRouter): OpenRouter
63
+
64
+ Choose how to add:
65
+ 1) Step by step # guided prompts, type < to go back
66
+ 2) Write JSON # opens $EDITOR
67
+
68
+ ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
69
+ ANTHROPIC_AUTH_TOKEN: sk-or-xxx
70
+ ANTHROPIC_MODEL: anthropic/claude-opus-4.6
71
+ ANTHROPIC_DEFAULT_OPUS_MODEL (optional):
72
+ ANTHROPIC_DEFAULT_SONNET_MODEL (optional):
73
+ ANTHROPIC_DEFAULT_HAIKU_MODEL (optional):
74
+
75
+ ✓ Saved configuration "OpenRouter"
76
+ Switch to this configuration now? (Y/n)
77
+ ```
78
+
79
+ ### Edit JSON directly
80
+
81
+ <details>
82
+ <summary>Standalone mode: <code>~/.cc-cast/config.json</code></summary>
83
+
84
+ ```json
85
+ {
86
+ "profiles": {
87
+ "OpenRouter": {
88
+ "env": {
89
+ "ANTHROPIC_BASE_URL": "https://openrouter.ai/api/v1",
90
+ "ANTHROPIC_AUTH_TOKEN": "sk-or-...",
91
+ "ANTHROPIC_MODEL": "anthropic/claude-opus-4.6"
92
+ }
93
+ }
94
+ }
95
+ }
96
+ ```
97
+ </details>
98
+
99
+ Aliases are stored in `~/.cc-cast/rc.json`:
100
+
101
+ ```json
102
+ {
103
+ "aliases": {
104
+ "or": "OpenRouter"
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## 📖 Commands
110
+
111
+ ### Core
112
+
113
+ | Command | Alias | Description |
114
+ |---|---|---|
115
+ | `cc-cast init` | | Initialize, auto-detect cc-switch |
116
+ | `cc-cast list` | `ls` | Interactive list & switch |
117
+ | `cc-cast use <name>` | | Switch by name |
118
+ | `cc-cast add` | `new` | Interactive add wizard |
119
+ | `cc-cast save <name>` | | Save current settings as profile |
120
+ | `cc-cast show [name]` | | View config details (all configs in JSON if no name) |
121
+ | `cc-cast modify [name]` | `edit` | Edit existing configuration |
122
+ | `cc-cast remove [name]` | `rm` | Interactive or named delete |
123
+ | `cc-cast current` | | Show active configuration |
124
+ | `cc-cast sync` | | Sync cc-switch configs into standalone |
125
+ | `cc-cast import [file]` | | Import configs from JSON (stdin if no file) |
126
+ | `cc-cast clear` | | Clean up data files |
127
+
128
+ ### Aliases
129
+
130
+ | Command | Description |
131
+ |---|---|
132
+ | `cc-cast alias set <short> <name>` | Create alias, e.g. `cc-cast alias set or OpenRouter` |
133
+ | `cc-cast alias rm <short>` | Remove alias |
134
+ | `cc-cast alias list` / `ls` | List all aliases |
135
+
136
+ ```bash
137
+ cc-cast alias set or OpenRouter
138
+ cc-cast use or # same as: cc-cast use OpenRouter
139
+ ```
140
+
141
+ ### Locale
142
+
143
+ | Command | Description |
144
+ |---|---|
145
+ | `cc-cast locale` / `ls` | List & switch language |
146
+ | `cc-cast locale set <lang>` | Set language (`zh` / `en`) |
147
+
148
+ ### Examples
149
+
150
+ ```bash
151
+ # Switch provider
152
+ $ cc-cast use OpenRouter
153
+ ✓ Switched to OpenRouter
154
+ Model: anthropic/claude-opus-4.6
155
+ Restart Claude Code to apply
156
+
157
+ # View current config
158
+ $ cc-cast current
159
+ Current configuration: OpenRouter
160
+ ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
161
+ ANTHROPIC_MODEL: anthropic/claude-opus-4.6
162
+ ANTHROPIC_AUTH_TOKEN: sk-or-v1...a3f2
163
+
164
+ # Save current settings.json as a new profile
165
+ $ cc-cast save my-backup
166
+ ✓ Saved current configuration as "my-backup"
167
+ ```
168
+
169
+ ## ⚙️ How It Works
170
+
171
+ Claude Code reads `~/.claude/settings.json` on startup. The `env` field controls the API provider and model:
172
+
173
+ | Variable | Description |
174
+ |---|---|
175
+ | `ANTHROPIC_BASE_URL` | API endpoint URL |
176
+ | `ANTHROPIC_AUTH_TOKEN` | Authentication token |
177
+ | `ANTHROPIC_MODEL` | Default model (optional) |
178
+ | `ANTHROPIC_DEFAULT_OPUS_MODEL` | Model used when selecting Opus via `/model` |
179
+ | `ANTHROPIC_DEFAULT_SONNET_MODEL` | Model used when selecting Sonnet via `/model` |
180
+ | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | Model used when selecting Haiku via `/model` |
181
+
182
+ `cc-cast use` writes the selected profile into `settings.json` while preserving personal settings (`language`, `permissions`, etc.). Restart Claude Code to apply.
183
+
184
+ ## 🗑️ Uninstall
185
+
186
+ Removing `cc-cast` only removes the CLI itself. Your data files are left behind.
187
+
188
+ Use `cc-cast clear` to delete them automatically, or clean them up manually:
189
+
190
+ - `~/.cc-cast/rc.json` — aliases and locale
191
+ - `~/.cc-cast/config.json` — profiles
192
+ - `~/.claude/settings.json` — may still contain an active `env` profile written by cc-cast
193
+
194
+ Then remove the CLI:
195
+
196
+ ```bash
197
+ npm uninstall -g @daylenjeez/cc-cast
198
+ ```
199
+
200
+ ## 📄 License
201
+
202
+ [MIT](./LICENSE)
@@ -0,0 +1,202 @@
1
+ <div align="center">
2
+
3
+ # cc-cast
4
+
5
+ **Claude Code Model Switcher**
6
+
7
+ 在终端几秒内完成 Claude Code 自定义模型配置的管理和切换。
8
+
9
+ [![npm version](https://img.shields.io/npm/v/@daylenjeez/cc-cast.svg?style=flat-square)](https://www.npmjs.com/package/@daylenjeez/cc-cast)
10
+ [![license](https://img.shields.io/github/license/daylenjeez/cc-cast?style=flat-square)](https://github.com/daylenjeez/cc-cast/blob/main/LICENSE)
11
+ [![node](https://img.shields.io/badge/node-%3E%3D18-brightgreen?style=flat-square)](https://nodejs.org)
12
+
13
+ [English](https://github.com/daylenjeez/cc-cast/blob/main/README.md) | 中文文档
14
+
15
+ [安装](#-安装) · [快速开始](#-快速开始) · [命令一览](#-命令一览) · [工作原理](#%EF%B8%8F-工作原理)
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ ## ✨ 亮点
22
+
23
+ - 🔌 **cc-switch Integration** — 直接读取 `cc-switch` 数据库,无需迁移
24
+ - 🧙 **Interactive Wizard** — `cc-cast add` 逐步引导,输入 `<` 可返回上一步
25
+ - ⚡ **One-command Switch** — `cc-cast use OpenRouter` 或 `cc-cast ls` 方向键选择
26
+ - 🛡️ **Safe Switching** — 自动保留 `language`、`permissions` 等个人设置
27
+ - 🪶 **轻量** — 没有多余功能,只做模型切换。体积小巧,启动迅速,无后台进程
28
+ - 🚀 **Zero Config** — 直接 `cc-cast init`,跟着提示走,无需阅读文档
29
+ - 🌍 **i18n** — `cc-cast locale set zh/en` 切换界面语言
30
+
31
+ ## 📦 安装
32
+
33
+ ```bash
34
+ npm install -g @daylenjeez/cc-cast
35
+ ```
36
+
37
+ ## 🚀 快速开始
38
+
39
+ ```bash
40
+ cc-cast init # 自动检测 cc-switch 或初始化独立模式
41
+ cc-cast add # 交互式向导添加供应商
42
+ ```
43
+
44
+ ## 🔌 cc-switch 集成
45
+
46
+ 已经在用 [cc-switch](https://github.com/farion1231/cc-switch)?检测到 cc-switch 数据库时,cc-cast 会直接使用它的配置库,无需迁移:
47
+
48
+ ```bash
49
+ $ cc-cast init
50
+ ✓ 初始化完成
51
+ ✓ 检测到 cc-switch,cc-cast 将直接使用 cc-switch 配置库
52
+ ```
53
+
54
+ 你也可以随时运行 `cc-cast sync` 将最新的 cc-switch 配置同步到独立模式。
55
+
56
+ ## ➕ 添加配置
57
+
58
+ ### 交互式向导(推荐)
59
+
60
+ ```bash
61
+ $ cc-cast add
62
+ 供应商名称 (如 OpenRouter): OpenRouter
63
+
64
+ 选择添加方式:
65
+ 1) 逐步填写 # 按步骤输入,输入 < 返回上一步
66
+ 2) 直接编写 JSON # 打开 $EDITOR 编辑
67
+
68
+ ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
69
+ ANTHROPIC_AUTH_TOKEN: sk-or-xxx
70
+ ANTHROPIC_MODEL: anthropic/claude-opus-4.6
71
+ ANTHROPIC_DEFAULT_OPUS_MODEL (可选):
72
+ ANTHROPIC_DEFAULT_SONNET_MODEL (可选):
73
+ ANTHROPIC_DEFAULT_HAIKU_MODEL (可选):
74
+
75
+ ✓ 已保存配置 "OpenRouter"
76
+ 是否立即切换到此配置?(Y/n)
77
+ ```
78
+
79
+ ### 直接编辑 JSON
80
+
81
+ <details>
82
+ <summary>独立模式:<code>~/.cc-cast/config.json</code></summary>
83
+
84
+ ```json
85
+ {
86
+ "profiles": {
87
+ "OpenRouter": {
88
+ "env": {
89
+ "ANTHROPIC_BASE_URL": "https://openrouter.ai/api/v1",
90
+ "ANTHROPIC_AUTH_TOKEN": "sk-or-...",
91
+ "ANTHROPIC_MODEL": "anthropic/claude-opus-4.6"
92
+ }
93
+ }
94
+ }
95
+ }
96
+ ```
97
+ </details>
98
+
99
+ 别名存储在 `~/.cc-cast/rc.json` 中:
100
+
101
+ ```json
102
+ {
103
+ "aliases": {
104
+ "or": "OpenRouter"
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## 📖 命令一览
110
+
111
+ ### 核心命令
112
+
113
+ | 命令 | 缩写 | 说明 |
114
+ |---|---|---|
115
+ | `cc-cast init` | | 初始化,自动检测 cc-switch |
116
+ | `cc-cast list` | `ls` | 交互式列表 & 切换 |
117
+ | `cc-cast use <name>` | | 按名称切换 |
118
+ | `cc-cast add` | `new` | 交互式添加向导 |
119
+ | `cc-cast save <name>` | | 将当前设置保存为方案 |
120
+ | `cc-cast show [name]` | | 查看配置详情(无名称时输出全部 JSON) |
121
+ | `cc-cast modify [name]` | `edit` | 修改已有配置 |
122
+ | `cc-cast remove [name]` | `rm` | 交互式或指定名称删除 |
123
+ | `cc-cast current` | | 显示当前激活配置 |
124
+ | `cc-cast sync` | | 从 cc-switch 同步配置到本地 |
125
+ | `cc-cast import [file]` | | 从 JSON 导入配置(无文件时从 stdin 读取) |
126
+ | `cc-cast clear` | | 清理数据文件 |
127
+
128
+ ### 别名管理
129
+
130
+ | 命令 | 说明 |
131
+ |---|---|
132
+ | `cc-cast alias set <short> <name>` | 创建别名,如 `cc-cast alias set or OpenRouter` |
133
+ | `cc-cast alias rm <short>` | 删除别名 |
134
+ | `cc-cast alias list` / `ls` | 列出所有别名 |
135
+
136
+ ```bash
137
+ cc-cast alias set or OpenRouter
138
+ cc-cast use or # 等同于: cc-cast use OpenRouter
139
+ ```
140
+
141
+ ### 语言设置
142
+
143
+ | 命令 | 说明 |
144
+ |---|---|
145
+ | `cc-cast locale` / `ls` | 列出并切换语言 |
146
+ | `cc-cast locale set <lang>` | 设置语言(`zh` / `en`) |
147
+
148
+ ### 使用示例
149
+
150
+ ```bash
151
+ # 切换供应商
152
+ $ cc-cast use OpenRouter
153
+ ✓ 已切换到 OpenRouter
154
+ 模型: anthropic/claude-opus-4.6
155
+ 重启 Claude Code 生效
156
+
157
+ # 查看当前配置
158
+ $ cc-cast current
159
+ 当前配置: OpenRouter
160
+ ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1
161
+ ANTHROPIC_MODEL: anthropic/claude-opus-4.6
162
+ ANTHROPIC_AUTH_TOKEN: sk-or-v1...a3f2
163
+
164
+ # 将当前 settings.json 保存为新方案
165
+ $ cc-cast save my-backup
166
+ ✓ 已保存当前配置为 "my-backup"
167
+ ```
168
+
169
+ ## ⚙️ 工作原理
170
+
171
+ Claude Code 启动时读取 `~/.claude/settings.json`,`env` 字段控制 API 供应商和模型:
172
+
173
+ | 变量 | 说明 |
174
+ |---|---|
175
+ | `ANTHROPIC_BASE_URL` | API 端点地址 |
176
+ | `ANTHROPIC_AUTH_TOKEN` | 认证令牌 |
177
+ | `ANTHROPIC_MODEL` | 默认模型(可选) |
178
+ | `ANTHROPIC_DEFAULT_OPUS_MODEL` | 在 Claude Code 中通过 `/model` 选择 Opus 时使用的模型 |
179
+ | `ANTHROPIC_DEFAULT_SONNET_MODEL` | 选择 Sonnet 时使用的模型 |
180
+ | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | 选择 Haiku 时使用的模型 |
181
+
182
+ `cc-cast use` 将选中配置写入 `settings.json`,同时保留 `language`、`permissions` 等个人设置。重启 Claude Code 后生效。
183
+
184
+ ## 🗑️ 卸载
185
+
186
+ 卸载 `cc-cast` 只会删除 CLI 程序本身,相关的数据文件仍然保留。
187
+
188
+ 你可以先运行 `cc-cast clear` 自动清理数据文件,也可以手动删除:
189
+
190
+ - `~/.cc-cast/rc.json` — 别名和语言设置
191
+ - `~/.cc-cast/config.json` — 配置方案
192
+ - `~/.claude/settings.json` — 可能仍包含 cc-cast 写入的 `env` 配置
193
+
194
+ 然后移除 CLI:
195
+
196
+ ```bash
197
+ npm uninstall -g @daylenjeez/cc-cast
198
+ ```
199
+
200
+ ## 📄 License
201
+
202
+ [MIT](./LICENSE)
@@ -0,0 +1,3 @@
1
+ export declare function readClaudeSettings(): Record<string, unknown>;
2
+ export declare function applyProfile(_name: string, settingsConfig: Record<string, unknown>): void;
3
+ export declare function getSettingsPath(): string;
package/dist/claude.js ADDED
@@ -0,0 +1,27 @@
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(_name, 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
+ // Merge instead of replace: keep any top-level keys from the existing file
21
+ // that the profile does not explicitly set (e.g. common snippets from cc-switch)
22
+ const merged = { ...current, ...preserved, ...settingsConfig };
23
+ writeFileSync(SETTINGS_PATH, JSON.stringify(merged, null, 2));
24
+ }
25
+ export function getSettingsPath() {
26
+ return SETTINGS_PATH;
27
+ }
@@ -0,0 +1,3 @@
1
+ import type { TranslationKey } from "./zh.js";
2
+ declare const en: Record<TranslationKey, string>;
3
+ export default en;
@@ -0,0 +1,139 @@
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: cc-cast init",
6
+ "common.model": "Model",
7
+ "common.model_default": "default",
8
+ "common.source": "Source",
9
+ "common.cancelled": "cancelled",
10
+ // error
11
+ "error.not_found": 'Configuration "{name}" not found',
12
+ "error.alias_target_missing": 'Alias "{alias}" points to "{target}", but it does not exist',
13
+ "error.invalid_choice": "Invalid choice",
14
+ // suggest
15
+ "suggest.did_you_mean": "Did you mean: {name}?",
16
+ "suggest.did_you_mean_header": "Did you mean:",
17
+ "suggest.use_list": "Use cc-cast list to see all available configurations",
18
+ // init
19
+ "init.description": "Initialize cc-cast",
20
+ "init.cc_switch_found": "cc-switch detected. Import configurations from it? (Y/n) ",
21
+ "init.cc_switch_mode": "✓ cc-switch detected — cc-cast will use cc-switch's configuration store directly",
22
+ "init.cc_switch_migrate": "Standalone cc-cast configurations found. Migrate them to cc-switch? (Y/n) ",
23
+ "init.cc_switch_migrate_done": "✓ Migrated {count} configurations to cc-switch",
24
+ "init.done": "✓ Initialized",
25
+ // list
26
+ "list.description": "List and select configurations",
27
+ "list.empty": "No configurations yet. Use cc-cast save <name> to save current config",
28
+ "list.header": "Available configurations:",
29
+ "list.select": "Select configuration:",
30
+ "list.current_marker": "(current)",
31
+ "list.choose_number": "Enter number to switch (Enter to skip): ",
32
+ // current
33
+ "current.description": "Show the currently active configuration",
34
+ "current.none": "No active configuration",
35
+ "current.settings_header": "Current settings.json:",
36
+ "current.not_exist": 'Current configuration "{name}" no longer exists',
37
+ "current.header": "Current configuration: {name}",
38
+ // use
39
+ "use.description": "Switch to a specified configuration",
40
+ "use.done": "✓ Switched to {name}",
41
+ "use.restart": "Restart Claude Code to apply",
42
+ "use.cc_switch_running": "cc-switch GUI is running. To avoid config conflicts, only the active marker was updated. Please switch manually in cc-switch GUI, or quit GUI and try again.",
43
+ // save
44
+ "save.description": "Save current settings.json as a new configuration",
45
+ "save.overwrite": 'Configuration "{name}" already exists, will overwrite',
46
+ "save.done": '✓ Saved current configuration as "{name}"',
47
+ // show
48
+ "show.description": "View configuration details (defaults to current)",
49
+ "show.no_current": "No active configuration. Specify a name: cc-cast show <name>",
50
+ "show.all_header": "All configurations:",
51
+ // remove
52
+ "remove.description": "Delete a configuration",
53
+ "remove.select": "Select configuration to delete:",
54
+ "remove.confirm": 'Delete "{name}"? (y/N) ',
55
+ "remove.done": '✓ Deleted "{name}"',
56
+ // alias
57
+ "alias.description": "Manage aliases",
58
+ "alias.set_description": "Set alias, e.g.: cc-cast alias set or openrouter-opus4.6",
59
+ "alias.set_done": "✓ Alias set: {short} → {name}",
60
+ "alias.rm_description": "Remove an alias",
61
+ "alias.rm_not_found": 'Alias "{short}" not found',
62
+ "alias.rm_done": '✓ Removed alias "{short}"',
63
+ "alias.list_description": "List all aliases",
64
+ "alias.list_empty": "No aliases yet. Use cc-cast alias set <short> <name> to add one",
65
+ "alias.list_header": "Aliases:",
66
+ // locale
67
+ "locale.description": "Manage interface language",
68
+ "locale.current": "Current language: {locale}",
69
+ "locale.set_description": "Set language (zh/en)",
70
+ "locale.set_done": "✓ Language set to {locale}",
71
+ "locale.set_invalid": "Unsupported language: {locale}. Available: zh, en",
72
+ "locale.list_description": "List and select language",
73
+ "locale.list_header": "Supported languages:",
74
+ "locale.list_current_marker": "(current)",
75
+ "locale.select": "Select language:",
76
+ "locale.choose_number": "Enter number to switch (Enter to skip): ",
77
+ // add
78
+ "add.description": "Interactively add a new configuration",
79
+ "add.prompt_name": "Provider name (e.g. OpenRouter): ",
80
+ "add.prompt_base_url": "ANTHROPIC_BASE_URL: ",
81
+ "add.prompt_auth_token": "ANTHROPIC_AUTH_TOKEN: ",
82
+ "add.prompt_model": "ANTHROPIC_MODEL: ",
83
+ "add.prompt_default_opus": "ANTHROPIC_DEFAULT_OPUS_MODEL (press Enter to skip): ",
84
+ "add.prompt_default_sonnet": "ANTHROPIC_DEFAULT_SONNET_MODEL (press Enter to skip): ",
85
+ "add.prompt_default_haiku": "ANTHROPIC_DEFAULT_HAIKU_MODEL (press Enter to skip): ",
86
+ "add.mode_select": "Choose how to add:",
87
+ "add.mode_interactive": "Step by step",
88
+ "add.mode_json": "Write JSON directly",
89
+ "add.mode_choose": "Choose (1/2): ",
90
+ "add.json_template_hint": "Fill in the configuration in editor, save and exit",
91
+ "add.json_parse_error": "JSON parse error, please check format",
92
+ "add.back_hint": "Type < to go back",
93
+ "add.name_required": "Provider name cannot be empty",
94
+ "add.field_required": "{field} cannot be empty",
95
+ "add.already_exists": 'Configuration "{name}" already exists. Overwrite? (y/N) ',
96
+ "add.edit_confirm": "Edit configuration in editor? (y/N) ",
97
+ "add.preview_header": "Configuration preview:",
98
+ "add.done": '✓ Saved configuration "{name}"',
99
+ "add.switch_confirm": "Switch to this configuration now? (Y/n) ",
100
+ "add.cancelled": "Cancelled",
101
+ // modify
102
+ "modify.description": "Modify an existing configuration",
103
+ "modify.select": "Select configuration to modify:",
104
+ "modify.done": '✓ Updated configuration "{name}"',
105
+ "modify.no_change": "No changes made",
106
+ // alias conflict
107
+ "alias.is_alias": '"{name}" is an alias for "{target}"',
108
+ "alias.conflict": '"{name}" is both an alias (→ {target}) and a config name. Which one?',
109
+ "alias.conflict_alias": "Alias (→ {target})",
110
+ "alias.conflict_config": "Config {name}",
111
+ "alias.choose_conflict": "Choose (1/2): ",
112
+ "alias.rm_which": "Which one to delete?",
113
+ "alias.rm_alias": "Alias {name}",
114
+ "alias.rm_config": "Config {target}",
115
+ "alias.rm_choose": "Choose (1/2): ",
116
+ // sync
117
+ "sync.description": "Sync configurations from cc-switch",
118
+ "sync.no_cc_switch": "cc-switch database not detected",
119
+ "sync.empty": "No Claude configurations found in cc-switch",
120
+ "sync.done": "✓ Synced {count} configurations",
121
+ "sync.current": "Active: {name}",
122
+ "sync.no_current": "No active configuration",
123
+ // clear
124
+ "clear.description": "Clean up cc-cast data files",
125
+ "clear.confirm": "Delete all cc-cast data files? (y/N) ",
126
+ "clear.cancelled": "Cancelled",
127
+ "clear.removed": "✓ Deleted {path}",
128
+ "clear.done": "✓ Cleanup complete",
129
+ // import
130
+ "import.description": "Import configurations from JSON (file or stdin)",
131
+ "import.paste_hint": "Paste JSON and press Ctrl+D (or Ctrl+Z on Windows) to finish:",
132
+ "import.file_not_found": 'File not found: {file}',
133
+ "import.json_parse_error": "Invalid JSON format",
134
+ "import.invalid_format": "Invalid format: expected object with configuration names as keys",
135
+ "import.done": "✓ Imported {count} configurations",
136
+ // store errors
137
+ "store.db_not_found": "cc-switch database not found: {path}",
138
+ };
139
+ export default en;
@@ -0,0 +1,6 @@
1
+ import { type TranslationKey } from "./zh.js";
2
+ export type Locale = "zh" | "en";
3
+ declare function getLocale(): Locale;
4
+ export declare function setLocale(locale: Locale): void;
5
+ export declare function t(key: TranslationKey, vars?: Record<string, string>): string;
6
+ export { getLocale, type TranslationKey };
@@ -0,0 +1,36 @@
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 English
15
+ return "en";
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.en[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
+ }
36
+ export { getLocale };