cc-x10ded 3.0.14 → 3.0.16

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 CHANGED
@@ -1,109 +1,75 @@
1
1
  # Claude-GLM Wrapper (ccx)
2
2
 
3
- > **šŸ“¢ Community Fork Notice**
4
- >
5
- > This is an actively maintained community fork of the original [claude-glm-wrapper](https://github.com/JoeInnsp23/claude-glm-wrapper).
6
- > Now rewritten in **Bun** for 10x speed and single-binary simplicity.
7
- >
8
- > Install via: `bunx cc-x10ded setup` or download the binary.
3
+ > **Community Fork** of [claude-glm-wrapper](https://github.com/JoeInnsp23/claude-glm-wrapper), rewritten in **Bun** for speed and simplicity.
9
4
 
10
- ---
5
+ Use [Z.AI GLM](https://z.ai), [Minimax](https://minimax.io), [OpenAI](https://openai.com), [Gemini](https://ai.google.dev), and more with [Claude Code](https://www.anthropic.com/claude-code).
11
6
 
12
- Use [Z.AI's GLM models](https://z.ai), [Minimax](https://minimax.io), [OpenAI](https://openai.com), and more with [Claude Code](https://www.anthropic.com/claude-code).
13
-
14
- **One Binary. Zero Friction.**
7
+ ## Quick Start
15
8
 
16
- ## Why ccx?
9
+ ### Installation (Recommended)
17
10
 
18
- **šŸš€ 10x Faster**: Native binary (written in Bun/TypeScript), starts instantly.
19
- **šŸ“¦ Single Binary**: No more "wrapper hell". One `ccx` executable handles everything.
20
- **šŸ›”ļø Safe & Clean**: No more `eval` in shell scripts. Configs stored safely in `~/.config`.
21
- **šŸ”€ Multi-Provider**: Switch between GLM, Minimax, OpenAI, Gemini, and Claude instantly.
22
- **🩺 Self-Healing**: Includes a `doctor` command to diagnose and fix configuration issues automatically.
11
+ ```bash
12
+ # Install globally (fast startup, no resolution overhead)
13
+ bun install -g cc-x10ded@latest
23
14
 
24
- ## Quick Start
15
+ # Run setup wizard
16
+ ccx setup
17
+ ```
25
18
 
26
- ### Installation
19
+ ### Alternative: One-liner with bunx
27
20
 
28
- **If you have Bun (recommended):**
29
21
  ```bash
30
22
  bunx cc-x10ded setup
31
23
  ```
32
24
 
33
- **Manual Download (Mac/Linux/Windows):**
34
- 1. Download the latest release from [GitHub Releases](https://github.com/MohMaya/claude-glm-wrapper/releases).
35
- 2. Run `./ccx setup` (or `.\ccx.exe setup` on Windows).
36
-
37
- ### Setup Wizard
38
-
39
- Run `ccx setup` to:
40
- 1. Configure your API keys (Z.AI, Minimax, OpenAI, etc.).
41
- 2. Install shell aliases (`cc`, `ccg`, `ccm`...) automatically.
42
- 3. Verify your Claude Code installation.
43
-
44
25
  ## Usage
45
26
 
46
27
  ### Commands
47
28
 
48
- | Command | Action |
49
- |---------|--------|
50
- | `ccx` | Run Claude Code with your default model (e.g. GLM-4.7) |
51
- | `ccx setup` | Run the interactive setup wizard |
29
+ | Command | Description |
30
+ |---------|-------------|
31
+ | `ccx` | Run Claude Code with default model (GLM-4.7) |
32
+ | `ccx setup` | Interactive setup wizard |
33
+ | `ccx update` | Update ccx and migrate aliases |
34
+ | `ccx doctor` | Diagnose configuration issues |
52
35
  | `ccx config` | Open configuration file |
53
- | `ccx doctor` | Run self-diagnostics to check API keys, paths, and dependencies |
54
- | `ccx update` | Update to the latest version |
55
- | `ccx --model=gpt-4o` | Run with a specific model override |
56
-
57
- ### Aliases (Optional)
58
36
 
59
- If you enabled aliases during setup:
37
+ ### Model Aliases
60
38
 
39
+ After setup, use these shortcuts:
61
40
 
62
- **šŸ†• New: ccx Multi-Provider Proxy**
63
- | Alias | Equivalent Command |
64
- |-------|-------------------|
65
- | `ccx` | `bunx cc-x10ded` |
66
- | `ccg` | `bunx cc-x10ded --model=glm-4.7` |
67
- | `ccg45` | `bunx cc-x10ded --model=glm-4.5` |
68
- | `ccf` | `bunx cc-x10ded --model=glm-4.5-air` |
69
- | `ccm` | `bunx cc-x10ded --model=MiniMax-M2.1` |
41
+ | Alias | Model |
42
+ |-------|-------|
43
+ | `ccg` | GLM-4.7 (default) |
44
+ | `ccg46` | GLM-4.6 |
45
+ | `ccg45` | GLM-4.5 |
46
+ | `ccf` | GLM-4.5-air (fast) |
47
+ | `ccm` | MiniMax-M2.1 |
70
48
 
71
- ### Multi-Provider Proxy
49
+ ### Multi-Provider Support
72
50
 
73
- `ccx` automatically acts as a local proxy. You can use ANY supported provider by specifying the prefix:
51
+ Specify any provider with a prefix:
74
52
 
75
53
  ```bash
76
54
  ccx --model=openai:gpt-4o
77
- ccx --model=gemini:gemini-1.5-pro
55
+ ccx --model=gemini:gemini-2.0-flash
78
56
  ccx --model=minimax:MiniMax-M2.1
57
+ ccx --model=glm-4.7 # No prefix needed for GLM
79
58
  ```
80
59
 
81
- Or switch **in-session** using Claude's slash command:
82
- `/model openai:gpt-4o`
83
-
84
- ### Auto-Discovery (Zero Config)
85
-
86
- `ccx` is smart! It automatically detects API keys in your environment variables, so you might not even need to run setup.
87
-
88
- Supported variables:
89
- - `ZAI_API_KEY` or `GLM_API_KEY`
90
- - `MINIMAX_API_KEY`
91
- - `OPENAI_API_KEY`
92
- - `ANTHROPIC_API_KEY`
93
- - `GEMINI_API_KEY`
94
- - `OPENROUTER_API_KEY`
60
+ Or switch in-session: `/model openai:gpt-4o`
95
61
 
96
62
  ## Configuration
97
63
 
98
- Config is stored in `~/.config/claude-glm/config.json`.
99
- You can edit it with `ccx config`.
64
+ Config is stored in `~/.config/claude-glm/config.json`:
100
65
 
101
66
  ```json
102
67
  {
103
- "zaiApiKey": "sk-...",
104
- "minimaxApiKey": "...",
68
+ "zaiApiKey": "your-zai-key",
69
+ "minimaxApiKey": "your-minimax-key",
105
70
  "providers": {
106
- "openai": { "apiKey": "sk-..." }
71
+ "openai": { "apiKey": "sk-..." },
72
+ "gemini": { "apiKey": "..." }
107
73
  },
108
74
  "defaults": {
109
75
  "model": "glm-4.7"
@@ -111,33 +77,80 @@ You can edit it with `ccx config`.
111
77
  }
112
78
  ```
113
79
 
80
+ ### Environment Variables (Auto-Discovery)
81
+
82
+ ccx automatically detects these environment variables:
83
+
84
+ - `ZAI_API_KEY` / `GLM_API_KEY`
85
+ - `MINIMAX_API_KEY`
86
+ - `OPENAI_API_KEY`
87
+ - `GEMINI_API_KEY`
88
+ - `ANTHROPIC_API_KEY`
89
+ - `OPENROUTER_API_KEY`
90
+
91
+ ## Updating
92
+
93
+ ```bash
94
+ ccx update
95
+ ```
96
+
97
+ This will:
98
+ 1. Install the latest version globally
99
+ 2. Migrate old `bunx`-based aliases to new format (if needed)
100
+
114
101
  ## Migrating from Old Versions
115
102
 
116
- If you're upgrading from `claude-glm-wrapper` (pre-3.0), you need to clean up the old installation:
103
+ If upgrading from v3.0.14 or earlier (bunx-based aliases):
117
104
 
118
105
  ```bash
119
- # Remove old global package
120
- npm uninstall -g claude-glm-wrapper
106
+ # Update and migrate aliases automatically
107
+ ccx update
121
108
 
122
- # Remove old proxy files (no longer used)
109
+ # Or manually reinstall
110
+ bun install -g cc-x10ded@latest
111
+ ccx setup
112
+ ```
113
+
114
+ If upgrading from pre-3.0 (`claude-glm-wrapper`):
115
+
116
+ ```bash
117
+ # Remove old installation
118
+ npm uninstall -g claude-glm-wrapper
123
119
  rm -rf ~/.claude-proxy/
124
120
 
125
121
  # Install new version
126
- bunx cc-x10ded setup
122
+ bun install -g cc-x10ded@latest
123
+ ccx setup
127
124
  ```
128
125
 
129
- The new version:
130
- - Uses `bunx cc-x10ded` instead of `ccx` command
131
- - Runs proxy in-process (no separate process or `~/.claude-proxy/`)
132
- - Stores config in `~/.config/claude-glm/` (unchanged)
133
-
134
126
  ## Troubleshooting
135
127
 
136
128
  **"ccx: command not found"**
137
- Run `bunx cc-x10ded setup` to install shell aliases, then restart your terminal.
129
+
130
+ Ensure bun's bin directory is in your PATH:
131
+ ```bash
132
+ export PATH="$HOME/.bun/bin:$PATH"
133
+ ```
134
+
135
+ Then reinstall: `bun install -g cc-x10ded@latest`
138
136
 
139
137
  **"Error: 'claude' command not found"**
140
- Run `bunx cc-x10ded doctor` — it will check your Claude Code installation.
138
+
139
+ Run `ccx doctor` to check your Claude Code installation.
140
+
141
+ **Aliases not working after update**
142
+
143
+ Run `ccx update` to migrate aliases, then:
144
+ ```bash
145
+ source ~/.zshrc # or restart your terminal
146
+ ```
147
+
148
+ ## Why ccx?
149
+
150
+ - **Fast startup**: Global binary, no bunx resolution overhead
151
+ - **Multi-provider**: GLM, Minimax, OpenAI, Gemini, Anthropic, OpenRouter
152
+ - **Self-healing**: `ccx doctor` diagnoses and fixes issues
153
+ - **Zero config**: Auto-discovers API keys from environment
141
154
 
142
155
  ## License
143
156
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-x10ded",
3
- "version": "3.0.14",
3
+ "version": "3.0.16",
4
4
  "description": "Extend Claude Code with custom OpenAI-compatible model providers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -88,14 +88,34 @@ export async function setupCommand() {
88
88
  if (mmKey) config.minimaxApiKey = mmKey as string;
89
89
  }
90
90
 
91
- // 4. Shell Config
91
+ // 4. Install ccx globally
92
+ const s2 = spinner();
93
+ s2.start("Installing ccx globally...");
94
+ try {
95
+ const proc = spawn(["bun", "install", "-g", "cc-x10ded@latest"], {
96
+ stdio: ["ignore", "ignore", "ignore"]
97
+ });
98
+ await proc.exited;
99
+ if (proc.exitCode === 0) {
100
+ s2.stop(pc.green("ccx installed globally!"));
101
+ } else {
102
+ s2.stop(pc.yellow("Global install may have failed. You can still use: bunx cc-x10ded"));
103
+ }
104
+ } catch {
105
+ s2.stop(pc.yellow("Could not install globally (bun not found?). Use: bunx cc-x10ded"));
106
+ }
107
+
108
+ // 5. Shell Config
92
109
  const detectedShell = shellInt.detectShell();
93
110
 
94
111
  if (detectedShell !== "unknown") {
112
+ // Ensure bun bin is in PATH
113
+ await shellInt.ensureBunBinInPath(detectedShell);
114
+
95
115
  const installAliases = await select({
96
- message: `Install shell aliases for ${detectedShell}? (cc, ccg, ccm...)`,
116
+ message: `Install shell aliases for ${detectedShell}? (ccg, ccm, ccf...)`,
97
117
  options: [
98
- { value: "yes", label: "Yes, install standard aliases", hint: "Recommended" },
118
+ { value: "yes", label: "Yes, install aliases", hint: "Recommended" },
99
119
  { value: "no", label: "No, I will use 'ccx' directly" },
100
120
  ],
101
121
  });
@@ -106,9 +126,6 @@ export async function setupCommand() {
106
126
  const s = spinner();
107
127
  s.start("Installing aliases...");
108
128
  const success = await shellInt.installAliases(detectedShell);
109
-
110
- // Attempt to ensure local bin is in path
111
- await shellInt.ensureLocalBinInPath(detectedShell);
112
129
 
113
130
  if (success) {
114
131
  s.stop("Aliases installed!");
@@ -120,6 +137,7 @@ export async function setupCommand() {
120
137
  }
121
138
 
122
139
  await configManager.write(config);
123
-
124
- outro(pc.green("Setup complete! Run 'ccx' to start."));
140
+
141
+ note(`To activate now, run: ${pc.cyan("source ~/.zshrc")} (or restart your terminal)`);
142
+ outro(pc.green("Setup complete! Run 'ccx' or 'ccg' to start."));
125
143
  }
package/src/core/shell.ts CHANGED
@@ -83,51 +83,67 @@ export class ShellIntegrator {
83
83
  }
84
84
 
85
85
  private generateAliasBlock(shell: ShellType): string {
86
- // Use bunx for zero-install experience
87
- const cmd = "bunx cc-x10ded";
88
-
86
+ // Use global ccx binary for faster startup (no bunx resolution overhead)
87
+ // ccx is installed globally via: bun install -g cc-x10ded
89
88
  if (shell === "zsh" || shell === "bash") {
90
- return `
91
- alias ccx='${cmd}'
92
- alias ccg='${cmd} --model=glm-4.7'
93
- alias ccg46='${cmd} --model=glm-4.6'
94
- alias ccg45='${cmd} --model=glm-4.5'
95
- alias ccf='${cmd} --model=glm-4.5-air'
96
- alias ccm='${cmd} --model=MiniMax-M2.1'
97
- `.trim();
89
+ return `# Installed via: bun install -g cc-x10ded
90
+ # Update with: ccx update
91
+ alias ccg='ccx --model=glm-4.7'
92
+ alias ccg46='ccx --model=glm-4.6'
93
+ alias ccg45='ccx --model=glm-4.5'
94
+ alias ccf='ccx --model=glm-4.5-air'
95
+ alias ccm='ccx --model=MiniMax-M2.1'`;
98
96
  }
99
97
  if (shell === "fish") {
100
- return `
101
- alias ccx '${cmd}'
102
- alias ccg '${cmd} --model=glm-4.7'
103
- alias ccg46 '${cmd} --model=glm-4.6'
104
- alias ccg45 '${cmd} --model=glm-4.5'
105
- alias ccf '${cmd} --model=glm-4.5-air'
106
- alias ccm '${cmd} --model=MiniMax-M2.1'
107
- `.trim();
98
+ return `# Installed via: bun install -g cc-x10ded
99
+ # Update with: ccx update
100
+ alias ccg 'ccx --model=glm-4.7'
101
+ alias ccg46 'ccx --model=glm-4.6'
102
+ alias ccg45 'ccx --model=glm-4.5'
103
+ alias ccf 'ccx --model=glm-4.5-air'
104
+ alias ccm 'ccx --model=MiniMax-M2.1'`;
108
105
  }
109
106
  if (shell === "powershell") {
110
- return `
111
- Function ccx { ${cmd} @args }
112
- Function ccg { ${cmd} --model=glm-4.7 @args }
113
- Function ccg46 { ${cmd} --model=glm-4.6 @args }
114
- Function ccg45 { ${cmd} --model=glm-4.5 @args }
115
- Function ccf { ${cmd} --model=glm-4.5-air @args }
116
- Function ccm { ${cmd} --model=MiniMax-M2.1 @args }
117
- `.trim();
107
+ return `# Installed via: bun install -g cc-x10ded
108
+ # Update with: ccx update
109
+ Function ccg { ccx --model=glm-4.7 @args }
110
+ Function ccg46 { ccx --model=glm-4.6 @args }
111
+ Function ccg45 { ccx --model=glm-4.5 @args }
112
+ Function ccf { ccx --model=glm-4.5-air @args }
113
+ Function ccm { ccx --model=MiniMax-M2.1 @args }`;
118
114
  }
119
115
  return "";
120
116
  }
121
117
 
118
+ async ensureBunBinInPath(shell: ShellType) {
119
+ if (platform() === "win32") return; // Windows handles PATH differently
120
+
121
+ const profile = this.getProfilePath(shell);
122
+ if (!profile || !existsSync(profile)) return;
123
+
124
+ const bunBin = join(this.home, ".bun", "bin");
125
+ const content = await Bun.file(profile).text();
126
+
127
+ // Check if bun bin is already in PATH (either via env or in profile)
128
+ const bunPathExport = `export PATH="$HOME/.bun/bin:$PATH"`;
129
+ const bunPathExportAlt = `export BUN_INSTALL="$HOME/.bun"`;
130
+
131
+ if (!content.includes(".bun/bin") && !process.env.PATH?.includes(bunBin)) {
132
+ // Add bun to PATH
133
+ const addition = `\n# Bun global binaries\nexport BUN_INSTALL="$HOME/.bun"\nexport PATH="$BUN_INSTALL/bin:$PATH"\n`;
134
+ await Bun.write(profile, content + addition);
135
+ }
136
+ }
137
+
122
138
  async ensureLocalBinInPath(shell: ShellType) {
123
139
  if (platform() === "win32") return; // Windows handles PATH differently (usually handled by installer or user)
124
140
 
125
141
  const profile = this.getProfilePath(shell);
126
142
  if (!profile || !existsSync(profile)) return;
127
-
143
+
128
144
  const localBin = join(this.home, ".local", "bin");
129
145
  const content = await Bun.file(profile).text();
130
-
146
+
131
147
  // Heuristic check
132
148
  if (!content.includes(localBin) && !process.env.PATH?.includes(localBin)) {
133
149
  const exportCmd = `export PATH="$HOME/.local/bin:$PATH"`;
@@ -137,6 +153,33 @@ Function ccm { ${cmd} --model=MiniMax-M2.1 @args }
137
153
  }
138
154
  }
139
155
 
156
+ /**
157
+ * Migrate old bunx-based aliases to new ccx-based aliases
158
+ */
159
+ async migrateAliases(shell: ShellType): Promise<boolean> {
160
+ const profile = this.getProfilePath(shell);
161
+ if (!profile || !existsSync(profile)) return false;
162
+
163
+ let content = await Bun.file(profile).text();
164
+
165
+ // Check if migration is needed (old bunx-based aliases exist)
166
+ if (!content.includes("bunx cc-x10ded")) {
167
+ return false; // No migration needed
168
+ }
169
+
170
+ // Remove old block and install new one
171
+ const startMarker = "# >>> claude-glm-wrapper";
172
+ const endMarker = "# <<< claude-glm-wrapper <<<";
173
+ const regex = new RegExp(`${startMarker}[\\s\\S]*?${endMarker}`, "g");
174
+ content = content.replace(regex, "").trim();
175
+
176
+ // Write cleaned content
177
+ await Bun.write(profile, content);
178
+
179
+ // Install new aliases
180
+ return await this.installAliases(shell);
181
+ }
182
+
140
183
  /**
141
184
  * Hunt for the 'claude' binary in common locations
142
185
  */
package/src/index.ts CHANGED
@@ -22,16 +22,46 @@ cli
22
22
 
23
23
  cli
24
24
  .command("update", "Update ccx to the latest version")
25
- .action(async () => {
26
- console.log("Updating ccx...");
25
+ .option("--skip-aliases", "Skip alias installation")
26
+ .action(async (options: { skipAliases?: boolean }) => {
27
27
  const { spawn } = await import("bun");
28
- const proc = spawn(["npm", "install", "-g", "cc-x10ded"], { stdio: ["inherit", "inherit", "inherit"] });
28
+ const { ShellIntegrator } = await import("./core/shell");
29
+ const pc = await import("picocolors");
30
+
31
+ console.log(pc.default.blue("Updating ccx..."));
32
+
33
+ // Update via bun global install
34
+ const proc = spawn(["bun", "install", "-g", "cc-x10ded@latest"], {
35
+ stdio: ["inherit", "inherit", "inherit"]
36
+ });
29
37
  await proc.exited;
30
- if (proc.exitCode === 0) {
31
- console.log("āœ… Update complete!");
32
- } else {
33
- console.error("āŒ Update failed.");
38
+
39
+ if (proc.exitCode !== 0) {
40
+ console.error(pc.default.red("āŒ Update failed."));
41
+ process.exit(1);
34
42
  }
43
+
44
+ console.log(pc.default.green("āœ… ccx updated!"));
45
+
46
+ // Always reinstall aliases (unless skipped)
47
+ if (!options.skipAliases) {
48
+ const shellInt = new ShellIntegrator();
49
+ const shell = shellInt.detectShell();
50
+
51
+ if (shell !== "unknown") {
52
+ // Ensure bun bin is in PATH
53
+ await shellInt.ensureBunBinInPath(shell);
54
+
55
+ // Install/update aliases
56
+ const success = await shellInt.installAliases(shell);
57
+ if (success) {
58
+ console.log(pc.default.green("āœ… Aliases updated!"));
59
+ console.log(pc.default.dim(` Run: source ~/.${shell}rc (or restart your terminal)`));
60
+ }
61
+ }
62
+ }
63
+
64
+ console.log(pc.default.green("\nšŸŽ‰ Update complete!"));
35
65
  });
36
66
 
37
67
  cli