claude-multi 0.2.0 → 0.4.1

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/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env node
2
- import { createRequire } from "node:module";
1
+ #!/usr/bin/env bun
2
+ // @bun
3
3
  var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
@@ -17,7 +17,7 @@ var __toESM = (mod, isNodeMode, target) => {
17
17
  return to;
18
18
  };
19
19
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
20
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
+ var __require = import.meta.require;
21
21
 
22
22
  // node_modules/commander/lib/error.js
23
23
  var require_error = __commonJS((exports) => {
@@ -342,7 +342,7 @@ var require_help = __commonJS((exports) => {
342
342
  return Math.max(helper.longestOptionTermLength(cmd, helper), helper.longestGlobalOptionTermLength(cmd, helper), helper.longestSubcommandTermLength(cmd, helper), helper.longestArgumentTermLength(cmd, helper));
343
343
  }
344
344
  wrap(str, width, indent, minColumnWidth = 40) {
345
- const indents = " \\f\\t\\v   -    \uFEFF";
345
+ const indents = " \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF";
346
346
  const manualIndent = new RegExp(`[\\n][${indents}]+`);
347
347
  if (str.match(manualIndent))
348
348
  return str;
@@ -354,7 +354,7 @@ var require_help = __commonJS((exports) => {
354
354
  `, `
355
355
  `);
356
356
  const indentString = " ".repeat(indent);
357
- const zeroWidthSpace = "​";
357
+ const zeroWidthSpace = "\u200B";
358
358
  const breaks = `\\s${zeroWidthSpace}`;
359
359
  const regex = new RegExp(`
360
360
  |.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`, "g");
@@ -597,11 +597,11 @@ var require_suggestSimilar = __commonJS((exports) => {
597
597
 
598
598
  // node_modules/commander/lib/command.js
599
599
  var require_command = __commonJS((exports) => {
600
- var EventEmitter = __require("node:events").EventEmitter;
601
- var childProcess = __require("node:child_process");
602
- var path = __require("node:path");
603
- var fs = __require("node:fs");
604
- var process2 = __require("node:process");
600
+ var EventEmitter = __require("events").EventEmitter;
601
+ var childProcess = __require("child_process");
602
+ var path = __require("path");
603
+ var fs = __require("fs");
604
+ var process2 = __require("process");
605
605
  var { Argument, humanReadableArgName } = require_argument();
606
606
  var { CommanderError } = require_error();
607
607
  var { Help } = require_help();
@@ -2162,18 +2162,18 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
2162
2162
  // node_modules/prompts/dist/util/figures.js
2163
2163
  var require_figures = __commonJS((exports, module) => {
2164
2164
  var main = {
2165
- arrowUp: "↑",
2166
- arrowDown: "↓",
2167
- arrowLeft: "←",
2168
- arrowRight: "→",
2169
- radioOn: "◉",
2170
- radioOff: "◯",
2171
- tick: "✔",
2172
- cross: "✖",
2173
- ellipsis: "…",
2174
- pointerSmall: "›",
2175
- line: "─",
2176
- pointer: "❯"
2165
+ arrowUp: "\u2191",
2166
+ arrowDown: "\u2193",
2167
+ arrowLeft: "\u2190",
2168
+ arrowRight: "\u2192",
2169
+ radioOn: "\u25C9",
2170
+ radioOff: "\u25EF",
2171
+ tick: "\u2714",
2172
+ cross: "\u2716",
2173
+ ellipsis: "\u2026",
2174
+ pointerSmall: "\u203A",
2175
+ line: "\u2500",
2176
+ pointer: "\u276F"
2177
2177
  };
2178
2178
  var win = {
2179
2179
  arrowUp: main.arrowUp,
@@ -2182,11 +2182,11 @@ var require_figures = __commonJS((exports, module) => {
2182
2182
  arrowRight: main.arrowRight,
2183
2183
  radioOn: "(*)",
2184
2184
  radioOff: "( )",
2185
- tick: "√",
2186
- cross: "×",
2185
+ tick: "\u221A",
2186
+ cross: "\xD7",
2187
2187
  ellipsis: "...",
2188
- pointerSmall: "»",
2189
- line: "─",
2188
+ pointerSmall: "\xBB",
2189
+ line: "\u2500",
2190
2190
  pointer: ">"
2191
2191
  };
2192
2192
  var figures = process.platform === "win32" ? win : main;
@@ -4686,18 +4686,18 @@ var require_clear2 = __commonJS((exports, module) => {
4686
4686
  // node_modules/prompts/lib/util/figures.js
4687
4687
  var require_figures2 = __commonJS((exports, module) => {
4688
4688
  var main = {
4689
- arrowUp: "↑",
4690
- arrowDown: "↓",
4691
- arrowLeft: "←",
4692
- arrowRight: "→",
4693
- radioOn: "◉",
4694
- radioOff: "◯",
4695
- tick: "✔",
4696
- cross: "✖",
4697
- ellipsis: "…",
4698
- pointerSmall: "›",
4699
- line: "─",
4700
- pointer: "❯"
4689
+ arrowUp: "\u2191",
4690
+ arrowDown: "\u2193",
4691
+ arrowLeft: "\u2190",
4692
+ arrowRight: "\u2192",
4693
+ radioOn: "\u25C9",
4694
+ radioOff: "\u25EF",
4695
+ tick: "\u2714",
4696
+ cross: "\u2716",
4697
+ ellipsis: "\u2026",
4698
+ pointerSmall: "\u203A",
4699
+ line: "\u2500",
4700
+ pointer: "\u276F"
4701
4701
  };
4702
4702
  var win = {
4703
4703
  arrowUp: main.arrowUp,
@@ -4706,11 +4706,11 @@ var require_figures2 = __commonJS((exports, module) => {
4706
4706
  arrowRight: main.arrowRight,
4707
4707
  radioOn: "(*)",
4708
4708
  radioOff: "( )",
4709
- tick: "√",
4710
- cross: "×",
4709
+ tick: "\u221A",
4710
+ cross: "\xD7",
4711
4711
  ellipsis: "...",
4712
- pointerSmall: "»",
4713
- line: "─",
4712
+ pointerSmall: "\xBB",
4713
+ line: "\u2500",
4714
4714
  pointer: ">"
4715
4715
  };
4716
4716
  var figures = process.platform === "win32" ? win : main;
@@ -6969,9 +6969,9 @@ var ansiStyles = assembleStyles();
6969
6969
  var ansi_styles_default = ansiStyles;
6970
6970
 
6971
6971
  // node_modules/chalk/source/vendor/supports-color/index.js
6972
- import process2 from "node:process";
6973
- import os from "node:os";
6974
- import tty from "node:tty";
6972
+ import process2 from "process";
6973
+ import os from "os";
6974
+ import tty from "tty";
6975
6975
  function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
6976
6976
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
6977
6977
  const position = argv.indexOf(prefix + flag);
@@ -7282,14 +7282,75 @@ var source_default = chalk;
7282
7282
 
7283
7283
  // src/cli.ts
7284
7284
  var import_prompts = __toESM(require_prompts3(), 1);
7285
- import { homedir as homedir2 } from "node:os";
7286
- import { join as join2 } from "node:path";
7285
+ import { homedir as homedir2 } from "os";
7286
+ import { join as join3 } from "path";
7287
+
7288
+ // src/config.ts
7289
+ import { existsSync, mkdirSync, readdirSync, statSync, unlinkSync, readlinkSync, rmSync } from "fs";
7290
+ import { readFile, writeFile, copyFile, mkdir, symlink } from "fs/promises";
7291
+ import { homedir } from "os";
7292
+ import { join } from "path";
7293
+
7294
+ // src/templates.ts
7295
+ var PROVIDER_TEMPLATES = {
7296
+ glm: {
7297
+ name: "glm",
7298
+ displayName: "GLM (\u667A\u8C31AI)",
7299
+ description: "GLM-4.5 and GLM-4.7 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.7",
7307
+ ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-4.7",
7308
+ ANTHROPIC_MODEL: "glm-4.7",
7309
+ ANTHROPIC_SMALL_FAST_MODEL: "glm-4.5-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
+ }
7287
7352
 
7288
7353
  // src/config.ts
7289
- import { existsSync, mkdirSync, readdirSync, statSync } from "node:fs";
7290
- import { readFile, writeFile, copyFile, mkdir } from "node:fs/promises";
7291
- import { homedir } from "node:os";
7292
- import { join } from "node:path";
7293
7354
  var CONFIG_DIR = join(homedir(), ".claude-multi");
7294
7355
  var CONFIG_FILE = join(CONFIG_DIR, "config.json");
7295
7356
  function ensureConfigDir() {
@@ -7342,7 +7403,21 @@ async function listInstances() {
7342
7403
  const config = await loadConfig();
7343
7404
  return config.instances;
7344
7405
  }
7406
+ async function updateInstanceAutoSync(name, autoSync) {
7407
+ const config = await loadConfig();
7408
+ const index = config.instances.findIndex((i) => i.name === name);
7409
+ if (index === -1) {
7410
+ return null;
7411
+ }
7412
+ config.instances[index].autoSync = autoSync;
7413
+ await saveConfig(config);
7414
+ return config.instances[index];
7415
+ }
7416
+ var _testDefaultClaudeDir;
7345
7417
  function getDefaultClaudeDir() {
7418
+ if (_testDefaultClaudeDir) {
7419
+ return _testDefaultClaudeDir;
7420
+ }
7346
7421
  return join(homedir(), ".claude");
7347
7422
  }
7348
7423
  function hasDefaultClaudeConfig() {
@@ -7353,16 +7428,29 @@ function hasDefaultClaudeConfig() {
7353
7428
  async function copySettingsFromDefault(targetConfigDir) {
7354
7429
  const defaultDir = getDefaultClaudeDir();
7355
7430
  const sourceSettings = join(defaultDir, "settings.json");
7356
- const targetSettings = join(targetConfigDir, "settings.json");
7357
7431
  if (!existsSync(sourceSettings)) {
7358
7432
  throw new Error("Default Claude settings.json not found");
7359
7433
  }
7434
+ const content = await readFile(sourceSettings, "utf-8");
7435
+ const settings = JSON.parse(content);
7436
+ const safeSettings = {};
7437
+ const SAFE_SETTINGS = [
7438
+ "includeCoAuthoredBy",
7439
+ "alwaysThinkingEnabled",
7440
+ "enabledPlugins"
7441
+ ];
7442
+ for (const key of SAFE_SETTINGS) {
7443
+ if (settings[key] !== undefined) {
7444
+ safeSettings[key] = settings[key];
7445
+ }
7446
+ }
7360
7447
  if (!existsSync(targetConfigDir)) {
7361
7448
  await mkdir(targetConfigDir, { recursive: true });
7362
7449
  }
7363
- await copyFile(sourceSettings, targetSettings);
7450
+ const targetSettings = join(targetConfigDir, "settings.json");
7451
+ await writeFile(targetSettings, JSON.stringify(safeSettings, null, 2), "utf-8");
7364
7452
  }
7365
- async function copyAllFromDefault(targetConfigDir) {
7453
+ async function copyAllFromDefault(targetConfigDir, autoSync = true) {
7366
7454
  const defaultDir = getDefaultClaudeDir();
7367
7455
  if (!existsSync(defaultDir)) {
7368
7456
  throw new Error("Default Claude directory not found");
@@ -7370,6 +7458,7 @@ async function copyAllFromDefault(targetConfigDir) {
7370
7458
  if (!existsSync(targetConfigDir)) {
7371
7459
  await mkdir(targetConfigDir, { recursive: true });
7372
7460
  }
7461
+ const symlinkDirs = ["plugins", "skills"];
7373
7462
  const excludeFiles = [
7374
7463
  "config.json",
7375
7464
  ".config.json",
@@ -7394,10 +7483,24 @@ async function copyAllFromDefault(targetConfigDir) {
7394
7483
  continue;
7395
7484
  }
7396
7485
  if (stat.isDirectory()) {
7397
- if (!existsSync(targetPath)) {
7398
- await mkdir(targetPath, { recursive: true });
7486
+ if (autoSync && symlinkDirs.includes(entry)) {
7487
+ if (existsSync(targetPath)) {
7488
+ try {
7489
+ readlinkSync(targetPath);
7490
+ unlinkSync(targetPath);
7491
+ } catch {
7492
+ rmSync(targetPath, { force: true, recursive: true });
7493
+ }
7494
+ }
7495
+ const relativePath = join("..", "..", ".claude", entry);
7496
+ await symlink(relativePath, targetPath, "dir");
7497
+ console.log(` Symlinked: ${entry} -> ~/.claude/${entry}`);
7498
+ } else {
7499
+ if (!existsSync(targetPath)) {
7500
+ await mkdir(targetPath, { recursive: true });
7501
+ }
7502
+ await copyRecursive(sourcePath, targetPath);
7399
7503
  }
7400
- await copyRecursive(sourcePath, targetPath);
7401
7504
  } else {
7402
7505
  await copyFile(sourcePath, targetPath);
7403
7506
  }
@@ -7498,12 +7601,144 @@ async function listMcpServers(instanceName) {
7498
7601
  const mcpConfig = await detectMcpConfigurations(instance.configDir);
7499
7602
  return mcpConfig?.mcpServers || null;
7500
7603
  }
7604
+ async function createSettingsFromTemplate(targetConfigDir, template, apiKey) {
7605
+ if (!existsSync(targetConfigDir)) {
7606
+ await mkdir(targetConfigDir, { recursive: true });
7607
+ }
7608
+ const settings = applyProviderTemplate(template, apiKey);
7609
+ const settingsFile = join(targetConfigDir, "settings.json");
7610
+ await writeFile(settingsFile, JSON.stringify(settings, null, 2), "utf-8");
7611
+ }
7612
+ async function syncPluginsAndSkills(configDir) {
7613
+ const defaultDir = getDefaultClaudeDir();
7614
+ const symlinkDirs = ["plugins", "skills"];
7615
+ if (!existsSync(configDir)) {
7616
+ throw new Error("Instance config directory does not exist");
7617
+ }
7618
+ for (const dir of symlinkDirs) {
7619
+ const targetPath = join(configDir, dir);
7620
+ const sourcePath = join(defaultDir, dir);
7621
+ if (!existsSync(sourcePath)) {
7622
+ console.log(source_default.yellow(` \u26A0 Source ${dir} not found in ~/.claude, skipping`));
7623
+ continue;
7624
+ }
7625
+ if (existsSync(targetPath)) {
7626
+ try {
7627
+ const linkTarget = readlinkSync(targetPath);
7628
+ const expectedTarget = join("..", "..", ".claude", dir);
7629
+ if (linkTarget === expectedTarget || linkTarget === sourcePath) {
7630
+ console.log(source_default.gray(` \u2713 ${dir} already synced`));
7631
+ continue;
7632
+ }
7633
+ rmSync(targetPath, { force: true });
7634
+ } catch {
7635
+ rmSync(targetPath, { force: true, recursive: true });
7636
+ }
7637
+ }
7638
+ const relativePath = join("..", "..", ".claude", dir);
7639
+ await symlink(relativePath, targetPath, "dir");
7640
+ console.log(source_default.green(` \u2713 Symlinked: ${dir} -> ~/.claude/${dir}`));
7641
+ }
7642
+ }
7643
+ async function unsyncPluginsAndSkills(configDir) {
7644
+ const defaultDir = getDefaultClaudeDir();
7645
+ const symlinkDirs = ["plugins", "skills"];
7646
+ if (!existsSync(configDir)) {
7647
+ throw new Error("Instance config directory does not exist");
7648
+ }
7649
+ for (const dir of symlinkDirs) {
7650
+ const targetPath = join(configDir, dir);
7651
+ const sourcePath = join(defaultDir, dir);
7652
+ if (!existsSync(sourcePath)) {
7653
+ console.log(source_default.yellow(` \u26A0 Source ${dir} not found in ~/.claude, skipping`));
7654
+ continue;
7655
+ }
7656
+ let isSymlink = false;
7657
+ try {
7658
+ readlinkSync(targetPath);
7659
+ isSymlink = true;
7660
+ } catch {}
7661
+ if (isSymlink) {
7662
+ rmSync(targetPath, { force: true });
7663
+ console.log(source_default.gray(` \u2713 Removed symlink for ${dir}`));
7664
+ } else if (!existsSync(targetPath)) {} else {
7665
+ console.log(source_default.yellow(` \u26A0 ${dir} is already a regular directory, skipping`));
7666
+ continue;
7667
+ }
7668
+ await mkdir(targetPath, { recursive: true });
7669
+ const copyRecursive = async (source, target) => {
7670
+ const entries = readdirSync(source);
7671
+ for (const entry of entries) {
7672
+ const sourceEntry = join(source, entry);
7673
+ const targetEntry = join(target, entry);
7674
+ const stat = statSync(sourceEntry);
7675
+ if (stat.isDirectory()) {
7676
+ await mkdir(targetEntry, { recursive: true });
7677
+ await copyRecursive(sourceEntry, targetEntry);
7678
+ } else {
7679
+ await copyFile(sourceEntry, targetEntry);
7680
+ }
7681
+ }
7682
+ };
7683
+ await copyRecursive(sourcePath, targetPath);
7684
+ console.log(source_default.green(` \u2713 Copied files for ${dir}`));
7685
+ }
7686
+ }
7687
+ async function readClaudeSettings(configDir) {
7688
+ const settingsFile = join(configDir, "settings.json");
7689
+ if (!existsSync(settingsFile)) {
7690
+ return null;
7691
+ }
7692
+ try {
7693
+ const content = await readFile(settingsFile, "utf-8");
7694
+ return JSON.parse(content);
7695
+ } catch (error) {
7696
+ console.error(source_default.yellow(`Warning: Failed to parse settings.json: ${error}`));
7697
+ return null;
7698
+ }
7699
+ }
7700
+ async function writeClaudeSettings(configDir, settings) {
7701
+ const settingsFile = join(configDir, "settings.json");
7702
+ if (!existsSync(configDir)) {
7703
+ await mkdir(configDir, { recursive: true });
7704
+ }
7705
+ await writeFile(settingsFile, JSON.stringify(settings, null, 2), "utf-8");
7706
+ }
7707
+ async function getEnabledPlugins(configDir) {
7708
+ const settings = await readClaudeSettings(configDir);
7709
+ return settings?.enabledPlugins || null;
7710
+ }
7711
+ async function setEnabledPlugins(configDir, enabledPlugins) {
7712
+ const settings = await readClaudeSettings(configDir) || {};
7713
+ settings.enabledPlugins = enabledPlugins;
7714
+ await writeClaudeSettings(configDir, settings);
7715
+ }
7716
+ async function enablePlugin(configDir, pluginId) {
7717
+ const settings = await readClaudeSettings(configDir) || {};
7718
+ if (!settings.enabledPlugins) {
7719
+ settings.enabledPlugins = {};
7720
+ }
7721
+ settings.enabledPlugins[pluginId] = true;
7722
+ await writeClaudeSettings(configDir, settings);
7723
+ }
7724
+ async function disablePlugin(configDir, pluginId) {
7725
+ const settings = await readClaudeSettings(configDir) || {};
7726
+ if (!settings.enabledPlugins) {
7727
+ settings.enabledPlugins = {};
7728
+ }
7729
+ settings.enabledPlugins[pluginId] = false;
7730
+ await writeClaudeSettings(configDir, settings);
7731
+ }
7732
+ async function listAvailablePlugins() {
7733
+ const defaultSettings = await readClaudeSettings(getDefaultClaudeDir());
7734
+ return defaultSettings?.enabledPlugins || null;
7735
+ }
7501
7736
 
7502
7737
  // src/wrapper.ts
7503
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, chmodSync, unlinkSync } from "node:fs";
7504
- import { writeFile as writeFile2 } from "node:fs/promises";
7505
- import { resolve, dirname } from "node:path";
7506
- import { execSync } from "node:child_process";
7738
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, chmodSync, unlinkSync as unlinkSync2 } from "fs";
7739
+ import { writeFile as writeFile2 } from "fs/promises";
7740
+ import { resolve, dirname } from "path";
7741
+ import { execSync } from "child_process";
7507
7742
  function getClaudePath() {
7508
7743
  try {
7509
7744
  const command = process.platform === "win32" ? "where claude" : "which claude";
@@ -7520,7 +7755,7 @@ function getClaudePath() {
7520
7755
  }
7521
7756
  function generateWrapperScript(options) {
7522
7757
  const claudePath = getClaudePath();
7523
- return `#!/usr/bin/env node
7758
+ return `#!/usr/bin/env bun
7524
7759
 
7525
7760
  // Claude Multi - Wrapper for ${options.name}
7526
7761
  // Generated by claude-multi
@@ -7570,20 +7805,48 @@ async function createWrapper(options) {
7570
7805
  }
7571
7806
  function removeWrapper(binaryPath) {
7572
7807
  if (existsSync2(binaryPath)) {
7573
- unlinkSync(binaryPath);
7808
+ unlinkSync2(binaryPath);
7574
7809
  }
7575
7810
  }
7576
7811
  function getDefaultBinaryPath(name) {
7577
- const binDir = process.platform === "win32" ? resolve(process.env.APPDATA || "", "npm") : resolve(process.env.HOME || "", ".local", "bin");
7812
+ const binDir = process.platform === "win32" ? resolve(process.env.LOCALAPPDATA || "", "bun", "bin") : resolve(process.env.HOME || "", ".local", "bin");
7578
7813
  const binaryName = process.platform === "win32" ? `claude-${name}.cmd` : `claude-${name}`;
7579
7814
  return resolve(binDir, binaryName);
7580
7815
  }
7581
7816
 
7582
7817
  // src/version.ts
7583
- import { execSync as execSync2 } from "node:child_process";
7818
+ import { execSync as execSync2 } from "child_process";
7819
+ import { readFileSync } from "fs";
7820
+ import { join as join2 } from "path";
7821
+ function getClaudeMultiVersion() {
7822
+ const pkgPath = join2(process.cwd(), "package.json");
7823
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
7824
+ return pkg.version;
7825
+ }
7826
+ async function getLatestClaudeMultiVersion() {
7827
+ const response = await fetch("https://registry.npmjs.org/claude-multi/latest");
7828
+ const data = await response.json();
7829
+ return data.version;
7830
+ }
7831
+ async function checkForClaudeMultiUpdates() {
7832
+ try {
7833
+ const current = getClaudeMultiVersion();
7834
+ const latest = await getLatestClaudeMultiVersion();
7835
+ return {
7836
+ current,
7837
+ latest,
7838
+ updateAvailable: current !== latest
7839
+ };
7840
+ } catch {
7841
+ return { current: "", latest: "", updateAvailable: false };
7842
+ }
7843
+ }
7844
+ function upgradeClaudeMulti() {
7845
+ execSync2("bun upgrade -g claude-multi", { stdio: "inherit" });
7846
+ }
7584
7847
  function getCurrentVersion() {
7585
7848
  try {
7586
- const output = execSync2("npm list -g @anthropic-ai/claude-code --json", {
7849
+ const output = execSync2("bun pm ls -g @anthropic-ai/claude-code --json", {
7587
7850
  encoding: "utf-8",
7588
7851
  stdio: ["pipe", "pipe", "ignore"]
7589
7852
  });
@@ -7596,7 +7859,7 @@ function getCurrentVersion() {
7596
7859
  }
7597
7860
  async function getLatestVersion() {
7598
7861
  try {
7599
- const output = execSync2("npm view @anthropic-ai/claude-code version", {
7862
+ const output = execSync2("bun pm npm view @anthropic-ai/claude-code version", {
7600
7863
  encoding: "utf-8",
7601
7864
  stdio: ["pipe", "pipe", "ignore"]
7602
7865
  });
@@ -7617,7 +7880,7 @@ async function checkForUpdates() {
7617
7880
  async function updateClaudeCode() {
7618
7881
  try {
7619
7882
  console.log("Updating @anthropic-ai/claude-code...");
7620
- execSync2("npm install -g @anthropic-ai/claude-code@latest", {
7883
+ execSync2("bun install -g @anthropic-ai/claude-code@latest", {
7621
7884
  stdio: "inherit"
7622
7885
  });
7623
7886
  console.log("Update completed successfully!");
@@ -7628,17 +7891,34 @@ async function updateClaudeCode() {
7628
7891
 
7629
7892
  // src/cli.ts
7630
7893
  var program2 = new Command;
7631
- program2.name("claude-multi").description("Manage multiple Claude Code instances with different aliases").version("0.1.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) => {
7894
+ program2.name("claude-multi").description("Manage multiple Claude Code instances with different aliases").version("0.4.0");
7895
+ program2.command("add <name>").description("Add a new Claude Code instance").option("-c, --config <dir>", "Config directory path", (name) => join3(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").option("--auto-sync", "Auto-sync plugins/skills via symlinks (default)").option("--manual", "Manually manage plugins/skills (copy files)").action(async (name, options) => {
7633
7896
  try {
7634
- const configDir = options.config || join2(homedir2(), `.claude-${name}`);
7897
+ const configDir = options.config || join3(homedir2(), `.claude-${name}`);
7635
7898
  const binaryPath = options.binary || getDefaultBinaryPath(name);
7636
7899
  const hasDefaultConfig = hasDefaultClaudeConfig();
7637
7900
  const hasDefaultMcp = await hasDefaultMcpConfig();
7638
7901
  let copySettings = false;
7639
7902
  let copyAllFiles = false;
7640
7903
  let copyMcpServers = false;
7641
- if (options.copySettings || options.copyAll || options.copyMcp || options.skipPrompts) {
7904
+ let useProviderTemplate = false;
7905
+ let providerTemplate = null;
7906
+ let apiKey = "";
7907
+ let autoSync = !options.manual;
7908
+ if (options.provider) {
7909
+ providerTemplate = getProviderTemplate(options.provider);
7910
+ if (!providerTemplate) {
7911
+ console.error(source_default.red(`\u2717 Unknown provider '${options.provider}'. Available: glm, minimax`));
7912
+ process.exit(1);
7913
+ }
7914
+ if (!options.apiKey) {
7915
+ console.error(source_default.red("\u2717 --api-key is required when using --provider"));
7916
+ process.exit(1);
7917
+ }
7918
+ apiKey = options.apiKey;
7919
+ useProviderTemplate = true;
7920
+ }
7921
+ if (options.copySettings || options.copyAll || options.copyMcp || options.skipPrompts || options.provider) {
7642
7922
  if (options.copyAll) {
7643
7923
  copyAllFiles = true;
7644
7924
  copySettings = true;
@@ -7680,7 +7960,7 @@ Found existing Claude Code configuration at ~/.claude`));
7680
7960
  ]);
7681
7961
  if (response.copyOption === undefined) {
7682
7962
  console.log(source_default.yellow(`
7683
- ✗ Cancelled`));
7963
+ \u2717 Cancelled`));
7684
7964
  process.exit(0);
7685
7965
  }
7686
7966
  copySettings = response.copyOption === "settings" || response.copyOption === "settings+mcp" || response.copyOption === "all";
@@ -7691,28 +7971,39 @@ Found existing Claude Code configuration at ~/.claude`));
7691
7971
  name,
7692
7972
  configDir,
7693
7973
  binaryPath,
7694
- createdAt: new Date().toISOString()
7974
+ createdAt: new Date().toISOString(),
7975
+ autoSync
7695
7976
  };
