@supertiny99/cc-switch 1.0.1

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) 2025 cc-switch contributors
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,340 @@
1
+ # cc-switch
2
+
3
+ > 快速切换 Claude Code API 提供商的 TUI 工具
4
+
5
+ 当 token 额度用尽时,可以快速切换到另一个提供商/token。
6
+
7
+ ## 功能特性
8
+
9
+ - 🔄 **快速切换** - 1-2 秒内完成提供商切换
10
+ - 🎨 **交互式选择** - 支持模糊搜索的友好界面
11
+ - 🔒 **自动备份** - 每次切换前自动备份配置
12
+ - 📦 **可扩展** - 预留 MCP、技能、插件切换接口
13
+ - 🌍 **多提供商** - 支持任意兼容 Anthropic API 的提供商
14
+
15
+ ## 安装
16
+
17
+ ### 全局安装
18
+
19
+ ```bash
20
+ npm install -g @supertiny99/cc-switch
21
+ ```
22
+
23
+ ### 本地开发
24
+
25
+ ```bash
26
+ git clone <repo-url>
27
+ cd cc-switch
28
+ npm install
29
+ npm link # 链接到本地环境
30
+ ```
31
+
32
+ ## 快速开始
33
+
34
+ ### 1. 查看当前配置
35
+
36
+ ```bash
37
+ cc-switch current
38
+ ```
39
+
40
+ 输出:
41
+ ```
42
+ Current Configuration:
43
+ Provider: zhipu
44
+ Base URL: https://open.bigmodel.cn/api/anthropic
45
+ Haiku Model: GLM-4.5-Air
46
+ Sonnet Model: GLM-4.7
47
+ Opus Model: GLM-4.7
48
+ ```
49
+
50
+ ### 2. 列出所有提供商
51
+
52
+ ```bash
53
+ cc-switch list
54
+ ```
55
+
56
+ ### 3. 交互式切换
57
+
58
+ ```bash
59
+ cc-switch
60
+ ```
61
+
62
+ 输入 `zh` 即可快速定位到 "Zhipu AI",按 Enter 确认。
63
+
64
+ ### 4. 直接切换
65
+
66
+ ```bash
67
+ cc-switch use anthropic
68
+ ```
69
+
70
+ ## 配置文件
71
+
72
+ 提供商配置文件位于 `~/.claude/profiles/`:
73
+
74
+ ```
75
+ ~/.claude/
76
+ ├── settings.json # Claude Code 当前配置
77
+ ├── profiles/ # 提供商配置目录
78
+ │ ├── zhipu.json # 智谱 AI (GLM)
79
+ │ ├── anthropic.json # Anthropic 官方
80
+ │ └── custom.json # 自定义提供商
81
+ └── cc-switch-backups/ # 自动备份目录
82
+ ```
83
+
84
+ ### 创建自定义提供商
85
+
86
+ 在 `~/.claude/profiles/` 创建 JSON 文件:
87
+
88
+ ```json
89
+ {
90
+ "id": "my-provider",
91
+ "name": "我的提供商",
92
+ "description": "自定义 API 提供商",
93
+ "icon": "🚀",
94
+ "config": {
95
+ "env": {
96
+ "ANTHROPIC_AUTH_TOKEN": "your_token_here",
97
+ "ANTHROPIC_BASE_URL": "https://your-api-endpoint.com",
98
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL": "model-name",
99
+ "ANTHROPIC_DEFAULT_OPUS_MODEL": "model-name",
100
+ "ANTHROPIC_DEFAULT_SONNET_MODEL": "model-name"
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ ## 命令参考
107
+
108
+ | 命令 | 说明 |
109
+ |------|------|
110
+ | `cc-switch` | 交互式选择提供商 |
111
+ | `cc-switch use <id>` | 直接切换到指定提供商 |
112
+ | `cc-switch list` | 列出所有可用提供商 |
113
+ | `cc-switch current` | 显示当前配置 |
114
+ | `cc-switch history` | 查看备份历史 |
115
+ | `cc-switch restore <file>` | 从备份恢复 |
116
+
117
+ ## 开发
118
+
119
+ ### 项目结构
120
+
121
+ ```
122
+ cc-switch/
123
+ ├── src/
124
+ │ ├── index.ts # CLI 入口
125
+ │ ├── lib/
126
+ │ │ └── config/
127
+ │ │ ├── schema.ts # 类型定义
128
+ │ │ ├── loader.ts # 配置读取
129
+ │ │ └── writer.ts # 配置写入(含备份)
130
+ │ └── ui/
131
+ │ └── quick-select.ts # 交互式选择
132
+ ├── package.json
133
+ ├── tsconfig.json
134
+ └── README.md
135
+ ```
136
+
137
+ ### 开发命令
138
+
139
+ ```bash
140
+ # 安装依赖
141
+ npm install
142
+
143
+ # 开发模式(热重载)
144
+ npm run dev list
145
+
146
+ # 构建
147
+ npm run build
148
+
149
+ # 本地测试
150
+ npm link
151
+ cc-switch list
152
+
153
+ # 运行测试
154
+ npm test
155
+ ```
156
+
157
+ ### 添加新功能
158
+
159
+ 1. **新增 CLI 命令** - 在 `src/index.ts` 添加:
160
+ ```typescript
161
+ program
162
+ .command('my-command')
163
+ .description('我的命令')
164
+ .action(async () => {
165
+ // 你的逻辑
166
+ });
167
+ ```
168
+
169
+ 2. **新增配置项** - 在 `src/lib/config/schema.ts` 扩展类型
170
+
171
+ 3. **新增 UI 组件** - 在 `src/ui/` 创建新文件
172
+
173
+ ## 测试
174
+
175
+ ### 手动测试清单
176
+
177
+ ```bash
178
+ # 1. 测试列出提供商
179
+ cc-switch list
180
+
181
+ # 2. 测试显示当前配置
182
+ cc-switch current
183
+
184
+ # 3. 测试切换提供商
185
+ cc-switch use anthropic
186
+ cc-switch current # 验证已切换
187
+
188
+ # 4. 测试备份功能
189
+ cc-switch history
190
+
191
+ # 5. 测试恢复备份
192
+ cc-switch restore settings-2025-01-29T14-30-22-123Z.json
193
+
194
+ # 6. 测试交互式选择
195
+ cc-switch # 按 Ctrl+C 取消
196
+ ```
197
+
198
+ ### 单元测试(待实现)
199
+
200
+ ```bash
201
+ npm test
202
+ ```
203
+
204
+ ## 发布到 npm
205
+
206
+ ### 1. 准备发布
207
+
208
+ ```bash
209
+ # 确保已构建
210
+ npm run build
211
+
212
+ # 检查 package.json 配置
213
+ cat package.json
214
+ ```
215
+
216
+ ### 2. npm 账号设置
217
+
218
+ ```bash
219
+ # 登录 npm(首次需要)
220
+ npm login
221
+
222
+ # 或使用 token 登录
223
+ npm token create
224
+ npm logout
225
+ npm login --registry=https://registry.npmjs.org --auth-only
226
+ ```
227
+
228
+ ### 3. 检查包名是否可用
229
+
230
+ ```bash
231
+ npm search @supertiny99/cc-switch
232
+ # 或访问 https://www.npmjs.com/package/@supertiny99/cc-switch
233
+ ```
234
+
235
+ ### 4. 发布流程
236
+
237
+ ```bash
238
+ # 1. 更新版本号
239
+ npm version patch # 1.0.0 -> 1.0.1
240
+ npm version minor # 1.0.0 -> 1.1.0
241
+ npm version major # 1.0.0 -> 2.0.0
242
+
243
+ # 2. 发布到 npm
244
+ npm publish
245
+
246
+ # 3. 验证发布
247
+ npm view @supertiny99/cc-switch
248
+ ```
249
+
250
+ ### 5. 发布选项
251
+
252
+ ```bash
253
+ # 公开发布(默认)
254
+ npm publish
255
+
256
+ # 作为一个包的发布范围(@scope/package-name)
257
+ npm publish --access public
258
+
259
+ # 干运行(不实际发布)
260
+ npm publish --dry-run
261
+
262
+ # 发布特定 tag
263
+ npm publish --tag beta
264
+ ```
265
+
266
+ ### 6. 发布后验证
267
+
268
+ ```bash
269
+ # 全局安装测试
270
+ npm install -g @supertiny99/cc-switch
271
+
272
+ # 或使用 npx 直接运行
273
+ npx @supertiny99/cc-switch list
274
+ ```
275
+
276
+ ## 发布检查清单
277
+
278
+ - [ ] 更新 package.json 版本号
279
+ - [ ] 运行 `npm run build` 确保构建成功
280
+ - [ ] 更新 README.md 文档
281
+ - [ ] 添加 LICENSE 文件
282
+ - [ ] 测试所有命令功能正常
283
+ - [ ] 确认包名未被占用
284
+ - [ ] 检查 .npmignore 排除不必要的文件
285
+
286
+ ## 故障排除
287
+
288
+ ### 命令未找到
289
+
290
+ ```bash
291
+ # 重新链接
292
+ npm link
293
+
294
+ # 或检查全局路径
295
+ which cc-switch
296
+ ```
297
+
298
+ ### 配置文件错误
299
+
300
+ ```bash
301
+ # 查看备份
302
+ cc-switch history
303
+
304
+ # 恢复备份
305
+ cc-switch restore <backup-file>
306
+ ```
307
+
308
+ ### 权限问题
309
+
310
+ ```bash
311
+ # macOS/Linux 可能需要 sudo
312
+ sudo npm link
313
+ ```
314
+
315
+ ## 兼容性
316
+
317
+ - Node.js >= 16.0.0
318
+ - macOS, Linux, Windows
319
+
320
+ ## 许可证
321
+
322
+ MIT
323
+
324
+ ## 贡献
325
+
326
+ 欢迎提交 Issue 和 Pull Request!
327
+
328
+ ## 路线图
329
+
330
+ - [ ] MCP 服务器切换
331
+ - [ ] 技能启用/禁用
332
+ - [ ] 插件管理
333
+ - [ ] 完整 TUI 界面(使用 Ink)
334
+ - [ ] 配置验证
335
+ - [ ] 单元测试
336
+
337
+ ## 相关链接
338
+
339
+ - [Claude Code](https://github.com/anthropics/claude-code)
340
+ - [Anthropic API](https://docs.anthropic.com/)
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const quick_select_1 = require("./ui/quick-select");
9
+ const loader_1 = require("./lib/config/loader");
10
+ const writer_1 = require("./lib/config/writer");
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const program = new commander_1.Command();
13
+ program
14
+ .name('cc-switch')
15
+ .description('Quick Claude Code configuration switcher')
16
+ .version('1.0.0');
17
+ program
18
+ .action(async () => {
19
+ await (0, quick_select_1.quickSelect)();
20
+ });
21
+ program
22
+ .command('use <profile-id>')
23
+ .description('Switch to a provider profile')
24
+ .action(async (profileId) => {
25
+ try {
26
+ const profile = await (0, loader_1.loadProfile)(profileId);
27
+ await (0, writer_1.applyProfile)(profile);
28
+ console.log(chalk_1.default.green(`✓ Switched to ${profile.name}`));
29
+ }
30
+ catch (err) {
31
+ console.error(chalk_1.default.red(`Error: ${err.message}`));
32
+ process.exit(1);
33
+ }
34
+ });
35
+ program
36
+ .command('list')
37
+ .description('List available profiles')
38
+ .action(async () => {
39
+ try {
40
+ const profiles = await (0, loader_1.listProfiles)();
41
+ const settings = await (0, loader_1.loadSettings)();
42
+ const current = (0, loader_1.getCurrentProvider)(settings);
43
+ if (profiles.length === 0) {
44
+ console.log(chalk_1.default.yellow('No profiles found. Create profiles in ~/.claude/profiles/'));
45
+ return;
46
+ }
47
+ console.log(chalk_1.default.bold('Available Profiles:'));
48
+ profiles.forEach(p => {
49
+ const marker = p.id === current ? chalk_1.default.green('✓') : ' ';
50
+ console.log(` ${marker} ${p.icon || '📦'} ${chalk_1.default.bold(p.name)} (${chalk_1.default.gray(p.id)})`);
51
+ if (p.description)
52
+ console.log(` ${p.description}`);
53
+ });
54
+ }
55
+ catch (err) {
56
+ console.error(chalk_1.default.red(`Error: ${err.message}`));
57
+ process.exit(1);
58
+ }
59
+ });
60
+ program
61
+ .command('current')
62
+ .description('Show current configuration')
63
+ .action(async () => {
64
+ try {
65
+ const settings = await (0, loader_1.loadSettings)();
66
+ const current = (0, loader_1.getCurrentProvider)(settings);
67
+ console.log(chalk_1.default.bold('Current Configuration:'));
68
+ console.log(` Provider: ${chalk_1.default.cyan(current || 'unknown')}`);
69
+ console.log(` Base URL: ${chalk_1.default.gray(settings.env?.ANTHROPIC_BASE_URL || 'default')}`);
70
+ console.log(` Haiku Model: ${chalk_1.default.gray(settings.env?.ANTHROPIC_DEFAULT_HAIKU_MODEL || 'default')}`);
71
+ console.log(` Sonnet Model: ${chalk_1.default.gray(settings.env?.ANTHROPIC_DEFAULT_SONNET_MODEL || 'default')}`);
72
+ console.log(` Opus Model: ${chalk_1.default.gray(settings.env?.ANTHROPIC_DEFAULT_OPUS_MODEL || 'default')}`);
73
+ }
74
+ catch (err) {
75
+ console.error(chalk_1.default.red(`Error: ${err.message}`));
76
+ process.exit(1);
77
+ }
78
+ });
79
+ program
80
+ .command('history')
81
+ .description('Show backup history')
82
+ .action(async () => {
83
+ try {
84
+ const backups = await (0, writer_1.listBackups)();
85
+ if (backups.length === 0) {
86
+ console.log(chalk_1.default.yellow('No backups found'));
87
+ return;
88
+ }
89
+ console.log(chalk_1.default.bold('Backup History:'));
90
+ backups.forEach((b, i) => console.log(` ${chalk_1.default.gray(`${i + 1}.`)} ${b}`));
91
+ }
92
+ catch (err) {
93
+ console.error(chalk_1.default.red(`Error: ${err.message}`));
94
+ process.exit(1);
95
+ }
96
+ });
97
+ program
98
+ .command('restore <backup-file>')
99
+ .description('Restore from backup')
100
+ .action(async (backupFile) => {
101
+ try {
102
+ await (0, writer_1.restoreBackup)(backupFile);
103
+ console.log(chalk_1.default.green(`✓ Restored from ${backupFile}`));
104
+ }
105
+ catch (err) {
106
+ console.error(chalk_1.default.red(`Error: ${err.message}`));
107
+ process.exit(1);
108
+ }
109
+ });
110
+ program.parse();
111
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Settings, ProviderProfile } from './schema';
2
+ export declare function loadSettings(): Promise<Settings>;
3
+ export declare function loadProfile(profileId: string): Promise<ProviderProfile>;
4
+ export declare function listProfiles(): Promise<ProviderProfile[]>;
5
+ export declare function getCurrentProvider(settings: Settings): string | null;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadSettings = loadSettings;
7
+ exports.loadProfile = loadProfile;
8
+ exports.listProfiles = listProfiles;
9
+ exports.getCurrentProvider = getCurrentProvider;
10
+ const fs_extra_1 = __importDefault(require("fs-extra"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const os_1 = __importDefault(require("os"));
13
+ const CLAUDE_DIR = path_1.default.join(os_1.default.homedir(), '.claude');
14
+ const SETTINGS_FILE = path_1.default.join(CLAUDE_DIR, 'settings.json');
15
+ const PROFILES_DIR = path_1.default.join(CLAUDE_DIR, 'profiles');
16
+ async function loadSettings() {
17
+ if (!(await fs_extra_1.default.pathExists(SETTINGS_FILE))) {
18
+ throw new Error('Claude Code settings not found');
19
+ }
20
+ return fs_extra_1.default.readJSON(SETTINGS_FILE);
21
+ }
22
+ async function loadProfile(profileId) {
23
+ const profilePath = path_1.default.join(PROFILES_DIR, `${profileId}.json`);
24
+ if (!(await fs_extra_1.default.pathExists(profilePath))) {
25
+ throw new Error(`Profile not found: ${profileId}`);
26
+ }
27
+ return fs_extra_1.default.readJSON(profilePath);
28
+ }
29
+ async function listProfiles() {
30
+ if (!(await fs_extra_1.default.pathExists(PROFILES_DIR))) {
31
+ await fs_extra_1.default.ensureDir(PROFILES_DIR);
32
+ return [];
33
+ }
34
+ const files = await fs_extra_1.default.readdir(PROFILES_DIR);
35
+ const profiles = [];
36
+ for (const file of files) {
37
+ if (file.endsWith('.json')) {
38
+ const profile = await fs_extra_1.default.readJSON(path_1.default.join(PROFILES_DIR, file));
39
+ profiles.push(profile);
40
+ }
41
+ }
42
+ return profiles;
43
+ }
44
+ function getCurrentProvider(settings) {
45
+ const baseUrl = settings.env?.ANTHROPIC_BASE_URL;
46
+ if (!baseUrl)
47
+ return 'anthropic';
48
+ if (baseUrl.includes('bigmodel.cn'))
49
+ return 'zhipu';
50
+ if (baseUrl.includes('api.anthropic.com'))
51
+ return 'anthropic';
52
+ return 'custom';
53
+ }
54
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/lib/config/loader.ts"],"names":[],"mappings":";;;;;AASA,oCAKC;AAED,kCAMC;AAED,oCAcC;AAED,gDAMC;AA9CD,wDAA0B;AAC1B,gDAAwB;AACxB,4CAAoB;AAGpB,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACtD,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AAC7D,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAEhD,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,kBAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AACpC,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,SAAiB;IACjD,MAAM,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,SAAS,OAAO,CAAC,CAAC;IACjE,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,kBAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAClC,CAAC;AAEM,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QACzC,MAAM,kBAAE,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACjC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;YACjE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAgB,kBAAkB,CAAC,QAAkB;IACnD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IACjD,IAAI,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC;IACjC,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,OAAO,CAAC;IACpD,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QAAE,OAAO,WAAW,CAAC;IAC9D,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,30 @@
1
+ export interface ProviderProfile {
2
+ id: string;
3
+ name: string;
4
+ description?: string;
5
+ icon?: string;
6
+ config: {
7
+ env: {
8
+ ANTHROPIC_AUTH_TOKEN: string;
9
+ ANTHROPIC_BASE_URL?: string;
10
+ ANTHROPIC_DEFAULT_HAIKU_MODEL?: string;
11
+ ANTHROPIC_DEFAULT_OPUS_MODEL?: string;
12
+ ANTHROPIC_DEFAULT_SONNET_MODEL?: string;
13
+ API_TIMEOUT_MS?: string;
14
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC?: string;
15
+ [key: string]: string | undefined;
16
+ };
17
+ };
18
+ }
19
+ export interface Settings {
20
+ env?: Record<string, string>;
21
+ enabledPlugins?: Record<string, boolean>;
22
+ permissions?: {
23
+ allow?: string[];
24
+ };
25
+ statusLine?: {
26
+ type?: string;
27
+ command?: string;
28
+ };
29
+ [key: string]: any;
30
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/lib/config/schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import { ProviderProfile } from './schema';
2
+ export declare function backupSettings(): Promise<string>;
3
+ export declare function applyProfile(profile: ProviderProfile): Promise<void>;
4
+ export declare function listBackups(): Promise<string[]>;
5
+ export declare function restoreBackup(backupFile: string): Promise<void>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.backupSettings = backupSettings;
7
+ exports.applyProfile = applyProfile;
8
+ exports.listBackups = listBackups;
9
+ exports.restoreBackup = restoreBackup;
10
+ const fs_extra_1 = __importDefault(require("fs-extra"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const os_1 = __importDefault(require("os"));
13
+ const CLAUDE_DIR = path_1.default.join(os_1.default.homedir(), '.claude');
14
+ const SETTINGS_FILE = path_1.default.join(CLAUDE_DIR, 'settings.json');
15
+ const BACKUP_DIR = path_1.default.join(CLAUDE_DIR, 'cc-switch-backups');
16
+ async function backupSettings() {
17
+ await fs_extra_1.default.ensureDir(BACKUP_DIR);
18
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
19
+ const backupPath = path_1.default.join(BACKUP_DIR, `settings-${timestamp}.json`);
20
+ await fs_extra_1.default.copy(SETTINGS_FILE, backupPath);
21
+ return backupPath;
22
+ }
23
+ async function applyProfile(profile) {
24
+ await backupSettings();
25
+ const settings = await fs_extra_1.default.readJSON(SETTINGS_FILE);
26
+ const newEnv = {};
27
+ for (const [key, value] of Object.entries(profile.config.env)) {
28
+ if (value !== undefined) {
29
+ newEnv[key] = value;
30
+ }
31
+ }
32
+ settings.env = { ...settings.env, ...newEnv };
33
+ await fs_extra_1.default.writeJSON(SETTINGS_FILE, settings, { spaces: 2 });
34
+ }
35
+ async function listBackups() {
36
+ if (!(await fs_extra_1.default.pathExists(BACKUP_DIR)))
37
+ return [];
38
+ const files = await fs_extra_1.default.readdir(BACKUP_DIR);
39
+ return files.filter((f) => f.endsWith('.json')).sort().reverse();
40
+ }
41
+ async function restoreBackup(backupFile) {
42
+ const backupPath = path_1.default.join(BACKUP_DIR, backupFile);
43
+ if (!(await fs_extra_1.default.pathExists(backupPath))) {
44
+ throw new Error(`Backup not found: ${backupFile}`);
45
+ }
46
+ await fs_extra_1.default.copy(backupPath, SETTINGS_FILE);
47
+ }
48
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/lib/config/writer.ts"],"names":[],"mappings":";;;;;AASA,wCAMC;AAED,oCAaC;AAED,kCAIC;AAED,sCAMC;AA5CD,wDAA0B;AAC1B,gDAAwB;AACxB,4CAAoB;AAGpB,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACtD,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AAC7D,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;AAEvD,KAAK,UAAU,cAAc;IAClC,MAAM,kBAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,SAAS,OAAO,CAAC,CAAC;IACvE,MAAM,kBAAE,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IACzC,OAAO,UAAU,CAAC;AACpB,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,OAAwB;IACzD,MAAM,cAAc,EAAE,CAAC;IAEvB,MAAM,QAAQ,GAAa,MAAM,kBAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC5D,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,GAAG,GAAG,EAAE,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAE9C,MAAM,kBAAE,CAAC,SAAS,CAAC,aAAa,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AAC7D,CAAC;AAEM,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;AAC3E,CAAC;AAEM,KAAK,UAAU,aAAa,CAAC,UAAkB;IACpD,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACrD,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,MAAM,kBAAE,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function quickSelect(): Promise<void>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.quickSelect = quickSelect;
7
+ const prompts_1 = __importDefault(require("prompts"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const loader_1 = require("../lib/config/loader");
10
+ const writer_1 = require("../lib/config/writer");
11
+ const loader_2 = require("../lib/config/loader");
12
+ async function quickSelect() {
13
+ const profiles = await (0, loader_1.listProfiles)();
14
+ const settings = await (0, loader_2.loadSettings)();
15
+ const current = (0, loader_2.getCurrentProvider)(settings);
16
+ if (profiles.length === 0) {
17
+ console.log(chalk_1.default.yellow('No profiles found. Create profiles in ~/.claude/profiles/'));
18
+ return;
19
+ }
20
+ const { profileId } = await (0, prompts_1.default)({
21
+ type: 'autocomplete',
22
+ name: 'profileId',
23
+ message: 'Select provider (type to filter):',
24
+ choices: profiles.map(p => ({
25
+ title: `${p.icon || '📦'} ${p.name}`,
26
+ description: p.description,
27
+ value: p.id,
28
+ selected: p.id === current
29
+ })),
30
+ suggest: (input, choices) => {
31
+ return Promise.resolve(choices.filter((choice) => choice.title.toLowerCase().includes(input.toLowerCase())));
32
+ }
33
+ });
34
+ if (profileId) {
35
+ const profile = await (0, loader_1.loadProfile)(profileId);
36
+ await (0, writer_1.applyProfile)(profile);
37
+ console.log(chalk_1.default.green(`✓ Switched to ${profile.name}`));
38
+ }
39
+ }
40
+ //# sourceMappingURL=quick-select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quick-select.js","sourceRoot":"","sources":["../../src/ui/quick-select.ts"],"names":[],"mappings":";;;;;AAMA,kCAgCC;AAtCD,sDAA8B;AAC9B,kDAA0B;AAC1B,iDAAiE;AACjE,iDAAoD;AACpD,iDAAwE;AAEjE,KAAK,UAAU,WAAW;IAC/B,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAY,GAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAY,GAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAA,2BAAkB,EAAC,QAAQ,CAAC,CAAC;IAE7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,2DAA2D,CAAC,CAAC,CAAC;QACvF,OAAO;IACT,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,IAAA,iBAAO,EAAC;QAClC,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,mCAAmC;QAC5C,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1B,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE;YACpC,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,KAAK,EAAE,CAAC,CAAC,EAAE;YACX,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,OAAO;SAC3B,CAAC,CAAC;QACH,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1B,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAW,EAAE,EAAE,CACpD,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CACzD,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,MAAM,IAAA,oBAAW,EAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,IAAA,qBAAY,EAAC,OAAO,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,iBAAiB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@supertiny99/cc-switch",
3
+ "version": "1.0.1",
4
+ "description": "Quick TUI for switching Claude Code API providers - fast provider/token switching when quota is exhausted",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "cc-switch": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "ts-node src/index.ts",
17
+ "link": "npm link",
18
+ "prepublishOnly": "npm run build",
19
+ "pretest": "npm run build",
20
+ "test": "echo \"Error: no test specified\" && exit 1",
21
+ "version": "git add .",
22
+ "postversion": "git push && git push --tags"
23
+ },
24
+ "keywords": [
25
+ "claude",
26
+ "claude-code",
27
+ "cli",
28
+ "switcher",
29
+ "anthropic",
30
+ "api",
31
+ "provider",
32
+ "tui",
33
+ "terminal",
34
+ "config",
35
+ "configuration"
36
+ ],
37
+ "author": "supertiny99 <supertiny99@gmail.com>",
38
+ "license": "MIT",
39
+ "type": "commonjs",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+ssh://git@github.com/supertiny99/cc-switch.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/supertiny99/cc-switch/issues"
46
+ },
47
+ "homepage": "https://github.com/supertiny99/cc-switch#readme",
48
+ "engines": {
49
+ "node": ">=16.0.0"
50
+ },
51
+ "os": [
52
+ "darwin",
53
+ "linux",
54
+ "win32"
55
+ ],
56
+ "dependencies": {
57
+ "chalk": "^5.6.2",
58
+ "commander": "^12.1.0",
59
+ "fs-extra": "^11.3.3",
60
+ "ink": "^4.4.1",
61
+ "lodash": "^4.17.23",
62
+ "prompts": "^2.4.2",
63
+ "react": "^18.3.1"
64
+ },
65
+ "devDependencies": {
66
+ "@types/fs-extra": "^11.0.4",
67
+ "@types/lodash": "^4.17.23",
68
+ "@types/node": "^25.0.10",
69
+ "@types/prompts": "^2.4.9",
70
+ "@types/react": "^19.2.10",
71
+ "ts-node": "^10.9.2",
72
+ "typescript": "^5.9.3"
73
+ }
74
+ }