claude-multi 0.5.7 → 0.5.8

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +24 -14
  2. package/dist/cli.js +99 -7
  3. package/package.json +11 -4
package/CHANGELOG.md CHANGED
@@ -5,19 +5,29 @@ 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.5.8] - 2026-05-28
9
+
10
+ ### Added
11
+ - **Region selection for MiMo Token Plan** (`--region`): `mimo-token` provider now supports regional endpoints — China (`cn`), Singapore (`sgp`), Europe (`ams`). Users are prompted to pick a region after selecting `mimo-token` in all three entry points (CLI `--region` flag, interactive prompts, Ink TUI wizard). Defaults to `cn` for backward compatibility.
12
+ - **API key prefix mapping** (`API_KEY_PREFIXES`): `mimo-token` shows `tp_...` placeholder in the API key input; all other providers show `sk-...`. Extensible map for future providers with non-standard key formats.
13
+
14
+ ### Changed
15
+ - **`--provider` error message** (`src/cli.ts`): unknown provider error now dynamically lists all available providers instead of hardcoding three names.
16
+ - **Region advisory**: both the interactive prompts and Ink TUI display a highlighted message reminding users to check their Xiaomi account console for the correct region.
17
+
8
18
  ## [0.5.7] - 2026-05-27
9
19
 
10
20
  ### Added
11
21
  - **Provider templates** (`src/templates.ts`): five new AI provider templates
12
- - **Xiaomi MiMo** (`mimo`): MiMo-V2.5-Pro and MiMo-V2.5 via xiaomimimo.com — pay-per-token API
22
+ - **Xiaomi MiMo** (`mimo`): MiMo-V2.5-Pro and MiMo-V2.5 via xiaomimimo.com, pay-per-token API
13
23
  - **Xiaomi MiMo Token Plan** (`mimo-token`): MiMo-V2.5-Pro via xiaomimimo.com subscription; replace base URL with your regional endpoint (CN/SG/EU) from the subscription console
14
- - **Moonshot Kimi** (`kimi`): Kimi K2.6 (opus) and Kimi K2.5 (sonnet/haiku) via moonshot.ai — pay-per-token
15
- - **Alibaba Qwen** (`qwen`): Qwen3-Coder-Next/Plus/Flash via Alibaba DashScope — pay-per-token API
24
+ - **Moonshot Kimi** (`kimi`): Kimi K2.6 (opus) and Kimi K2.5 (sonnet/haiku) via moonshot.ai, pay-per-token
25
+ - **Alibaba Qwen** (`qwen`): Qwen3-Coder-Next/Plus/Flash via Alibaba DashScope, pay-per-token API
16
26
  - **Alibaba Qwen Coding Plan** (`qwen-coding`): Qwen3-Coder-Next/Plus/Flash via DashScope Coding Plan subscription
17
27
 
18
28
  ### Changed
19
29
  - **GLM template** (`glm`): display name updated to "GLM Coding Plan"; description now clarifies the Anthropic endpoint is coding-plan-only (standard Z.ai pay-per-token API has no Anthropic-compatible URL)
20
- - **Kimi template** (`kimi`): sonnet/haiku tiers use `kimi-k2.5` instead of `kimi-k2.6` — same family, ~37% cheaper; legacy K2 series EOL'd May 25 2026
30
+ - **Kimi template** (`kimi`): sonnet/haiku tiers use `kimi-k2.5` instead of `kimi-k2.6`, same family, ~37% cheaper; legacy K2 series EOL'd May 25 2026
21
31
 
22
32
  ## [0.5.6] - 2026-05-23
23
33
 
@@ -27,7 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
27
37
  ### Changed
28
38
  - **Runtime-agnostic launcher** (`bin/claude-multi.js`): polyglot bin entry is simultaneously valid POSIX sh and ESM JavaScript
29
39
  - On Linux/macOS: shell shebang detects bun/node/deno and execs the correct runtime
30
- - On Windows + bun global install: bun's `.exe` shim reads the `.js` extension and runs directly as ESM — no `/bin/sh` lookup required
40
+ - On Windows + bun global install: bun's `.exe` shim reads the `.js` extension and runs directly as ESM, no `/bin/sh` lookup required
31
41
  - On Windows + npm install: npm's `.cmd` shim calls `node` on the `.js` file
