@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 +21 -0
- package/README.md +340 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +111 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config/loader.d.ts +5 -0
- package/dist/lib/config/loader.js +54 -0
- package/dist/lib/config/loader.js.map +1 -0
- package/dist/lib/config/schema.d.ts +30 -0
- package/dist/lib/config/schema.js +3 -0
- package/dist/lib/config/schema.js.map +1 -0
- package/dist/lib/config/writer.d.ts +5 -0
- package/dist/lib/config/writer.js +48 -0
- package/dist/lib/config/writer.js.map +1 -0
- package/dist/ui/quick-select.d.ts +1 -0
- package/dist/ui/quick-select.js +40 -0
- package/dist/ui/quick-select.js.map +1 -0
- package/package.json +74 -0
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/)
|
package/dist/index.d.ts
ADDED
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 @@
|
|
|
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
|
+
}
|