7696
7977
  await addInstance(instance);
7697
7978
  await createWrapper(instance);
7698
7979
  if (copySettings && !copyAllFiles) {
7699
7980
  await copySettingsFromDefault(configDir);
7700
- console.log(source_default.green("✓ Copied settings.json"));
7981
+ console.log(source_default.green("\u2713 Copied settings.json"));
7701
7982
  }
7702
7983
  if (copyMcpServers && !copyAllFiles) {
7703
7984
  try {
7704
7985
  await copyMcpServersFromDefault(configDir);
7705
- console.log(source_default.green("✓ Copied MCP server configurations"));
7986
+ console.log(source_default.green("\u2713 Copied MCP server configurations"));
7706
7987
  } catch (error) {
7707
- console.log(source_default.yellow(`⚠ Warning: ${error.message}`));
7988
+ console.log(source_default.yellow(`\u26A0 Warning: ${error.message}`));
7708
7989
  }
7709
7990
  }
7710
7991
  if (copyAllFiles) {
7711
- await copyAllFromDefault(configDir);
7712
- console.log(source_default.green("✓ Copied all files from default Claude"));
7992
+ await copyAllFromDefault(configDir, autoSync);
7993
+ if (autoSync) {
7994
+ console.log(source_default.green("\u2713 Copied all files with auto-sync (plugins/skills symlinked)"));
7995
+ } else {
7996
+ console.log(source_default.green("\u2713 Copied all files from default Claude (manual mode)"));
7997
+ }
7998
+ }
7999
+ if (useProviderTemplate && providerTemplate && !copySettings && !copyAllFiles) {
8000
+ await createSettingsFromTemplate(configDir, providerTemplate, apiKey);
8001
+ console.log(source_default.green(`\u2713 Applied ${providerTemplate.displayName} template`));
8002
+ } else if (useProviderTemplate && (copySettings || copyAllFiles)) {
8003
+ console.log(source_default.yellow("\u26A0 Provider template skipped (copied settings from default Claude)"));
7713
8004
  }
