claude-multi 0.2.0 → 0.3.0
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/CHANGELOG.md +16 -0
- package/README.md +74 -7
- package/dist/cli.js +143 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2025-01-XX
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Provider Templates**: Built-in templates for popular AI providers
|
|
12
|
+
- GLM (智谱AI) template with GLM-4.5-air and GLM-4.6 models
|
|
13
|
+
- MiniMax template with MiniMax-M2 model
|
|
14
|
+
- Interactive provider selection with secure API key prompt
|
|
15
|
+
- CLI flags: `--provider <name>` and `--api-key <key>`
|
|
16
|
+
- Auto-configuration of base URLs, model mappings, and optimal settings
|
|
17
|
+
- **Quick Start Guide**: Added quick start section with provider template examples
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Interactive mode now prompts for provider templates before config copying
|
|
21
|
+
- Enhanced instance creation flow with provider-first approach
|
|
22
|
+
|
|
8
23
|
## [0.2.0] - 2025-01-XX
|
|
9
24
|
|
|
10
25
|
### Added
|
|
@@ -45,5 +60,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
45
60
|
- Support for custom config and binary paths
|
|
46
61
|
- Command-line interface built with Commander.js
|
|
47
62
|
|
|
63
|
+
[0.3.0]: https://github.com/hmziqrs/claude-multi/compare/v0.2.0...v0.3.0
|
|
48
64
|
[0.2.0]: https://github.com/hmziqrs/claude-multi/compare/v0.1.0...v0.2.0
|
|
49
65
|
[0.1.0]: https://github.com/hmziqrs/claude-multi/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ Claude Code supports multiple AI providers (Anthropic, GLM, Minimax), but switch
|
|
|
11
11
|
- 🔄 **Multiple Instances**: Run different Claude Code configs simultaneously
|
|
12
12
|
- 🎯 **Simple CLI**: Easy-to-use commands for managing instances
|
|
13
13
|
- 🔒 **Isolated Configs**: Each instance has its own settings and history
|
|
14
|
+
- 🎨 **Provider Templates**: Built-in templates for GLM, MiniMax, and more
|
|
14
15
|
- ✅ **Legal**: Uses wrapper scripts, no code modification
|
|
15
16
|
- 🚀 **Auto-sync**: Always uses the latest official Claude Code
|
|
16
17
|
|
|
@@ -27,6 +28,31 @@ bun run build
|
|
|
27
28
|
npm link
|
|
28
29
|
```
|
|
29
30
|
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
Get started with a provider template in 30 seconds:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Install claude-multi
|
|
37
|
+
npm link # or npm install -g claude-multi
|
|
38
|
+
|
|
39
|
+
# Create a GLM instance
|
|
40
|
+
claude-multi add glm --provider glm --api-key "your-glm-api-key"
|
|
41
|
+
|
|
42
|
+
# Use it!
|
|
43
|
+
claude-glm --help
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Or use interactive mode:**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
claude-multi add myinstance
|
|
50
|
+
# Choose "Yes" when asked about provider templates
|
|
51
|
+
# Select GLM or MiniMax
|
|
52
|
+
# Enter your API key
|
|
53
|
+
# Done!
|
|
54
|
+
```
|
|
55
|
+
|
|
30
56
|
### Windows Setup
|
|
31
57
|
|
|
32
58
|
On Windows, ensure `%APPDATA%\npm` is in your PATH to use the wrapper commands:
|
|
@@ -46,9 +72,13 @@ After adding to PATH, restart your terminal for changes to take effect.
|
|
|
46
72
|
### Create instances
|
|
47
73
|
|
|
48
74
|
```bash
|
|
49
|
-
# Create instance (interactive - prompts for copying settings)
|
|
75
|
+
# Create instance (interactive - prompts for provider templates and copying settings)
|
|
50
76
|
claude-multi add glm
|
|
51
77
|
|
|
78
|
+
# Create instance with provider template (CLI mode)
|
|
79
|
+
claude-multi add glm --provider glm --api-key "your-api-key-here"
|
|
80
|
+
claude-multi add minimax --provider minimax --api-key "your-api-key-here"
|
|
81
|
+
|
|
52
82
|
# Create instance with custom config path
|
|
53
83
|
claude-multi add work --config ~/configs/claude-work
|
|
54
84
|
|
|
@@ -61,11 +91,18 @@ claude-multi add glm --copy-all # Copy all files (settings, CLAUDE.md,
|
|
|
61
91
|
claude-multi add glm --skip-prompts # Start fresh, no prompts
|
|
62
92
|
```
|
|
63
93
|
|
|
94
|
+
**Provider Templates:**
|
|
95
|
+
- **GLM (智谱AI)**: GLM-4.5-air and GLM-4.6 models via z.ai
|
|
96
|
+
- **MiniMax**: MiniMax-M2 model via minimax.io
|
|
97
|
+
|
|
64
98
|
**Interactive prompt options:**
|
|
99
|
+
- **Provider templates**: Choose GLM, MiniMax, or None/Custom
|
|
65
100
|
- **Nothing - start fresh**: Empty config directory
|
|
66
101
|
- **Only settings.json**: Copy your settings (API keys, preferences)
|
|
67
102
|
- **All files**: Copy settings, CLAUDE.md, plugins, etc. (excludes history, debug logs)
|
|
68
103
|
|
|
104
|
+
When using a provider template, you'll be prompted to enter your API key securely.
|
|
105
|
+
|
|
69
106
|
### Use instances
|
|
70
107
|
|
|
71
108
|
Each instance gets its own command:
|
|
@@ -130,13 +167,20 @@ claude-personal # Personal projects
|
|
|
130
167
|
claude-work # Work projects
|
|
131
168
|
```
|
|
132
169
|
|
|
133
|
-
###
|
|
170
|
+
### Different AI Providers
|
|
134
171
|
```bash
|
|
135
|
-
|
|
136
|
-
claude-multi add
|
|
137
|
-
|
|
138
|
-
claude-
|
|
139
|
-
|
|
172
|
+
# Interactive mode with provider template
|
|
173
|
+
claude-multi add anthropic # Use Anthropic (prompted for API key)
|
|
174
|
+
claude-multi add glm # Use GLM template (prompted for API key)
|
|
175
|
+
claude-multi add minimax # Use MiniMax template (prompted for API key)
|
|
176
|
+
|
|
177
|
+
# CLI mode with provider template
|
|
178
|
+
claude-multi add glm --provider glm --api-key "sk-..."
|
|
179
|
+
claude-multi add minimax --provider minimax --api-key "sk-..."
|
|
180
|
+
|
|
181
|
+
claude-anthropic # Uses Anthropic Claude
|
|
182
|
+
claude-glm # Uses GLM-4.6
|
|
183
|
+
claude-minimax # Uses MiniMax-M2
|
|
140
184
|
```
|
|
141
185
|
|
|
142
186
|
### Multiple Environments
|
|
@@ -148,6 +192,29 @@ claude-multi add dev
|
|
|
148
192
|
# Different configs for each
|
|
149
193
|
```
|
|
150
194
|
|
|
195
|
+
## Provider Templates
|
|
196
|
+
|
|
197
|
+
Built-in templates for popular AI providers. Each template auto-configures the API endpoint, model mappings, and optimal settings.
|
|
198
|
+
|
|
199
|
+
### Available Providers
|
|
200
|
+
|
|
201
|
+
**GLM (智谱AI)**: GLM-4.5-air and GLM-4.6 models via `api.z.ai`
|
|
202
|
+
|
|
203
|
+
**MiniMax**: MiniMax-M2 model via `api.minimax.io`
|
|
204
|
+
|
|
205
|
+
### Usage
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# CLI mode
|
|
209
|
+
claude-multi add glm --provider glm --api-key "your-api-key"
|
|
210
|
+
|
|
211
|
+
# Interactive mode
|
|
212
|
+
claude-multi add myinstance
|
|
213
|
+
# Select provider when prompted and enter API key
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Customize later by editing `~/.claude-{name}/settings.json`
|
|
217
|
+
|
|
151
218
|
## Development
|
|
152
219
|
|
|
153
220
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -7290,6 +7290,67 @@ import { existsSync, mkdirSync, readdirSync, statSync } from "node:fs";
|
|
|
7290
7290
|
import { readFile, writeFile, copyFile, mkdir } from "node:fs/promises";
|
|
7291
7291
|
import { homedir } from "node:os";
|
|
7292
7292
|
import { join } from "node:path";
|
|
7293
|
+
|
|
7294
|
+
// src/templates.ts
|
|
7295
|
+
var PROVIDER_TEMPLATES = {
|
|
7296
|
+
glm: {
|
|
7297
|
+
name: "glm",
|
|
7298
|
+
displayName: "GLM (智谱AI)",
|
|
7299
|
+
description: "GLM-4.5 and GLM-4.6 models via z.ai",
|
|
7300
|
+
settings: {
|
|
7301
|
+
env: {
|
|
7302
|
+
ANTHROPIC_AUTH_TOKEN: "",
|
|
7303
|
+
ANTHROPIC_BASE_URL: "https://api.z.ai/api/anthropic",
|
|
7304
|
+
API_TIMEOUT_MS: "3000000",
|
|
7305
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: "glm-4.5-air",
|
|
7306
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-4.6",
|
|
7307
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-4.6",
|
|
7308
|
+
ANTHROPIC_MODEL: "glm-4.6",
|
|
7309
|
+
ANTHROPIC_SMALL_FAST_MODEL: "glm-4.6-air",
|
|
7310
|
+
ENABLE_THINKING: "true",
|
|
7311
|
+
REASONING_EFFORT: "high",
|
|
7312
|
+
MAX_THINKING_TOKENS: "8000",
|
|
7313
|
+
ENABLE_STREAMING: "true",
|
|
7314
|
+
MAX_OUTPUT_TOKENS: "64000"
|
|
7315
|
+
},
|
|
7316
|
+
includeCoAuthoredBy: false,
|
|
7317
|
+
alwaysThinkingEnabled: false
|
|
7318
|
+
}
|
|
7319
|
+
},
|
|
7320
|
+
minimax: {
|
|
7321
|
+
name: "minimax",
|
|
7322
|
+
displayName: "MiniMax",
|
|
7323
|
+
description: "MiniMax-M2 model via minimax.io",
|
|
7324
|
+
settings: {
|
|
7325
|
+
env: {
|
|
7326
|
+
ANTHROPIC_AUTH_TOKEN: "",
|
|
7327
|
+
ANTHROPIC_BASE_URL: "https://api.minimax.io/anthropic",
|
|
7328
|
+
API_TIMEOUT_MS: "3000000",
|
|
7329
|
+
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
|
|
7330
|
+
ANTHROPIC_MODEL: "MiniMax-M2",
|
|
7331
|
+
ANTHROPIC_SMALL_FAST_MODEL: "MiniMax-M2",
|
|
7332
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "MiniMax-M2",
|
|
7333
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "MiniMax-M2",
|
|
7334
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: "MiniMax-M2"
|
|
7335
|
+
},
|
|
7336
|
+
includeCoAuthoredBy: false,
|
|
7337
|
+
alwaysThinkingEnabled: true
|
|
7338
|
+
}
|
|
7339
|
+
}
|
|
7340
|
+
};
|
|
7341
|
+
function getAvailableProviders() {
|
|
7342
|
+
return Object.values(PROVIDER_TEMPLATES);
|
|
7343
|
+
}
|
|
7344
|
+
function getProviderTemplate(name) {
|
|
7345
|
+
return PROVIDER_TEMPLATES[name.toLowerCase()];
|
|
7346
|
+
}
|
|
7347
|
+
function applyProviderTemplate(template, apiKey) {
|
|
7348
|
+
const settings = JSON.parse(JSON.stringify(template.settings));
|
|
7349
|
+
settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
|
|
7350
|
+
return settings;
|
|
7351
|
+
}
|
|
7352
|
+
|
|
7353
|
+
// src/config.ts
|
|
7293
7354
|
var CONFIG_DIR = join(homedir(), ".claude-multi");
|
|
7294
7355
|
var CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
7295
7356
|
function ensureConfigDir() {
|
|
@@ -7498,6 +7559,14 @@ async function listMcpServers(instanceName) {
|
|
|
7498
7559
|
const mcpConfig = await detectMcpConfigurations(instance.configDir);
|
|
7499
7560
|
return mcpConfig?.mcpServers || null;
|
|
7500
7561
|
}
|
|
7562
|
+
async function createSettingsFromTemplate(targetConfigDir, template, apiKey) {
|
|
7563
|
+
if (!existsSync(targetConfigDir)) {
|
|
7564
|
+
await mkdir(targetConfigDir, { recursive: true });
|
|
7565
|
+
}
|
|
7566
|
+
const settings = applyProviderTemplate(template, apiKey);
|
|
7567
|
+
const settingsFile = join(targetConfigDir, "settings.json");
|
|
7568
|
+
await writeFile(settingsFile, JSON.stringify(settings, null, 2), "utf-8");
|
|
7569
|
+
}
|
|
7501
7570
|
|
|
7502
7571
|
// src/wrapper.ts
|
|
7503
7572
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, chmodSync, unlinkSync } from "node:fs";
|
|
@@ -7628,8 +7697,8 @@ async function updateClaudeCode() {
|
|
|
7628
7697
|
|
|
7629
7698
|
// src/cli.ts
|
|
7630
7699
|
var program2 = new Command;
|
|
7631
|
-
program2.name("claude-multi").description("Manage multiple Claude Code instances with different aliases").version("0.
|
|
7632
|
-
program2.command("add <name>").description("Add a new Claude Code instance").option("-c, --config <dir>", "Config directory path", (name) => join2(homedir2(), `.claude-${name}`)).option("-b, --binary <path>", "Binary path (default: ~/.local/bin/claude-<name>)").option("--copy-settings", "Copy settings.json from default Claude").option("--copy-all", "Copy all files from default Claude").option("--copy-mcp", "Copy MCP server configurations from default Claude").option("--skip-prompts", "Skip interactive prompts (start fresh)").action(async (name, options) => {
|
|
7700
|
+
program2.name("claude-multi").description("Manage multiple Claude Code instances with different aliases").version("0.3.0");
|
|
7701
|
+
program2.command("add <name>").description("Add a new Claude Code instance").option("-c, --config <dir>", "Config directory path", (name) => join2(homedir2(), `.claude-${name}`)).option("-b, --binary <path>", "Binary path (default: ~/.local/bin/claude-<name>)").option("--copy-settings", "Copy settings.json from default Claude").option("--copy-all", "Copy all files from default Claude").option("--copy-mcp", "Copy MCP server configurations from default Claude").option("--skip-prompts", "Skip interactive prompts (start fresh)").option("--provider <name>", "Use a provider template (glm, minimax)").option("--api-key <key>", "API key for the provider").action(async (name, options) => {
|
|
7633
7702
|
try {
|
|
7634
7703
|
const configDir = options.config || join2(homedir2(), `.claude-${name}`);
|
|
7635
7704
|
const binaryPath = options.binary || getDefaultBinaryPath(name);
|
|
@@ -7638,7 +7707,23 @@ program2.command("add <name>").description("Add a new Claude Code instance").opt
|
|
|
7638
7707
|
let copySettings = false;
|
|
7639
7708
|
let copyAllFiles = false;
|
|
7640
7709
|
let copyMcpServers = false;
|
|
7641
|
-
|
|
7710
|
+
let useProviderTemplate = false;
|
|
7711
|
+
let providerTemplate = null;
|
|
7712
|
+
let apiKey = "";
|
|
7713
|
+
if (options.provider) {
|
|
7714
|
+
providerTemplate = getProviderTemplate(options.provider);
|
|
7715
|
+
if (!providerTemplate) {
|
|
7716
|
+
console.error(source_default.red(`✗ Unknown provider '${options.provider}'. Available: glm, minimax`));
|
|
7717
|
+
process.exit(1);
|
|
7718
|
+
}
|
|
7719
|
+
if (!options.apiKey) {
|
|
7720
|
+
console.error(source_default.red("✗ --api-key is required when using --provider"));
|
|
7721
|
+
process.exit(1);
|
|
7722
|
+
}
|
|
7723
|
+
apiKey = options.apiKey;
|
|
7724
|
+
useProviderTemplate = true;
|
|
7725
|
+
}
|
|
7726
|
+
if (options.copySettings || options.copyAll || options.copyMcp || options.skipPrompts || options.provider) {
|
|
7642
7727
|
if (options.copyAll) {
|
|
7643
7728
|
copyAllFiles = true;
|
|
7644
7729
|
copySettings = true;
|
|
@@ -7711,6 +7796,12 @@ Found existing Claude Code configuration at ~/.claude`));
|
|
|
7711
7796
|
await copyAllFromDefault(configDir);
|
|
7712
7797
|
console.log(source_default.green("✓ Copied all files from default Claude"));
|
|
7713
7798
|
}
|
|
7799
|
+
if (useProviderTemplate && providerTemplate && !copySettings && !copyAllFiles) {
|
|
7800
|
+
await createSettingsFromTemplate(configDir, providerTemplate, apiKey);
|
|
7801
|
+
console.log(source_default.green(`✓ Applied ${providerTemplate.displayName} template`));
|
|
7802
|
+
} else if (useProviderTemplate && (copySettings || copyAllFiles)) {
|
|
7803
|
+
console.log(source_default.yellow("⚠ Provider template skipped (copied settings from default Claude)"));
|
|
7804
|
+
}
|
|
7714
7805
|
console.log(source_default.green(`
|
|
7715
7806
|
✓ Instance '${name}' created successfully!`));
|
|
7716
7807
|
console.log(source_default.gray(` Binary: ${binaryPath}`));
|
|
@@ -7939,6 +8030,49 @@ async function handleAddInstance() {
|
|
|
7939
8030
|
console.log(source_default.red(`✗ Instance '${name}' already exists`));
|
|
7940
8031
|
return;
|
|
7941
8032
|
}
|
|
8033
|
+
const { useProvider } = await import_prompts.default({
|
|
8034
|
+
type: "confirm",
|
|
8035
|
+
name: "useProvider",
|
|
8036
|
+
message: "Would you like to use a provider template (GLM, MiniMax)?",
|
|
8037
|
+
initial: false
|
|
8038
|
+
});
|
|
8039
|
+
let providerTemplate = null;
|
|
8040
|
+
let apiKey = "";
|
|
8041
|
+
if (useProvider) {
|
|
8042
|
+
const providers = getAvailableProviders();
|
|
8043
|
+
const providerChoices = [
|
|
8044
|
+
...providers.map((p) => ({
|
|
8045
|
+
title: `${p.displayName} - ${p.description}`,
|
|
8046
|
+
value: p.name
|
|
8047
|
+
})),
|
|
8048
|
+
{ title: "None / Custom", value: "none" }
|
|
8049
|
+
];
|
|
8050
|
+
const { selectedProvider } = await import_prompts.default({
|
|
8051
|
+
type: "select",
|
|
8052
|
+
name: "selectedProvider",
|
|
8053
|
+
message: "Select a provider:",
|
|
8054
|
+
choices: providerChoices,
|
|
8055
|
+
initial: 0
|
|
8056
|
+
});
|
|
8057
|
+
if (!selectedProvider || selectedProvider === "none") {} else {
|
|
8058
|
+
providerTemplate = getProviderTemplate(selectedProvider);
|
|
8059
|
+
if (providerTemplate) {
|
|
8060
|
+
const { inputApiKey } = await import_prompts.default({
|
|
8061
|
+
type: "password",
|
|
8062
|
+
name: "inputApiKey",
|
|
8063
|
+
message: `Enter your ${providerTemplate.displayName} API key:`,
|
|
8064
|
+
validate: (value) => {
|
|
8065
|
+
if (!value.trim())
|
|
8066
|
+
return "API key is required";
|
|
8067
|
+
return true;
|
|
8068
|
+
}
|
|
8069
|
+
});
|
|
8070
|
+
if (!inputApiKey)
|
|
8071
|
+
return;
|
|
8072
|
+
apiKey = inputApiKey;
|
|
8073
|
+
}
|
|
8074
|
+
}
|
|
8075
|
+
}
|
|
7942
8076
|
const { useDefaults } = await import_prompts.default({
|
|
7943
8077
|
type: "confirm",
|
|
7944
8078
|
name: "useDefaults",
|
|
@@ -8029,6 +8163,12 @@ async function handleAddInstance() {
|
|
|
8029
8163
|
await copyAllFromDefault(configDir);
|
|
8030
8164
|
console.log(source_default.green("✓ Copied all files from default Claude"));
|
|
8031
8165
|
}
|
|
8166
|
+
if (providerTemplate && !copySettings && !copyAllFiles) {
|
|
8167
|
+
await createSettingsFromTemplate(configDir, providerTemplate, apiKey);
|
|
8168
|
+
console.log(source_default.green(`✓ Applied ${providerTemplate.displayName} template`));
|
|
8169
|
+
} else if (providerTemplate && (copySettings || copyAllFiles)) {
|
|
8170
|
+
console.log(source_default.yellow("⚠ Provider template skipped (copied settings from default Claude)"));
|
|
8171
|
+
}
|
|
8032
8172
|
console.log(source_default.green(`
|
|
8033
8173
|
✓ Instance '${name}' created successfully!`));
|
|
8034
8174
|
console.log(source_default.gray(` Binary: ${binaryPath}`));
|