32
42
  - Shebang changed to `#!/usr/bin/env bun` so bun's Windows shim can resolve itself in `PATH`
33
43
 
@@ -44,10 +54,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
44
54
 
45
55
  ### Changed
46
56
  - **Cross-runtime support**: all package-manager operations (`upgradeClaudeMulti`, `getCurrentVersion`, `updateClaudeCode`) now use the detected package manager instead of hard-coding bun commands
47
- - `getLatestVersion()` replaced `bun pm npm view` with a direct `fetch()` to the npm registry — works in any runtime
57
+ - `getLatestVersion()` replaced `bun pm npm view` with a direct `fetch()` to the npm registry, works in any runtime
48
58
  - `getDefaultBinaryPath()` selects the correct global bin directory for the active package manager on Windows (was always `%LOCALAPPDATA%\bun\bin`)
49
59
  - Generated wrapper shebang changed from `#!/usr/bin/env bun` to `#!/usr/bin/env node`
50
- - Default action (no subcommand) always launches the Ink TUI and awaits `waitUntilExit()` — the `CLAUDE_MULTI_INK=false` prompts fallback is removed
60
+ - Default action (no subcommand) always launches the Ink TUI and awaits `waitUntilExit()`, the `CLAUDE_MULTI_INK=false` prompts fallback is removed
51
61
  - Update check is now **opt-in**: set `CLAUDE_MULTI_UPDATE_CHECK=true` to enable; it no longer runs on every invocation
52
62
  - Removed `interactive` / `i` command alias (default action covers this)
53
63
 
@@ -117,11 +127,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
117
127
  - Verify MCP configuration
118
128
  - Copy between instances
119
129
  - **CLI Plugin Commands**: 5 new `plugins` sub-commands
120
- - `plugins install <instance> <ids...>` — install plugins with collision detection
121
- - `plugins remove <instance> <ids...>` — remove plugins with symlink guard
122
- - `plugins list-defaults` — list all 50 default plugins with category/MCP badges
123
- - `plugins list-installed [instance]` — list installed plugins per instance
124
- - `plugins check-collisions <instance> <ids...>` — detect MCP name conflicts
130
+ - `plugins install <instance> <ids...>`, install plugins with collision detection
131
+ - `plugins remove <instance> <ids...>`, remove plugins with symlink guard
132
+ - `plugins list-defaults`, list all 50 default plugins with category/MCP badges
133
+ - `plugins list-installed [instance]`, list installed plugins per instance
134
+ - `plugins check-collisions <instance> <ids...>`, detect MCP name conflicts
125
135
  - **Provider Templates**: DeepSeek provider template added
126
136
  - **Instance State**: `initializeInstanceState()` creates `.claude.json` with `hasCompletedOnboarding: true`
127
137
  - **Provider Env**: `mergeProviderEnv()` integrates provider template env vars into instance settings
@@ -131,7 +141,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
131
141
  - `copyAllFromDefault()` restored `autoSync` parameter for symlink-based plugin sync
132
142
  - `syncPluginsAndSkills()` creates actual symlinks instead of copying files
133
143
  - Broken symlink detection uses `lstatSync` (works when `existsSync` returns false)
134
- - `~/.claude` is strictly read-only — never modified by any operation
144
+ - `~/.claude` is strictly read-only, never modified by any operation
135
145
  - Atomic file writes for both config.json and settings.json (temp-file-rename pattern)
136
146
  - Lazy path resolution in migration.ts and health.ts for testability
137
147
 
@@ -139,7 +149,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
139
149
  - `syncPluginsAndSkills` was doing recursive copy instead of creating symlinks
140
150
  - `copyAllFromDefault` `autoSync` parameter was removed, breaking symlink-based sync
141
151
  - Broken symlinks not cleaned before creating new ones (used `lstatSync` instead of `existsSync`)
142
- - `isClaudeCodeRunning()` blocked tests — skips in `NODE_ENV=test`
152
+ - `isClaudeCodeRunning()` blocked tests, skips in `NODE_ENV=test`
143
153
  - `writeFileSync` not imported in config.ts
144
154
  - `McpSourceDetails` prop name mismatch in ManageMcp
145
155
  - `renameSync` dynamic import in `saveConfigAtomic` replaced with top-level import