7714
8005
  console.log(source_default.green(`
7715
- ✓ Instance '${name}' created successfully!`));
8006
+ \u2713 Instance '${name}' created successfully!`));
7716
8007
  console.log(source_default.gray(` Binary: ${binaryPath}`));
7717
8008
  console.log(source_default.gray(` Config: ${configDir}`));
7718
8009
  console.log();
@@ -7720,7 +8011,7 @@ Found existing Claude Code configuration at ~/.claude`));
7720
8011
  const pathEnv = process.env.PATH || "";
7721
8012
  const isInPath = pathEnv.split(":").some((p) => p === binDir);
7722
8013
  if (!isInPath) {
7723
- console.log(source_default.yellow(`⚠ Warning: ${binDir} is not in your PATH`));
8014
+ console.log(source_default.yellow(`\u26A0 Warning: ${binDir} is not in your PATH`));
7724
8015
  console.log(source_default.gray(`Add to PATH by running:`));
7725
8016
  console.log(source_default.cyan(` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc`));
7726
8017
  console.log(source_default.cyan(` source ~/.zshrc`));
@@ -7730,7 +8021,7 @@ Found existing Claude Code configuration at ~/.claude`));
7730
8021
  console.log(source_default.cyan(`Run: claude-${name} --help`));
7731
8022
  }
7732
8023
  } catch (error) {
7733
- console.error(source_default.red(`✗ Error: ${error.message}`));
8024
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
7734
8025
  process.exit(1);
7735
8026
  }
7736
8027
  });
@@ -7738,7 +8029,7 @@ program2.command("remove <name>").alias("rm").description("Remove a Claude Code
7738
8029
  try {
7739
8030
  const instance = await getInstance(name);
7740
8031
  if (!instance) {
7741
- console.error(source_default.red(`✗ Instance '${name}' not found`));
8032
+ console.error(source_default.red(`\u2717 Instance '${name}' not found`));
7742
8033
  process.exit(1);
7743
8034
  }
7744
8035
  if (!options.force) {
@@ -7752,11 +8043,11 @@ program2.command("remove <name>").alias("rm").description("Remove a Claude Code
7752
8043
  }
7753
8044
  await removeInstance(name);
7754
8045
  removeWrapper(instance.binaryPath);
7755
- console.log(source_default.green(`✓ Instance '${name}' removed successfully!`));
8046
+ console.log(source_default.green(`\u2713 Instance '${name}' removed successfully!`));
7756
8047
  console.log();
7757
8048
  console.log(source_default.gray(`To remove config files, run: rm -rf ${instance.configDir}`));
7758
8049
  } catch (error) {
7759
- console.error(source_default.red(`✗ Error: ${error.message}`));
8050
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
7760
8051
  process.exit(1);
7761
8052
  }
7762
8053
  });
@@ -7772,14 +8063,16 @@ program2.command("list").alias("ls").description("List all Claude Code instances
7772
8063
  console.log(source_default.bold(`Found ${instances.length} instance(s):
7773
8064
  `));
7774
8065
  for (const instance of instances) {
7775
- console.log(source_default.cyan(`● ${instance.name}`));
8066
+ console.log(source_default.cyan(`\u25CF ${instance.name}`));
7776
8067
  console.log(source_default.gray(` Binary: ${instance.binaryPath}`));
7777
8068
  console.log(source_default.gray(` Config: ${instance.configDir}`));
7778
8069
  console.log(source_default.gray(` Created: ${new Date(instance.createdAt).toLocaleString()}`));
8070
+ const autoSyncStatus = instance.autoSync !== false ? source_default.green("on") : source_default.yellow("off");
8071
+ console.log(source_default.gray(` Auto-sync: ${autoSyncStatus}`));
7779
8072
  console.log();
7780
8073
  }
7781
8074
  } catch (error) {
7782
- console.error(source_default.red(`✗ Error: ${error.message}`));
8075
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
7783
8076
  process.exit(1);
7784
8077
  }
7785
8078
  });
@@ -7787,7 +8080,7 @@ program2.command("info <name>").description("Show details about a specific insta
7787
8080
  try {
7788
8081
  const instance = await getInstance(name);
7789
8082
  if (!instance) {
7790
- console.error(source_default.red(`✗ Instance '${name}' not found`));
8083
+ console.error(source_default.red(`\u2717 Instance '${name}' not found`));
7791
8084
  process.exit(1);
7792
8085
  }
7793
8086
  console.log(source_default.bold(`Instance: ${source_default.cyan(instance.name)}
@@ -7795,8 +8088,10 @@ program2.command("info <name>").description("Show details about a specific insta
7795
8088
  console.log(`${source_default.gray("Binary:")} ${instance.binaryPath}`);
7796
8089
  console.log(`${source_default.gray("Config:")} ${instance.configDir}`);
7797
8090
  console.log(`${source_default.gray("Created:")} ${new Date(instance.createdAt).toLocaleString()}`);
8091
+ const autoSyncStatus = instance.autoSync !== false ? source_default.green("\u2713 Enabled") : source_default.yellow("\u2717 Disabled");
8092
+ console.log(`${source_default.gray("Auto-sync:")} ${autoSyncStatus}`);
7798
8093
  } catch (error) {
7799
- console.error(source_default.red(`✗ Error: ${error.message}`));
8094
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
7800
8095
  process.exit(1);
7801
8096
  }
7802
8097
  });
