@adithya-13/cc-switch 1.0.4 → 1.0.6
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.md +0 -24
- package/package.json +2 -3
- package/bin/cclaude.js +0 -90
package/README.md
CHANGED
|
@@ -48,30 +48,6 @@ cc-switch add <name> # add a custom provider
|
|
|
48
48
|
cc-switch doctor # check setup and saved keys
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
## Rate Limit Detection (cclaude)
|
|
52
|
-
|
|
53
|
-
Instead of `claude`, use `cclaude` — it wraps Claude Code and notifies you when a rate limit is hit, with quick-switch suggestions:
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
cclaude # same as claude, but with rate limit detection
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
When a limit is hit:
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
63
|
-
⚠ Claude usage limit reached
|
|
64
|
-
|
|
65
|
-
Available fallbacks:
|
|
66
|
-
|
|
67
|
-
→ z.ai (GLM) cc-switch use zai
|
|
68
|
-
→ Kimi K2 cc-switch use kimi
|
|
69
|
-
|
|
70
|
-
Quick switch: cc-switch use zai
|
|
71
|
-
Then restart: cclaude
|
|
72
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
73
|
-
```
|
|
74
|
-
|
|
75
51
|
## Key Storage
|
|
76
52
|
|
|
77
53
|
API keys are saved in `~/.cc-switch/keys.json` (chmod 600). Never hardcoded or exposed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adithya-13/cc-switch",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Switch Claude Code between providers (Claude Pro, z.ai, Kimi, OpenRouter, DeepSeek, and more)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -21,8 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"type": "module",
|
|
23
23
|
"bin": {
|
|
24
|
-
"cc-switch": "./bin/cc-switch.js"
|
|
25
|
-
"cclaude": "./bin/cclaude.js"
|
|
24
|
+
"cc-switch": "./bin/cc-switch.js"
|
|
26
25
|
},
|
|
27
26
|
"files": [
|
|
28
27
|
"bin",
|
package/bin/cclaude.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from "child_process";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import { readSettings, getCurrentProvider } from "../src/settings.js";
|
|
5
|
-
import { PRESETS } from "../src/presets.js";
|
|
6
|
-
import { loadKeys, loadProfiles } from "../src/profiles.js";
|
|
7
|
-
|
|
8
|
-
const RATE_LIMIT_PATTERNS = [
|
|
9
|
-
/you['']ve hit your limit/i,
|
|
10
|
-
/usage limit reached/i,
|
|
11
|
-
/rate limit/i,
|
|
12
|
-
/Claude\.ai usage limit/i,
|
|
13
|
-
/exceeded.*limit/i,
|
|
14
|
-
/quota exceeded/i,
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
function getAvailableFallbacks(current) {
|
|
18
|
-
const keys = loadKeys();
|
|
19
|
-
const customProfiles = loadProfiles();
|
|
20
|
-
const allProviders = { ...PRESETS, ...customProfiles };
|
|
21
|
-
|
|
22
|
-
return Object.entries(allProviders)
|
|
23
|
-
.filter(([name, preset]) => {
|
|
24
|
-
if (name === current) return false;
|
|
25
|
-
if (preset.requiresKey === false) return true; // pro (OAuth) always "available"
|
|
26
|
-
return !!keys[name]; // only if key is saved
|
|
27
|
-
})
|
|
28
|
-
.map(([name, preset]) => ({ name, label: preset.name || name }));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function notifyRateLimit(current, fallbacks) {
|
|
32
|
-
console.error("\n" + chalk.yellow("━".repeat(50)));
|
|
33
|
-
console.error(chalk.yellow.bold(" ⚠ Claude usage limit reached"));
|
|
34
|
-
console.error(chalk.yellow("━".repeat(50)));
|
|
35
|
-
|
|
36
|
-
if (fallbacks.length === 0) {
|
|
37
|
-
console.error(chalk.gray("\n No saved fallback providers."));
|
|
38
|
-
console.error(chalk.gray(` Add one: ${chalk.cyan("cc-switch add <provider>")}\n`));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
console.error(chalk.bold("\n Available fallbacks:\n"));
|
|
43
|
-
fallbacks.forEach(({ name, label }) => {
|
|
44
|
-
console.error(` ${chalk.cyan("→")} ${label.padEnd(20)} ${chalk.gray(`cc-switch use ${name}`)}`);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const top = fallbacks[0];
|
|
48
|
-
console.error(
|
|
49
|
-
`\n ${chalk.bold("Quick switch:")} ${chalk.cyan(`cc-switch use ${top.name}`)}\n` +
|
|
50
|
-
` Then restart: ${chalk.cyan("cclaude")}\n`
|
|
51
|
-
);
|
|
52
|
-
console.error(chalk.yellow("━".repeat(50)) + "\n");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// run claude, intercept output for rate limit signals
|
|
56
|
-
const settings = readSettings();
|
|
57
|
-
const current = getCurrentProvider(settings);
|
|
58
|
-
|
|
59
|
-
const child = spawn("claude", process.argv.slice(2), {
|
|
60
|
-
stdio: ["inherit", "pipe", "pipe"], // intercept both stdout and stderr
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
let combinedBuffer = "";
|
|
64
|
-
let notified = false;
|
|
65
|
-
|
|
66
|
-
function checkRateLimit(text) {
|
|
67
|
-
if (notified) return;
|
|
68
|
-
const isRateLimit = RATE_LIMIT_PATTERNS.some((p) => p.test(text));
|
|
69
|
-
if (isRateLimit) {
|
|
70
|
-
const fallbacks = getAvailableFallbacks(current);
|
|
71
|
-
notifyRateLimit(current, fallbacks);
|
|
72
|
-
notified = true; // only notify once
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
child.stdout.on("data", (data) => {
|
|
77
|
-
const text = data.toString();
|
|
78
|
-
combinedBuffer += text;
|
|
79
|
-
process.stdout.write(data); // forward to user
|
|
80
|
-
checkRateLimit(combinedBuffer);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
child.stderr.on("data", (data) => {
|
|
84
|
-
const text = data.toString();
|
|
85
|
-
combinedBuffer += text;
|
|
86
|
-
process.stderr.write(data); // forward to user
|
|
87
|
-
checkRateLimit(combinedBuffer);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
child.on("exit", (code) => process.exit(code ?? 0));
|