@adithya-13/cc-switch 1.0.5 → 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 -98
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,98 +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
|
-
// OAuth mode (pro/claude) sends rate limit to stdout, API providers to stderr
|
|
60
|
-
const isOAuthMode = current === "pro" || current === "claude";
|
|
61
|
-
|
|
62
|
-
const child = spawn("claude", process.argv.slice(2), {
|
|
63
|
-
stdio: ["inherit", isOAuthMode ? "pipe" : "inherit", "pipe"], // always pipe stderr
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
let notified = false;
|
|
67
|
-
|
|
68
|
-
function checkRateLimit(text) {
|
|
69
|
-
if (notified) return;
|
|
70
|
-
const isRateLimit = RATE_LIMIT_PATTERNS.some((p) => p.test(text));
|
|
71
|
-
if (isRateLimit) {
|
|
72
|
-
const fallbacks = getAvailableFallbacks(current);
|
|
73
|
-
notifyRateLimit(current, fallbacks);
|
|
74
|
-
notified = true; // only notify once
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Only capture stdout for OAuth mode (pro/claude)
|
|
79
|
-
if (isOAuthMode) {
|
|
80
|
-
let buffer = "";
|
|
81
|
-
child.stdout.on("data", (data) => {
|
|
82
|
-
const text = data.toString();
|
|
83
|
-
buffer += text;
|
|
84
|
-
process.stdout.write(data); // forward to user
|
|
85
|
-
checkRateLimit(buffer);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Always capture stderr for API providers' rate limit errors
|
|
90
|
-
let stderrBuffer = "";
|
|
91
|
-
child.stderr.on("data", (data) => {
|
|
92
|
-
const text = data.toString();
|
|
93
|
-
stderrBuffer += text;
|
|
94
|
-
process.stderr.write(data); // forward to user
|
|
95
|
-
checkRateLimit(stderrBuffer);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
child.on("exit", (code) => process.exit(code ?? 0));
|