package/dist/cli.js CHANGED
@@ -7293,6 +7293,25 @@ var require_prompts3 = __commonJS((exports, module) => {
7293
7293
  });
7294
7294
 
7295
7295
  // src/templates.ts
7296
+ function getApiKeyPlaceholder(providerName) {
7297
+ const prefix = API_KEY_PREFIXES[providerName];
7298
+ return prefix ? `${prefix}...` : "sk-...";
7299
+ }
7300
+ function providerHasRegions(providerName) {
7301
+ return providerName === "mimo-token";
7302
+ }
7303
+ function resolveRegionTemplate(template, region) {
7304
+ if (!providerHasRegions(template.name)) {
7305
+ return template;
7306
+ }
7307
+ const regionConfig = MIMO_TOKEN_REGIONS[region];
7308
+ if (!regionConfig) {
7309
+ throw new Error(`Unknown region '${region}' for ${template.name}. Available: ${Object.keys(MIMO_TOKEN_REGIONS).join(", ")}`);
7310
+ }
7311
+ const resolved = structuredClone(template);
7312
+ resolved.settings.env.ANTHROPIC_BASE_URL = regionConfig.baseUrl;
7313
+ return resolved;
7314
+ }
7296
7315
  function getAvailableProviders() {
7297
7316
  return Object.values(PROVIDER_TEMPLATES);
7298
7317
  }
@@ -7304,7 +7323,7 @@ function applyProviderTemplate(template, apiKey) {
7304
7323
  settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
7305
7324
  return settings;
7306
7325
  }
7307
- var PROVIDER_TEMPLATES;
7326
+ var PROVIDER_TEMPLATES, API_KEY_PREFIXES, MIMO_TOKEN_REGIONS;
7308
7327
  var init_templates = __esm(() => {
7309
7328
  PROVIDER_TEMPLATES = {
7310
7329
  glm: {
@@ -7468,6 +7487,23 @@ var init_templates = __esm(() => {
7468
7487
  }
7469
7488
  }
7470
7489
  };
7490
+ API_KEY_PREFIXES = {
7491
+ "mimo-token": "tp_"
7492
+ };
7493
+ MIMO_TOKEN_REGIONS = {
7494
+ cn: {
7495
+ label: "China",
7496
+ baseUrl: "https://token-plan-cn.xiaomimimo.com/anthropic"
7497
+ },
7498
+ sgp: {
7499
+ label: "Singapore",
7500
+ baseUrl: "https://token-plan-sgp.xiaomimimo.com/anthropic"
7501
+ },
7502
+ ams: {
7503
+ label: "Europe",
7504
+ baseUrl: "https://token-plan-ams.xiaomimimo.com/anthropic"
7505
+ }
7506
+ };
7471
7507
  });
7472
7508
 
7473
7509
  // src/util/json-file.ts
@@ -53787,6 +53823,10 @@ function useConfig() {
53787
53823
  getDefaultBinaryPath,
53788
53824
  getAvailableProviders,
53789
53825
  getProviderTemplate,
53826
+ providerHasRegions,
53827
+ resolveRegionTemplate,
53828
+ MIMO_TOKEN_REGIONS,
53829
+ getApiKeyPlaceholder,
53790
53830
  updateInstanceAutoSync,
53791
53831
  syncPluginsAndSkills,
53792
53832
  initializeInstanceState,
@@ -53899,6 +53939,7 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
53899
53939
  const [error, setError] = import_react67.useState("");
53900
53940
  const [useProvider, setUseProvider] = import_react67.useState(false);
53901
53941
  const [selectedProvider, setSelectedProvider] = import_react67.useState(null);
53942
+ const [selectedRegion, setSelectedRegion] = import_react67.useState(null);
53902
53943
  const [apiKey, setApiKey] = import_react67.useState("");
53903
53944
  const [autoSync, setAutoSync] = import_react67.useState(false);
53904
53945
  const [copyOption, setCopyOption] = import_react67.useState(CopyOption.None);
@@ -53918,7 +53959,8 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
53918
53959
  const goBack = import_react67.useCallback(() => {
53919
53960
  const prevMap = {
53920
53961
  "provider-select": "name",
53921
- "provider-apikey": "provider-select",
53962
+ "provider-region": "provider-select",
53963
+ "provider-apikey": "provider-region",
53922
53964
  "paths-confirm": "provider-select",
53923
53965
  "copy-options": "paths-confirm",
53924
53966
  "select-plugins": "copy-options",
@@ -53954,6 +53996,14 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
53954
53996
  }
53955
53997
  setUseProvider(true);
53956
53998
  setSelectedProvider(value);
53999
+ if (providerHasRegions(value)) {
54000
+ setStep("provider-region");
54001
+ } else {
54002
+ setStep("provider-apikey");
54003
+ }
54004
+ }, []);
54005
+ const handleRegionSelect = import_react67.useCallback((value) => {
54006
+ setSelectedRegion(value);
53957
54007
  setStep("provider-apikey");
53958
54008
  }, []);
53959
54009
  const handleApiKeySubmit = import_react67.useCallback((value) => {
@@ -54022,7 +54072,10 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
54022
54072
  await cfg.copySettingsFromDefault(cDir);
54023
54073
  }
54024
54074
  if (useProvider && selectedProvider) {
54025
- const template2 = cfg.getProviderTemplate(selectedProvider);
54075
+ let template2 = cfg.getProviderTemplate(selectedProvider);
54076
+ if (template2 && selectedRegion && providerHasRegions(selectedProvider)) {
54077
+ template2 = resolveRegionTemplate(template2, selectedRegion);
54078
+ }
54026
54079
  if (template2)
54027
54080
  await cfg.mergeProviderEnv(cDir, template2, apiKey);
54028
54081
  }
@@ -54102,6 +54155,33 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
54102
54155
  }, undefined, false, undefined, this)
54103
54156
  ]