@@ -7813,13 +8108,13 @@ program2.command("version").description("Check Claude Code version and updates")
7813
8108
  console.log(`${source_default.gray("Latest:")} ${source_default.cyan(versionInfo.latest)}`);
7814
8109
  console.log();
7815
8110
  if (versionInfo.updateAvailable) {
7816
- console.log(source_default.yellow(`⚠ Update available: ${versionInfo.latest}`));
8111
+ console.log(source_default.yellow(`\u26A0 Update available: ${versionInfo.latest}`));
7817
8112
  console.log(source_default.gray("Run 'claude-multi update' to update"));
7818
8113
  } else if (versionInfo.current) {
7819
- console.log(source_default.green("✓ You're up to date!"));
8114
+ console.log(source_default.green("\u2713 You're up to date!"));
7820
8115
  }
7821
8116
  } catch (error) {
7822
- console.error(source_default.red(`✗ Error: ${error.message}`));
8117
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
7823
8118
  process.exit(1);
7824
8119
  }
7825
8120
  });
@@ -7827,20 +8122,206 @@ program2.command("update").description("Update @anthropic-ai/claude-code to the
7827
8122
  try {
7828
8123
  const versionInfo = await checkForUpdates();
7829
8124
  if (!versionInfo.updateAvailable && versionInfo.current) {
7830
- console.log(source_default.green(`✓ Already up to date (${versionInfo.current})`));
8125
+ console.log(source_default.green(`\u2713 Already up to date (${versionInfo.current})`));
7831
8126
  return;
7832
8127
  }
7833
8128
  await updateClaudeCode();
7834
8129
  } catch (error) {
7835
- console.error(source_default.red(`✗ Error: ${error.message}`));
8130
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
8131
+ process.exit(1);
8132
+ }
8133
+ });
8134
+ program2.command("auto-sync <name> <status>").description("Toggle auto-sync for plugins/skills (on/off)").action(async (name, status) => {
8135
+ try {
8136
+ const instance = await getInstance(name);
8137
+ if (!instance) {
8138
+ console.error(source_default.red(`\u2717 Instance '${name}' not found`));
8139
+ process.exit(1);
8140
+ }
8141
+ const newStatus = status.toLowerCase() === "on" || status.toLowerCase() === "true" || status === "1";
8142
+ const currentStatus = instance.autoSync !== false;
8143
+ if (currentStatus === newStatus) {
8144
+ console.log(source_default.yellow(`Auto-sync is already ${newStatus ? "enabled" : "disabled"} for '${name}'`));
8145
+ return;
8146
+ }
8147
+ await updateInstanceAutoSync(name, newStatus);
8148
+ console.log(source_default.bold(`
8149
+ \uD83D\uDD04 ${newStatus ? "Enabling" : "Disabling"} auto-sync for '${name}'...
8150
+ `));
8151
+ if (newStatus) {
8152
+ await syncPluginsAndSkills(instance.configDir);
8153
+ } else {
8154
+ await unsyncPluginsAndSkills(instance.configDir);
8155
+ }
8156
+ console.log(source_default.green(`
8157
+ \u2713 Auto-sync ${newStatus ? "enabled" : "disabled"} for '${name}'`));
8158
+ } catch (error) {
8159
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
8160
+ process.exit(1);
8161
+ }
8162
+ });
8163
+ program2.command("plugins").description("Manage enabled plugins for instances").argument("[action]", "Action to perform (list, enable, disable, copy)", "list").argument("[instance]", "Instance name (for list/enable/disable)", "").argument("[plugins...]", "Plugin IDs to enable/disable", []).action(async (action = "list", instanceName = "", plugins = []) => {
8164
+ try {
8165
+ switch (action) {
8166
+ case "list":
8167
+ await handlePluginsList(instanceName);
8168
+ break;
8169
+ case "enable":
8170
+ await handlePluginsEnable(instanceName, plugins);
8171
+ break;
8172
+ case "disable":
8173
+ await handlePluginsDisable(instanceName, plugins);
8174
+ break;
8175
+ case "copy":
8176
+ await handlePluginsCopy(instanceName);
8177
+ break;
8178
+ default:
8179
+ console.error(source_default.red(`\u2717 Unknown action: ${action}`));
8180
+ console.log(source_default.gray("Available actions: list, enable, disable, copy"));
8181
+ process.exit(1);
8182
+ }
8183
+ } catch (error) {
8184
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
7836
8185
  process.exit(1);
7837
8186
  }
7838
8187
  });