54104
54157
  }, undefined, true, undefined, this),
54158
+ step === "provider-region" && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
54159
+ flexDirection: "column",
54160
+ gap: 1,
54161
+ children: [
54162
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
54163
+ children: "Select your subscription region:"
54164
+ }, undefined, false, undefined, this),
54165
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
54166
+ borderStyle: "round",
54167
+ borderColor: "yellow",
54168
+ paddingX: 1,
54169
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
54170
+ bold: true,
54171
+ color: "yellow",
54172
+ children: "Check your Xiaomi account console to confirm the correct region for your subscription."
54173
+ }, undefined, false, undefined, this)
54174
+ }, undefined, false, undefined, this),
54175
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Select, {
54176
+ options: Object.entries(MIMO_TOKEN_REGIONS).map(([key, val]) => ({
54177
+ label: `${val.label} — ${val.baseUrl}`,
54178
+ value: key
54179
+ })),
54180
+ visibleOptionCount: 3,
54181
+ onChange: handleRegionSelect
54182
+ }, undefined, false, undefined, this)
54183
+ ]
54184
+ }, undefined, true, undefined, this),
54105
54185
  step === "provider-apikey" && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
54106
54186
  flexDirection: "column",
54107
54187
  gap: 1,
@@ -54114,7 +54194,7 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
54114
54194
  ]
54115
54195
  }, undefined, true, undefined, this),
54116
54196
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(PasswordInput, {
54117
- placeholder: "sk-...",
54197
+ placeholder: selectedProvider ? getApiKeyPlaceholder(selectedProvider) : "sk-...",
54118
54198
  onSubmit: handleApiKeySubmit
54119
54199
  }, undefined, false, undefined, this)
54120
54200
  ]
@@ -54240,6 +54320,7 @@ var init_AddInstance = __esm(async () => {
54240
54320
  init_wrapper();
54241
54321
  init_useAnimations();
54242
54322
  init_constants();
54323
+ init_templates();
54243
54324
  await __promiseAll([
54244
54325
  init_build2(),
54245
54326
  init_build3(),
@@ -54253,6 +54334,7 @@ var init_AddInstance = __esm(async () => {
54253
54334
  STEP_TITLES = {
54254
54335
  name: "Instance Name",
54255
54336
  "provider-select": "Provider Template",
54337
+ "provider-region": "Region",
54256
54338
  "provider-apikey": "API Key",
54257
54339
  "paths-confirm": "Paths",
54258
54340
  "copy-options": "Copy Options",
@@ -54264,6 +54346,7 @@ var init_AddInstance = __esm(async () => {
54264
54346
  STEP_ORDER = [
54265
54347
  "name",
54266
54348
  "provider-select",
54349
+ "provider-region",
54267
54350
  "provider-apikey",
54268
54351
  "paths-confirm",
54269
54352
  "copy-options",
@@ -56942,8 +57025,8 @@ function requireNonEmptyArgs(items, errorMsg, usage) {
56942
57025
  }
56943
57026
  }
56944
57027
  var program2 = new Command;
56945
- program2.name("claude-multi").description("Manage multiple Claude Code instances with different aliases").version("0.5.5");
56946
- program2.command("add <name>").description("Add a new Claude Code instance").option("-c, --config <dir>", "Config directory path", (name) => join7(homedir4(), `.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").option("--auto-sync", "Auto-sync plugins/skills via symlinks (default)").option("--manual", "Manually manage plugins/skills (copy files)").action(async (name, options) => {
57028
+ program2.name("claude-multi").description("Manage multiple Claude Code instances with different aliases").version("0.5.8");
57029
+ program2.command("add <name>").description("Add a new Claude Code instance").option("-c, --config <dir>", "Config directory path", (name) => join7(homedir4(), `.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, deepseek, mimo, mimo-token, kimi, qwen, qwen-coding)").option("--api-key <key>", "API key for the provider").option("--region <region>", "Region for regional providers (e.g., cn, sgp, ams for mimo-token)").option("--auto-sync", "Auto-sync plugins/skills via symlinks (default)").option("--manual", "Manually manage plugins/skills (copy files)").action(async (name, options) => {
56947
57030
  try {
56948
57031
  const configDir = options.config || join7(homedir4(), `.claude-${name}`);
56949
57032
  const binaryPath = options.binary || getDefaultBinaryPath(name);
@@ -56959,7 +57042,7 @@ program2.command("add <name>").description("Add a new Claude Code instance").opt
56959
57042
  if (options.provider) {
56960
57043
  providerTemplate = getProviderTemplate(options.provider);
56961
57044
  if (!providerTemplate) {
56962
- console.error(source_default.red(`✗ Unknown provider '${options.provider}'. Available: glm, minimax, deepseek`));
57045
+ console.error(source_default.red(`✗ Unknown provider '${options.provider}'. Available: ${getAvailableProviders().map((p) => p.name).join(", ")}`));
56963
57046
  exitWithCode(1);
56964
57047
  }
56965
57048
  if (!options.apiKey) {
@@ -56968,6 +57051,15 @@ program2.command("add <name>").description("Add a new Claude Code instance").opt
56968
57051
  }
56969
57052
  apiKey = options.apiKey;
56970
57053
  useProviderTemplate = true;
57054
+ if (providerHasRegions(providerTemplate.name)) {
57055
+ const region = options.region || "cn";
57056
+ try {
57057
+ providerTemplate = resolveRegionTemplate(providerTemplate, region);
57058
+ } catch (err) {
57059
+ console.error(source_default.red(`✗ ${toMessage(err)}`));
57060
+ exitWithCode(1);
57061
+ }
57062
+ }
56971
57063
  }
56972
57064
  if (options.copySettings || options.copyAll || options.copyMcp || options.skipPrompts || options.provider) {
56973
57065
  if (options.copyAll) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-multi",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "description": "Manage multiple Claude Code instances with different aliases and configurations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,7 +23,9 @@
23
23
  "docs:preview": "astro preview",
24
24
  "ci:docs:deploy": "gh workflow run deploy-docs.yml",
25
25
  "ci:publish": "gh workflow run publish.yml -f version=$(node -p \"require('./package.json').version\")",
26
- "ci:test-install": "gh workflow run test-install.yml"
26
+ "ci:test-install": "gh workflow run test-install.yml",
27
+ "tts-server": "bash scripts/start-tts-server.sh",
28
+ "generate-audio": "bun run scripts/generate-audio.ts"
27
29
  },
28
30
  "keywords": [
29
31
  "claude",
@@ -74,6 +76,11 @@
74
76
  "@astrojs/rss": "^4.0.18",
75
77
  "@iconify-json/lucide": "^1.2.109",
76
78
  "@iconify-json/simple-icons": "^1.2.83",
77
- "astro-icon": "^1.1.5"
78
- }
79
+ "astro-icon": "^1.1.5",
80
+ "sharp": "^0.34.5"
81
+ },
82
+ "trustedDependencies": [
83
+ "onnxruntime-node",
84
+ "protobufjs"
85
+ ]
79
86
  }