8188
+ async function handlePluginsList(instanceName) {
8189
+ const instances = await listInstances();
8190
+ if (!instanceName) {
8191
+ console.log(source_default.bold(`
8192
+ \uD83D\uDCCB Enabled Plugins by Instance
8193
+ `));
8194
+ const defaultPlugins = await listAvailablePlugins();
8195
+ if (defaultPlugins) {
8196
+ console.log(source_default.gray(`Default Claude (~/.claude):`));
8197
+ const enabledCount = Object.values(defaultPlugins).filter((v) => v === true).length;
8198
+ console.log(source_default.gray(` Plugins: ${enabledCount} enabled
8199
+ `));
8200
+ for (const [pluginId, enabled] of Object.entries(defaultPlugins)) {
8201
+ const status = enabled ? source_default.green("\u2713") : source_default.gray("\u2717");
8202
+ console.log(source_default.gray(` ${status} ${pluginId}`));
8203
+ }
8204
+ console.log();
8205
+ }
8206
+ if (instances.length === 0) {
8207
+ console.log(source_default.yellow("No instances found."));
8208
+ return;
8209
+ }
8210
+ for (const instance of instances) {
8211
+ const plugins = await getEnabledPlugins(instance.configDir);
8212
+ console.log(source_default.cyan(`${instance.name}:`));
8213
+ if (plugins) {
8214
+ const enabledCount = Object.values(plugins).filter((v) => v === true).length;
8215
+ console.log(source_default.gray(` Plugins: ${enabledCount} enabled
8216
+ `));
8217
+ for (const [pluginId, enabled] of Object.entries(plugins)) {
8218
+ const status = enabled ? source_default.green("\u2713") : source_default.gray("\u2717");
8219
+ console.log(source_default.gray(` ${status} ${pluginId}`));
8220
+ }
8221
+ } else {
8222
+ console.log(source_default.yellow(" No plugins configured"));
8223
+ }
8224
+ console.log();
8225
+ }
8226
+ } else {
8227
+ const instance = await getInstance(instanceName);
8228
+ if (!instance) {
8229
+ console.error(source_default.red(`\u2717 Instance '${instanceName}' not found`));
8230
+ process.exit(1);
8231
+ }
8232
+ const plugins = await getEnabledPlugins(instance.configDir);
8233
+ if (!plugins) {
8234
+ console.log(source_default.yellow(`No plugins configured for '${instanceName}'`));
8235
+ return;
8236
+ }
8237
+ console.log(source_default.bold(`
8238
+ \uD83D\uDCCB Enabled Plugins for '${instanceName}'
8239
+ `));
8240
+ for (const [pluginId, enabled] of Object.entries(plugins)) {
8241
+ const status = enabled ? source_default.green("\u2713") : source_default.gray("\u2717");
8242
+ console.log(`${status} ${source_default.cyan(pluginId)}`);
8243
+ }
8244
+ }
8245
+ }
8246
+ async function handlePluginsEnable(instanceName, plugins) {
8247
+ const instance = await getInstance(instanceName);
8248
+ if (!instance) {
8249
+ console.error(source_default.red(`\u2717 Instance '${instanceName}' not found`));
8250
+ process.exit(1);
8251
+ }
8252
+ if (plugins.length === 0) {
8253
+ console.error(source_default.red("\u2717 No plugins specified"));
8254
+ console.log(source_default.gray("Usage: claude-multi plugins enable <instance> <plugin-id>..."));
8255
+ process.exit(1);
8256
+ }
8257
+ const currentPlugins = await getEnabledPlugins(instance.configDir) || {};
8258
+ let updated = false;
8259
+ for (const pluginId of plugins) {
8260
+ if (currentPlugins[pluginId] === true) {
8261
+ console.log(source_default.yellow(`\u26A0 Plugin '${pluginId}' is already enabled`));
8262
+ } else {
8263
+ currentPlugins[pluginId] = true;
8264
+ await enablePlugin(instance.configDir, pluginId);
8265
+ console.log(source_default.green(`\u2713 Enabled plugin '${pluginId}'`));
8266
+ updated = true;
8267
+ }
8268
+ }
8269
+ if (updated) {
8270
+ console.log(source_default.green(`
8271
+ \u2713 Updated plugins for '${instanceName}'`));
8272
+ }
8273
+ }
8274
+ async function handlePluginsDisable(instanceName, plugins) {
8275
+ const instance = await getInstance(instanceName);
8276
+ if (!instance) {
8277
+ console.error(source_default.red(`\u2717 Instance '${instanceName}' not found`));
8278
+ process.exit(1);
8279
+ }
8280
+ if (plugins.length === 0) {
8281
+ console.error(source_default.red("\u2717 No plugins specified"));
8282
+ console.log(source_default.gray("Usage: claude-multi plugins disable <instance> <plugin-id>..."));
8283
+ process.exit(1);
8284
+ }
8285
+ const currentPlugins = await getEnabledPlugins(instance.configDir) || {};
8286
+ let updated = false;
8287
+ for (const pluginId of plugins) {
8288
+ if (currentPlugins[pluginId] === false) {
8289
+ console.log(source_default.yellow(`\u26A0 Plugin '${pluginId}' is already disabled`));
8290
+ } else {
8291
+ currentPlugins[pluginId] = false;
8292
+ await disablePlugin(instance.configDir, pluginId);
8293
+ console.log(source_default.green(`\u2713 Disabled plugin '${pluginId}'`));
8294
+ updated = true;
8295
+ }
8296
+ }
8297
+ if (updated) {
8298
+ console.log(source_default.green(`
8299
+ \u2713 Updated plugins for '${instanceName}'`));
8300
+ }
8301
+ }
8302
+ async function handlePluginsCopy(instanceName) {
8303
+ const instance = await getInstance(instanceName);
8304
+ if (!instance) {
8305
+ console.error(source_default.red(`\u2717 Instance '${instanceName}' not found`));
8306
+ process.exit(1);
8307
+ }
8308
+ const defaultPlugins = await listAvailablePlugins();
8309
+ if (!defaultPlugins) {
8310
+ console.log(source_default.yellow("No plugins found in default Claude settings"));
8311
+ return;
8312
+ }
8313
+ console.log(source_default.bold(`
8314
+ \uD83D\uDCCB Copying plugins from default Claude to '${instanceName}'
8315
+ `));
8316
+ await setEnabledPlugins(instance.configDir, defaultPlugins);
8317
+ const enabledCount = Object.values(defaultPlugins).filter((v) => v === true).length;
8318
+ console.log(source_default.green(`\u2713 Copied ${enabledCount} enabled plugins to '${instanceName}'`));
8319
+ }
7839
8320
  program2.command("interactive").alias("i").description("Launch interactive mode for managing Claude Code instances").action(async () => {
7840
8321
  try {
7841
8322
  await runInteractiveMode();
7842
8323
  } catch (error) {
7843
- console.error(source_default.red(`✗ Error: ${error.message}`));
8324
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
7844
8325
  process.exit(1);
7845
8326
  }
7846
8327
  });
@@ -7861,11 +8342,13 @@ async function runInteractiveMode() {
7861
8342
  name: "action",
7862
8343
  message: "What would you like to do?",
7863
8344
  choices: [
7864
- { title: "➕ Add new instance", value: "add" },
8345
+ { title: "\u2795 Add new instance", value: "add" },
7865
8346
  { title: "\uD83D\uDCCB List all instances", value: "list" },
7866
8347
  ...instances.length > 0 ? [
7867
- { title: "ℹ️ Show instance details", value: "info" },
7868
- { title: "\uD83D\uDDD1️ Remove instance", value: "remove" }
8348
+ { title: "\u2139\uFE0F Show instance details", value: "info" },
8349
+ { title: "\uD83D\uDD0C Manage plugins", value: "plugins" },
8350
+ { title: "\uD83D\uDD04 Toggle auto-sync", value: "autosync" },
8351
+ { title: "\uD83D\uDDD1\uFE0F Remove instance", value: "remove" }
7869
8352
  ] : [],
7870
8353
  { title: "\uD83D\uDEAA Exit", value: "exit" }
7871
8354
  ],
@@ -7886,6 +8369,12 @@ async function runInteractiveMode() {
7886
8369
  case "info":
7887
8370
  await handleShowInstanceInfo(instances);
7888
8371
  break;
8372
+ case "plugins":
8373
+ await handleManagePlugins(instances);
8374
+ break;
8375
+ case "autosync":
8376
+ await handleToggleAutoSync(instances);
8377
+ break;
7889
8378
  case "remove":
7890
8379
  await handleRemoveInstance(instances);
7891
8380
  break;
@@ -7917,7 +8406,7 @@ async function runInteractiveMode() {
7917
8406
  }
7918
8407
  async function handleAddInstance() {
7919
8408
  console.log(source_default.bold(`
7920
- ➕ Add New Instance
8409
+ \u2795 Add New Instance
7921
8410
  `));
7922
8411
  const { name } = await import_prompts.default({
7923
8412
  type: "text",
@@ -7936,9 +8425,52 @@ async function handleAddInstance() {
7936
8425
  return;
7937
8426
  const existing = await getInstance(name);
7938
8427
  if (existing) {
7939
- console.log(source_default.red(`✗ Instance '${name}' already exists`));
8428
+ console.log(source_default.red(`\u2717 Instance '${name}' already exists`));
7940
8429
  return;
7941
8430
  }
8431
+ const { useProvider } = await import_prompts.default({
8432
+ type: "confirm",
8433
+ name: "useProvider",
8434
+ message: "Would you like to use a provider template (GLM, MiniMax)?",
8435
+ initial: false
8436
+ });
8437
+ let providerTemplate = null;
8438
+ let apiKey = "";
8439
+ if (useProvider) {
8440
+ const providers = getAvailableProviders();
8441
+ const providerChoices = [
8442
+ ...providers.map((p) => ({
8443
+ title: `${p.displayName} - ${p.description}`,
8444
+ value: p.name
8445
+ })),
8446
+ { title: "None / Custom", value: "none" }
8447
+ ];
8448
+ const { selectedProvider } = await import_prompts.default({
8449
+ type: "select",
8450
+ name: "selectedProvider",
8451
+ message: "Select a provider:",
8452
+ choices: providerChoices,
8453
+ initial: 0
8454
+ });
8455
+ if (!selectedProvider || selectedProvider === "none") {} else {
8456
+ providerTemplate = getProviderTemplate(selectedProvider);
8457
+ if (providerTemplate) {
8458
+ const { inputApiKey } = await import_prompts.default({
8459
+ type: "password",
8460
+ name: "inputApiKey",
8461
+ message: `Enter your ${providerTemplate.displayName} API key:`,
8462
+ validate: (value) => {
8463
+ if (!value.trim())
8464
+ return "API key is required";
8465
+ return true;
8466
+ }
8467
+ });
8468
+ if (!inputApiKey)
8469
+ return;
8470
+ apiKey = inputApiKey;
8471
+ }
8472
+ }
8473
+ }
7942
8474
  const { useDefaults } = await import_prompts.default({
7943
8475
  type: "confirm",
7944
8476
  name: "useDefaults",
@@ -7948,7 +8480,7 @@ async function handleAddInstance() {
7948
8480
  let configDir;
7949
8481
  let binaryPath;
7950
8482
  if (useDefaults) {
7951
- configDir = join2(homedir2(), `.claude-${name}`);
8483
+ configDir = join3(homedir2(), `.claude-${name}`);
7952
8484
  binaryPath = getDefaultBinaryPath(name);
7953
8485
  } else {
7954
8486
  const configResponse = await import_prompts.default([
@@ -7956,7 +8488,7 @@ async function handleAddInstance() {
7956
8488
  type: "text",
7957
8489
  name: "configDir",
7958
8490
  message: "Config directory path:",
7959
- initial: join2(homedir2(), `.claude-${name}`)
8491
+ initial: join3(homedir2(), `.claude-${name}`)
7960
8492
  },
7961
8493
  {
7962
8494
  type: "text",
@@ -8005,39 +8537,63 @@ async function handleAddInstance() {
8005
8537
  copyMcpServers = copyOption === "mcp" || copyOption === "settings+mcp" || copyOption === "all";
8006
8538
  copyAllFiles = copyOption === "all";
8007
8539
  }
8540
+ let autoSync = true;
8541
+ if (copyAllFiles) {
8542
+ const { autoSync: autoSyncResponse } = await import_prompts.default({
8543
+ type: "confirm",
8544
+ name: "autoSync",
8545
+ message: "Auto-sync plugins and skills via symlinks?",
8546
+ initial: true,
8547
+ hint: "When enabled, plugins/skills are symlinked from ~/.claude (shared across instances)"
8548
+ });
8549
+ if (autoSyncResponse === undefined)
8550
+ return;
8551
+ autoSync = autoSyncResponse;
8552
+ }
8008
8553
  const instance = {
8009
8554
  name,
8010
8555
  configDir,
8011
8556
  binaryPath,
8012
- createdAt: new Date().toISOString()
8557
+ createdAt: new Date().toISOString(),
8558
+ autoSync
8013
8559
  };
8014
8560
  await addInstance(instance);
8015
8561
  await createWrapper(instance);
8016
8562
  if (copySettings && !copyAllFiles) {
8017
8563
  await copySettingsFromDefault(configDir);
8018
- console.log(source_default.green("✓ Copied settings.json"));
8564
+ console.log(source_default.green("\u2713 Copied settings.json"));
8019
8565
  }
8020
8566
  if (copyMcpServers && !copyAllFiles) {
8021
8567
  try {
8022
8568
  await copyMcpServersFromDefault(configDir);
8023
- console.log(source_default.green("✓ Copied MCP server configurations"));
8569
+ console.log(source_default.green("\u2713 Copied MCP server configurations"));
8024
8570
  } catch (error) {
8025
- console.log(source_default.yellow(`⚠ Warning: ${error.message}`));
8571
+ console.log(source_default.yellow(`\u26A0 Warning: ${error.message}`));
8026
8572
  }
8027
8573
  }
8028
8574
  if (copyAllFiles) {
8029
- await copyAllFromDefault(configDir);
8030
- console.log(source_default.green("✓ Copied all files from default Claude"));
8575
+ await copyAllFromDefault(configDir, autoSync);
8576
+ if (autoSync) {
8577
+ console.log(source_default.green("\u2713 Copied all files with auto-sync (plugins/skills symlinked)"));
8578
+ } else {
8579
+ console.log(source_default.green("\u2713 Copied all files from default Claude (manual mode)"));
8580
+ }
8581
+ }
8582
+ if (providerTemplate && !copySettings && !copyAllFiles) {
8583
+ await createSettingsFromTemplate(configDir, providerTemplate, apiKey);
8584
+ console.log(source_default.green(`\u2713 Applied ${providerTemplate.displayName} template`));
8585
+ } else if (providerTemplate && (copySettings || copyAllFiles)) {
8586
+ console.log(source_default.yellow("\u26A0 Provider template skipped (copied settings from default Claude)"));
8031
8587
  }
8032
8588
  console.log(source_default.green(`
8033
- ✓ Instance '${name}' created successfully!`));
8589
+ \u2713 Instance '${name}' created successfully!`));
8034
8590
  console.log(source_default.gray(` Binary: ${binaryPath}`));
8035
8591
  console.log(source_default.gray(` Config: ${configDir}`));
8036
8592
  const binDir = binaryPath.substring(0, binaryPath.lastIndexOf("/"));
8037
8593
  const pathEnv = process.env.PATH || "";
8038
8594
  const isInPath = pathEnv.split(":").some((p) => p === binDir);
8039
8595
  if (!isInPath) {
8040
- console.log(source_default.yellow(`⚠ Warning: ${binDir} is not in your PATH`));
8596
+ console.log(source_default.yellow(`\u26A0 Warning: ${binDir} is not in your PATH`));
8041
8597
  console.log(source_default.gray(`Add to PATH by running:`));
8042
8598
  console.log(source_default.cyan(` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc`));
8043
8599
  console.log(source_default.cyan(` source ~/.zshrc`));
@@ -8055,10 +8611,12 @@ async function handleListInstances(instances) {
8055
8611
  return;
8056
8612
  }
8057
8613
  for (const instance of instances) {
8058
- console.log(source_default.cyan(`● ${instance.name}`));
8614
+ console.log(source_default.cyan(`\u25CF ${instance.name}`));
8059
8615
  console.log(source_default.gray(` Binary: ${instance.binaryPath}`));
8060
8616
  console.log(source_default.gray(` Config: ${instance.configDir}`));
8061
8617
  console.log(source_default.gray(` Created: ${new Date(instance.createdAt).toLocaleString()}`));
8618
+ const autoSyncStatus = instance.autoSync !== false ? source_default.green("on") : source_default.yellow("off");
8619
+ console.log(source_default.gray(` Auto-sync: ${autoSyncStatus}`));
8062
8620
  console.log();
8063
8621
  }
8064
8622
  }
@@ -8068,7 +8626,7 @@ async function handleShowInstanceInfo(instances) {
8068
8626
  return;
8069
8627
  }
8070
8628
  console.log(source_default.bold(`
8071
- ℹ️ Instance Details
8629
+ \u2139\uFE0F Instance Details
8072
8630
  `));
8073
8631
  const { instanceName } = await import_prompts.default({
8074
8632
  type: "select",
@@ -8089,6 +8647,8 @@ Instance: ${source_default.cyan(instance.name)}`));
8089
8647
  console.log(`${source_default.gray("Binary:")} ${instance.binaryPath}`);
8090
8648
  console.log(`${source_default.gray("Config:")} ${instance.configDir}`);
8091
8649
  console.log(`${source_default.gray("Created:")} ${new Date(instance.createdAt).toLocaleString()}`);
8650
+ const autoSyncStatus = instance.autoSync !== false ? source_default.green("\u2713 Enabled") : source_default.yellow("\u2717 Disabled");
8651
+ console.log(`${source_default.gray("Auto-sync:")} ${autoSyncStatus}`);
8092
8652
  }
8093
8653
  async function handleRemoveInstance(instances) {
8094
8654
  if (instances.length === 0) {
@@ -8096,7 +8656,7 @@ async function handleRemoveInstance(instances) {
8096
8656
  return;
8097
8657
  }
8098
8658
  console.log(source_default.bold(`
8099
- \uD83D\uDDD1️ Remove Instance
8659
+ \uD83D\uDDD1\uFE0F Remove Instance
8100
8660
  `));
8101
8661
  const { instanceName } = await import_prompts.default({
8102
8662
  type: "select",
@@ -8119,14 +8679,176 @@ async function handleRemoveInstance(instances) {
8119
8679
  initial: false
8120
8680
  });
8121
8681
  if (!confirm) {
8122
- console.log(source_default.yellow("✗ Cancelled"));
8682
+ console.log(source_default.yellow("\u2717 Cancelled"));
8123
8683
  return;
8124
8684
  }
8125
8685
  await removeInstance(instanceName);
8126
8686
  removeWrapper(instance.binaryPath);
8127
- console.log(source_default.green(`✓ Instance '${instanceName}' removed successfully!`));
8687
+ console.log(source_default.green(`\u2713 Instance '${instanceName}' removed successfully!`));
8128
8688
  console.log(source_default.gray(`To remove config files, run: rm -rf ${instance.configDir}`));
8129
8689
  }
8690
+ async function handleToggleAutoSync(instances) {
8691
+ if (instances.length === 0) {
8692
+ console.log(source_default.yellow("No instances found."));
8693
+ return;
8694
+ }
8695
+ console.log(source_default.bold(`
8696
+ \uD83D\uDD04 Toggle Auto-Sync
8697
+ `));
8698
+ const { instanceName } = await import_prompts.default({
8699
+ type: "select",
8700
+ name: "instanceName",
8701
+ message: "Select an instance:",
8702
+ choices: instances.map((instance2) => {
8703
+ const currentStatus2 = instance2.autoSync !== false ? "on" : "off";
8704
+ return {
8705
+ title: `${instance2.name} (auto-sync: ${currentStatus2})`,
8706
+ value: instance2.name
8707
+ };
8708
+ })
8709
+ });
8710
+ if (!instanceName)
8711
+ return;
8712
+ const instance = instances.find((i) => i.name === instanceName);
8713
+ if (!instance)
8714
+ return;
8715
+ const currentStatus = instance.autoSync !== false;
8716
+ const { action } = await import_prompts.default({
8717
+ type: "select",
8718
+ name: "action",
8719
+ message: `Auto-sync is currently ${source_default.cyan(currentStatus ? "enabled" : "disabled")}. What would you like to do?`,
8720
+ choices: [
8721
+ { title: currentStatus ? "Turn off (copy files locally)" : "Turn on (use symlinks)", value: "toggle" },
8722
+ { title: "Cancel", value: "cancel" }
8723
+ ],
8724
+ initial: 0
8725
+ });
8726
+ if (!action || action === "cancel") {
8727
+ console.log(source_default.yellow("\u2717 Cancelled"));
8728
+ return;
8729
+ }
8730
+ const newStatus = !currentStatus;
8731
+ console.log(source_default.bold(`
8732
+ \uD83D\uDD04 ${newStatus ? "Enabling" : "Disabling"} auto-sync for '${instanceName}'...
8733
+ `));
8734
+ try {
8735
+ await updateInstanceAutoSync(instanceName, newStatus);
8736
+ if (newStatus) {
8737
+ await syncPluginsAndSkills(instance.configDir);
8738
+ } else {
8739
+ await unsyncPluginsAndSkills(instance.configDir);
8740
+ }
8741
+ console.log(source_default.green(`
8742
+ \u2713 Auto-sync ${newStatus ? "enabled" : "disabled"} for '${instanceName}'`));
8743
+ } catch (error) {
8744
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
8745
+ }
8746
+ }
8747
+ async function handleManagePlugins(instances) {
8748
+ if (instances.length === 0) {
8749
+ console.log(source_default.yellow("No instances found."));
8750
+ return;
8751
+ }
8752
+ console.log(source_default.bold(`
8753
+ \uD83D\uDD0C Manage Plugins
8754
+ `));
8755
+ const { action } = await import_prompts.default({
8756
+ type: "select",
8757
+ name: "action",
8758
+ message: "What would you like to do?",
8759
+ choices: [
8760
+ { title: "\uD83D\uDCCB List all plugins", value: "list" },
8761
+ { title: "\uD83D\uDCCB Plugins for instance", value: "instance" },
8762
+ { title: "\u2705 Enable plugins", value: "enable" },
8763
+ { title: "\u274C Disable plugins", value: "disable" },
8764
+ { title: "\uD83D\uDCCB Copy from default", value: "copy" },
8765
+ { title: "Cancel", value: "cancel" }
8766
+ ],
8767
+ initial: 0
8768
+ });
8769
+ if (!action || action === "cancel") {
8770
+ console.log(source_default.yellow("\u2717 Cancelled"));
8771
+ return;
8772
+ }
8773
+ switch (action) {
8774
+ case "list":
8775
+ await handlePluginsList("");
8776
+ break;
8777
+ case "instance":
8778
+ const { listInstance } = await import_prompts.default({
8779
+ type: "select",
8780
+ name: "listInstance",
8781
+ message: "Select an instance:",
8782
+ choices: instances.map((i) => ({ title: i.name, value: i.name }))
8783
+ });
8784
+ if (listInstance) {
8785
+ await handlePluginsList(listInstance);
8786
+ }
8787
+ break;
8788
+ case "enable": {
8789
+ const { enableInstance } = await import_prompts.default({
8790
+ type: "select",
8791
+ name: "enableInstance",
8792
+ message: "Select an instance:",
8793
+ choices: instances.map((i) => ({ title: i.name, value: i.name }))
8794
+ });
8795
+ if (!enableInstance)
8796
+ return;
8797
+ const plugins = await getEnabledPlugins(instances.find((i) => i.name === enableInstance).configDir);
8798
+ if (!plugins) {
8799
+ console.log(source_default.yellow("No plugins configured for this instance"));
8800
+ return;
8801
+ }
8802
+ const { pluginsToEnable } = await import_prompts.default({
8803
+ type: "multiselect",
8804
+ name: "pluginsToEnable",
8805
+ message: "Select plugins to enable:",
8806
+ choices: Object.entries(plugins).filter(([_, enabled]) => !enabled).map(([pluginId, _]) => ({ title: pluginId, value: pluginId }))
8807
+ });
8808
+ if (pluginsToEnable && pluginsToEnable.length > 0) {
8809
+ await handlePluginsEnable(enableInstance, pluginsToEnable);
8810
+ }
8811
+ break;
8812
+ }
8813
+ case "disable": {
8814
+ const { disableInstance } = await import_prompts.default({
8815
+ type: "select",
8816
+ name: "disableInstance",
8817
+ message: "Select an instance:",
8818
+ choices: instances.map((i) => ({ title: i.name, value: i.name }))
8819
+ });
8820
+ if (!disableInstance)
8821
+ return;
8822
+ const plugins = await getEnabledPlugins(instances.find((i) => i.name === disableInstance).configDir);
8823
+ if (!plugins) {
8824
+ console.log(source_default.yellow("No plugins configured for this instance"));
8825
+ return;
8826
+ }
8827
+ const { pluginsToDisable } = await import_prompts.default({
8828
+ type: "multiselect",
8829
+ name: "pluginsToDisable",
8830
+ message: "Select plugins to disable:",
8831
+ choices: Object.entries(plugins).filter(([_, enabled]) => enabled).map(([pluginId, _]) => ({ title: pluginId, value: pluginId }))
8832
+ });
8833
+ if (pluginsToDisable && pluginsToDisable.length > 0) {
8834
+ await handlePluginsDisable(disableInstance, pluginsToDisable);
8835
+ }
8836
+ break;
8837
+ }
8838
+ case "copy": {
8839
+ const { copyInstance } = await import_prompts.default({
8840
+ type: "select",
8841
+ name: "copyInstance",
8842
+ message: "Select an instance:",
8843
+ choices: instances.map((i) => ({ title: i.name, value: i.name }))
8844
+ });
8845
+ if (copyInstance) {
8846
+ await handlePluginsCopy(copyInstance);
8847
+ }
8848
+ break;
8849
+ }
8850
+ }
8851
+ }
8130
8852
  program2.command("mcp").description("Manage MCP server configurations").argument("[action]", "Action to perform (list, copy, verify)", "list").argument("[instance]", "Instance name (for list/verify)", "").argument("[source]", "Source instance name (for copy)", "").argument("[target]", "Target instance name (for copy)", "").action(async (action = "list", instance = "", source = "", target = "") => {
8131
8853
  try {
8132
8854
  switch (action) {
@@ -8140,12 +8862,12 @@ program2.command("mcp").description("Manage MCP server configurations").argument
8140
8862
  await handleMcpVerify(instance);
8141
8863
  break;
8142
8864
  default:
8143
- console.error(source_default.red(`✗ Unknown action: ${action}`));
8865
+ console.error(source_default.red(`\u2717 Unknown action: ${action}`));
8144
8866
  console.log(source_default.gray("Available actions: list, copy, verify"));
8145
8867
  process.exit(1);
8146
8868
  }
8147
8869
  } catch (error) {
8148
- console.error(source_default.red(`✗ Error: ${error.message}`));
8870
+ console.error(source_default.red(`\u2717 Error: ${error.message}`));
8149
8871
  process.exit(1);
8150
8872
  }
8151
8873
  });
@@ -8163,11 +8885,11 @@ async function handleMcpList(instanceName) {
8163
8885
  for (const instance of instances) {
8164
8886
  const mcpServers = await listMcpServers(instance.name);
8165
8887
  const hasMcp = mcpServers && Object.keys(mcpServers).length > 0;
8166
- console.log(source_default.cyan(`● ${instance.name}`));
8888
+ console.log(source_default.cyan(`\u25CF ${instance.name}`));
8167
8889
  console.log(source_default.gray(` MCP Servers: ${hasMcp ? Object.keys(mcpServers).length : "None"}`));
8168
8890
  if (hasMcp) {
8169
8891
  for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
8170
- console.log(source_default.gray(` • ${serverName} (${serverConfig.type})`));
8892
+ console.log(source_default.gray(` \u2022 ${serverName} (${serverConfig.type})`));
8171
8893
  }
8172
8894
  }
8173
8895
  console.log();
@@ -8182,7 +8904,7 @@ async function handleMcpList(instanceName) {
8182
8904
  \uD83D\uDCCB MCP Servers in '${instanceName}'
8183
8905
  `));
8184
8906
  for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
8185
- console.log(source_default.cyan(`● ${serverName}`));
8907
+ console.log(source_default.cyan(`\u25CF ${serverName}`));
8186
8908
  console.log(source_default.gray(` Type: ${serverConfig.type}`));
8187
8909
  if (serverConfig.command) {
8188
8910
  console.log(source_default.gray(` Command: ${serverConfig.command}`));
@@ -8245,7 +8967,7 @@ async function handleMcpCopy(sourceInstanceName, targetInstanceName) {
8245
8967
  \uD83D\uDD04 Copying MCP servers from '${source}' to '${target}'
8246
8968
  `));
8247
8969
  await copyMcpServersBetweenInstances(source, target);
8248
- console.log(source_default.green(`✓ MCP servers copied successfully!`));
8970
+ console.log(source_default.green(`\u2713 MCP servers copied successfully!`));
8249
8971
  }
8250
8972
  async function handleMcpVerify(instanceName) {
8251
8973
  const instances = await listInstances();
@@ -8273,20 +8995,48 @@ async function handleMcpVerify(instanceName) {
8273
8995
  `));
8274
8996
  const mcpServers = await listMcpServers(instance);
8275
8997
  if (!mcpServers) {
8276
- console.log(source_default.yellow("⚠ No MCP configuration found"));
8998
+ console.log(source_default.yellow("\u26A0 No MCP configuration found"));
8277
8999
  return;
8278
9000
  }
8279
9001
  const serverCount = Object.keys(mcpServers).length;
8280
- console.log(source_default.green(`✓ Found ${serverCount} MCP server(s)`));
9002
+ console.log(source_default.green(`\u2713 Found ${serverCount} MCP server(s)`));
8281
9003
  for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
8282
- console.log(source_default.gray(` • ${serverName}: ${serverConfig.type}`));
9004
+ console.log(source_default.gray(` \u2022 ${serverName}: ${serverConfig.type}`));
8283
9005
  if (serverConfig.type === "stdio" && !serverConfig.command) {
8284
- console.log(source_default.yellow(` ⚠ Missing command for stdio server`));
9006
+ console.log(source_default.yellow(` \u26A0 Missing command for stdio server`));
8285
9007
  } else if ((serverConfig.type === "http" || serverConfig.type === "sse") && !serverConfig.url) {
8286
- console.log(source_default.yellow(` ⚠ Missing URL for ${serverConfig.type} server`));
9008
+ console.log(source_default.yellow(` \u26A0 Missing URL for ${serverConfig.type} server`));
8287
9009
  } else {
8288
- console.log(source_default.green(` ✓ Configuration looks valid`));
9010
+ console.log(source_default.green(` \u2713 Configuration looks valid`));
8289
9011
  }
8290
9012
  }
8291
9013
  }
8292
9014
  program2.parse();
9015
+ async function runUpdateCheck() {
9016
+ try {
9017
+ const updateInfo = await checkForClaudeMultiUpdates();
9018
+ if (updateInfo.updateAvailable) {
9019
+ console.log();
9020
+ console.log(source_default.yellow(`New version available: claude-multi ${updateInfo.latest}`));
9021
+ console.log(source_default.gray(`Current version: ${updateInfo.current}`));
9022
+ console.log();
9023
+ const { shouldUpdate } = await import_prompts.default({
9024
+ type: "confirm",
9025
+ name: "shouldUpdate",
9026
+ message: "Would you like to update now?",
9027
+ initial: true
9028
+ });
9029
+ if (shouldUpdate) {
9030
+ console.log(source_default.cyan(`
9031
+ Updating claude-multi...
9032
+ `));
9033
+ upgradeClaudeMulti();
9034
+ console.log(source_default.green(`
9035
+ Update complete! Please run your command again.
9036
+ `));
9037
+ process.exit(0);
9038
+ }
9039
+ }
9040
+ } catch {}
9041
+ }
9042
+ runUpdateCheck().catch(() => {});