ccman 3.0.33 → 3.1.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.
Files changed (3) hide show
  1. package/README.md +6 -6
  2. package/dist/index.js +701 -110
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -29,7 +29,7 @@ ccman 的核心功能是自动化配置文件的切换:
29
29
 
30
30
  如果你更喜欢手动编辑配置文件,或者只使用一个服务商从不切换,可能不需要这个工具。
31
31
 
32
- 📖 更多信息:[GitHub 仓库](https://github.com/2ue/ccm) - 包含手动配置方式和详细对比分析
32
+ 📖 更多信息:[GitHub 仓库](https://github.com/2ue/ccman) - 包含手动配置方式和详细对比分析
33
33
 
34
34
  ---
35
35
 
@@ -41,7 +41,7 @@ npm install -g ccman
41
41
 
42
42
  **要求**:Node.js >= 18.0.0
43
43
 
44
- **Desktop 版本**:如果你更喜欢图形界面,可以从 [GitHub Releases](https://github.com/2ue/ccm/releases) 下载 Desktop 应用(macOS/Windows/Linux)。
44
+ **Desktop 版本**:如果你更喜欢图形界面,可以从 [GitHub Releases](https://github.com/2ue/ccman/releases) 下载 Desktop 应用(macOS/Windows/Linux)。
45
45
 
46
46
  ---
47
47
 
@@ -290,7 +290,7 @@ MIT
290
290
 
291
291
  ## 相关链接
292
292
 
293
- - [GitHub 仓库](https://github.com/2ue/ccm)
294
- - [问题反馈](https://github.com/2ue/ccm/issues)
295
- - [更新日志](https://github.com/2ue/ccm/blob/main/CHANGELOG.md)
296
- - [Desktop 版本](https://github.com/2ue/ccm/releases)(图形界面)
293
+ - [GitHub 仓库](https://github.com/2ue/ccman)
294
+ - [问题反馈](https://github.com/2ue/ccman/issues)
295
+ - [更新日志](https://github.com/2ue/ccman/blob/main/CHANGELOG.md)
296
+ - [Desktop 版本](https://github.com/2ue/ccman/releases)(图形界面)
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "../core/package.json"() {
16
16
  package_default = {
17
17
  name: "@ccman/core",
18
- version: "3.0.33",
18
+ version: "3.1.0",
19
19
  type: "module",
20
20
  description: "Core business logic for ccman",
21
21
  main: "./dist/index.js",
@@ -43,12 +43,12 @@ var init_package = __esm({
43
43
  license: "MIT",
44
44
  repository: {
45
45
  type: "git",
46
- url: "https://github.com/2ue/ccm.git",
46
+ url: "https://github.com/2ue/ccman.git",
47
47
  directory: "packages/core"
48
48
  },
49
- homepage: "https://github.com/2ue/ccm#readme",
49
+ homepage: "https://github.com/2ue/ccman#readme",
50
50
  bugs: {
51
- url: "https://github.com/2ue/ccm/issues"
51
+ url: "https://github.com/2ue/ccman/issues"
52
52
  },
53
53
  dependencies: {
54
54
  "@iarna/toml": "^2.2.5",
@@ -77,6 +77,9 @@ function getCodexDir() {
77
77
  function getClaudeDir() {
78
78
  return claudeDir;
79
79
  }
80
+ function getGeminiDir() {
81
+ return geminiDir;
82
+ }
80
83
  function getConfigPath() {
81
84
  return path.join(ccmanDir, "config.json");
82
85
  }
@@ -92,7 +95,13 @@ function getClaudeConfigPath() {
92
95
  function getClaudeJsonPath() {
93
96
  return path.join(rootDir, ".claude.json");
94
97
  }
95
- var isDev, isTest, rootDir, ccmanDir, codexDir, claudeDir;
98
+ function getGeminiSettingsPath() {
99
+ return path.join(geminiDir, "settings.json");
100
+ }
101
+ function getGeminiEnvPath() {
102
+ return path.join(geminiDir, ".env");
103
+ }
104
+ var isDev, isTest, rootDir, ccmanDir, codexDir, claudeDir, geminiDir;
96
105
  var init_paths = __esm({
97
106
  "../core/dist/paths.js"() {
98
107
  "use strict";
@@ -108,6 +117,7 @@ var init_paths = __esm({
108
117
  ccmanDir = path.join(rootDir, ".ccman");
109
118
  codexDir = path.join(rootDir, ".codex");
110
119
  claudeDir = path.join(rootDir, ".claude");
120
+ geminiDir = path.join(rootDir, ".gemini");
111
121
  }
112
122
  });
113
123
 
@@ -344,15 +354,13 @@ function migrateMCPConfig(config) {
344
354
  config.managedServerNames = {
345
355
  claude: config.managedServerNames,
346
356
  codex: [],
347
- cursor: [],
348
- windsurf: []
357
+ gemini: []
349
358
  };
350
359
  } else if (!config.managedServerNames) {
351
360
  config.managedServerNames = {
352
361
  claude: [],
353
362
  codex: [],
354
- cursor: [],
355
- windsurf: []
363
+ gemini: []
356
364
  };
357
365
  }
358
366
  if (config.servers) {
@@ -374,8 +382,7 @@ function loadMCPConfig() {
374
382
  managedServerNames: {
375
383
  claude: [],
376
384
  codex: [],
377
- cursor: [],
378
- windsurf: []
385
+ gemini: []
379
386
  }
380
387
  };
381
388
  }
@@ -441,10 +448,10 @@ function writeMCPConfigForApp(app, _provider) {
441
448
  break;
442
449
  case "codex":
443
450
  return;
444
- case "cursor":
445
- return;
446
- case "windsurf":
447
- return;
451
+ case "gemini":
452
+ configPath = getGeminiSettingsPath();
453
+ configDir = getGeminiDir();
454
+ break;
448
455
  }
449
456
  ensureDir(configDir);
450
457
  let appConfig = {};
@@ -625,6 +632,127 @@ var init_mcp2 = __esm({
625
632
  }
626
633
  });
627
634
 
635
+ // ../core/dist/presets/gemini.js
636
+ var GEMINI_PRESETS;
637
+ var init_gemini = __esm({
638
+ "../core/dist/presets/gemini.js"() {
639
+ "use strict";
640
+ GEMINI_PRESETS = [
641
+ {
642
+ name: "Google Gemini (API Key)",
643
+ baseUrl: "",
644
+ description: "\u4F7F\u7528\u5B98\u65B9 Gemini API\uFF08\u901A\u8FC7 GEMINI_API_KEY \u6216 GOOGLE_API_KEY \u8BA4\u8BC1\uFF09"
645
+ },
646
+ {
647
+ name: "PackyAPI",
648
+ baseUrl: "https://www.packyapi.com",
649
+ description: "PackyAPI Gemini \u517C\u5BB9\u670D\u52A1"
650
+ },
651
+ {
652
+ name: "LiteLLM Proxy",
653
+ baseUrl: "http://localhost:4000",
654
+ description: "\u4F7F\u7528\u672C\u5730 LiteLLM Proxy \u4F5C\u4E3A Gemini \u517C\u5BB9\u4EE3\u7406"
655
+ }
656
+ ];
657
+ }
658
+ });
659
+
660
+ // ../core/dist/writers/gemini.js
661
+ import * as fs5 from "fs";
662
+ function loadEnvFile(envPath) {
663
+ if (!fileExists(envPath))
664
+ return {};
665
+ const content = fs5.readFileSync(envPath, "utf-8");
666
+ const result = {};
667
+ for (const line of content.split("\n")) {
668
+ const trimmed = line.trim();
669
+ if (!trimmed || trimmed.startsWith("#"))
670
+ continue;
671
+ const eqIndex = trimmed.indexOf("=");
672
+ if (eqIndex === -1)
673
+ continue;
674
+ const key = trimmed.slice(0, eqIndex).trim();
675
+ const value = trimmed.slice(eqIndex + 1).trim();
676
+ if (!key)
677
+ continue;
678
+ result[key] = value;
679
+ }
680
+ return result;
681
+ }
682
+ function saveEnvFile(envPath, env) {
683
+ const lines = [];
684
+ const keys = Object.keys(env).sort();
685
+ for (const key of keys) {
686
+ lines.push(`${key}=${String(env[key])}`);
687
+ }
688
+ const content = lines.join("\n") + (lines.length ? "\n" : "");
689
+ fs5.writeFileSync(envPath, content, { mode: 384 });
690
+ }
691
+ function writeGeminiConfig(provider) {
692
+ const settingsPath = getGeminiSettingsPath();
693
+ const envPath = getGeminiEnvPath();
694
+ const dir = getGeminiDir();
695
+ ensureDir(dir);
696
+ let settings = {};
697
+ if (fileExists(settingsPath)) {
698
+ try {
699
+ const content = fs5.readFileSync(settingsPath, "utf-8");
700
+ const parsed = JSON.parse(content);
701
+ if (parsed && typeof parsed === "object") {
702
+ settings = parsed;
703
+ }
704
+ } catch (error) {
705
+ throw new Error(`\u65E0\u6CD5\u8BFB\u53D6 Gemini settings.json: ${error.message}`);
706
+ }
707
+ }
708
+ if (!settings.ide || typeof settings.ide !== "object") {
709
+ settings.ide = {};
710
+ }
711
+ if (settings.ide.enabled === void 0) {
712
+ settings.ide.enabled = true;
713
+ }
714
+ if (!settings.security || typeof settings.security !== "object") {
715
+ settings.security = {};
716
+ }
717
+ if (!settings.security.auth || typeof settings.security.auth !== "object") {
718
+ settings.security.auth = {};
719
+ }
720
+ if (settings.security.auth.selectedType === void 0) {
721
+ settings.security.auth.selectedType = "gemini-api-key";
722
+ }
723
+ try {
724
+ const tempPath = `${settingsPath}.tmp`;
725
+ fs5.writeFileSync(tempPath, JSON.stringify(settings, null, 2), {
726
+ mode: 384
727
+ });
728
+ fs5.renameSync(tempPath, settingsPath);
729
+ } catch (error) {
730
+ throw new Error(`\u5199\u5165 Gemini settings.json \u5931\u8D25: ${error.message}`);
731
+ }
732
+ const env = loadEnvFile(envPath);
733
+ if (provider.baseUrl && provider.baseUrl.trim().length > 0) {
734
+ env.GOOGLE_GEMINI_BASE_URL = provider.baseUrl;
735
+ } else {
736
+ delete env.GOOGLE_GEMINI_BASE_URL;
737
+ }
738
+ if (provider.apiKey && provider.apiKey.trim().length > 0) {
739
+ env.GEMINI_API_KEY = provider.apiKey;
740
+ } else {
741
+ delete env.GEMINI_API_KEY;
742
+ }
743
+ if (provider.model && provider.model.trim().length > 0) {
744
+ env.GEMINI_MODEL = provider.model;
745
+ }
746
+ saveEnvFile(envPath, env);
747
+ }
748
+ var init_gemini2 = __esm({
749
+ "../core/dist/writers/gemini.js"() {
750
+ "use strict";
751
+ init_paths();
752
+ init_file();
753
+ }
754
+ });
755
+
628
756
  // ../core/dist/tool-manager.types.js
629
757
  var ProviderNotFoundError, ProviderNameConflictError, PresetNameConflictError;
630
758
  var init_tool_manager_types = __esm({
@@ -901,6 +1029,9 @@ function createClaudeManager() {
901
1029
  function createMCPManager() {
902
1030
  return createToolManager("mcp");
903
1031
  }
1032
+ function createGeminiManager() {
1033
+ return createToolManager("gemini");
1034
+ }
904
1035
  var TOOL_CONFIGS;
905
1036
  var init_tool_manager = __esm({
906
1037
  "../core/dist/tool-manager.js"() {
@@ -913,6 +1044,8 @@ var init_tool_manager = __esm({
913
1044
  init_codex2();
914
1045
  init_claude2();
915
1046
  init_mcp2();
1047
+ init_gemini();
1048
+ init_gemini2();
916
1049
  init_tool_manager_types();
917
1050
  TOOL_CONFIGS = {
918
1051
  codex: {
@@ -949,11 +1082,16 @@ var init_tool_manager = __esm({
949
1082
  }
950
1083
  return mcpServer;
951
1084
  });
952
- for (const app of ["claude", "codex", "cursor", "windsurf"]) {
1085
+ for (const app of ["claude", "codex", "gemini"]) {
953
1086
  mcpConfig.managedServerNames[app] = mcpConfig.servers.filter((s) => s.enabledApps.includes(app)).map((s) => s.name);
954
1087
  }
955
1088
  saveMCPConfig(mcpConfig);
956
1089
  }
1090
+ },
1091
+ gemini: {
1092
+ configPath: path6.join(getCcmanDir(), "gemini.json"),
1093
+ builtinPresets: GEMINI_PRESETS,
1094
+ writer: writeGeminiConfig
957
1095
  }
958
1096
  };
959
1097
  }
@@ -968,20 +1106,20 @@ var init_migrate = __esm({
968
1106
  });
969
1107
 
970
1108
  // ../core/dist/config.js
971
- import * as fs5 from "fs";
1109
+ import * as fs6 from "fs";
972
1110
  function ensureConfigDir() {
973
1111
  const dir = getCcmanDir();
974
- if (!fs5.existsSync(dir)) {
975
- fs5.mkdirSync(dir, { recursive: true, mode: 448 });
1112
+ if (!fs6.existsSync(dir)) {
1113
+ fs6.mkdirSync(dir, { recursive: true, mode: 448 });
976
1114
  }
977
1115
  }
978
1116
  function loadConfig() {
979
1117
  const configPath = getConfigPath();
980
- if (!fs5.existsSync(configPath)) {
1118
+ if (!fs6.existsSync(configPath)) {
981
1119
  return {};
982
1120
  }
983
1121
  try {
984
- const content = fs5.readFileSync(configPath, "utf-8");
1122
+ const content = fs6.readFileSync(configPath, "utf-8");
985
1123
  return JSON.parse(content);
986
1124
  } catch (error) {
987
1125
  throw new Error(`Failed to load config: ${error.message}`);
@@ -992,10 +1130,10 @@ function saveConfig(config) {
992
1130
  const configPath = getConfigPath();
993
1131
  try {
994
1132
  const tempPath = `${configPath}.tmp`;
995
- fs5.writeFileSync(tempPath, JSON.stringify(config, null, 2), {
1133
+ fs6.writeFileSync(tempPath, JSON.stringify(config, null, 2), {
996
1134
  mode: 384
997
1135
  });
998
- fs5.renameSync(tempPath, configPath);
1136
+ fs6.renameSync(tempPath, configPath);
999
1137
  } catch (error) {
1000
1138
  throw new Error(`Failed to save config: ${error.message}`);
1001
1139
  }
@@ -1319,15 +1457,15 @@ var init_merge_advanced = __esm({
1319
1457
  });
1320
1458
 
1321
1459
  // ../core/dist/sync/merge.js
1322
- import fs6 from "fs";
1460
+ import fs7 from "fs";
1323
1461
  import path7 from "path";
1324
1462
  function backupConfig(configPath, keepCount = 3) {
1325
- if (!fs6.existsSync(configPath)) {
1463
+ if (!fs7.existsSync(configPath)) {
1326
1464
  throw new Error(`\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${configPath}`);
1327
1465
  }
1328
1466
  const timestamp = Date.now();
1329
1467
  const backupPath = `${configPath}.backup.${timestamp}`;
1330
- fs6.copyFileSync(configPath, backupPath);
1468
+ fs7.copyFileSync(configPath, backupPath);
1331
1469
  cleanupOldBackups(configPath, keepCount);
1332
1470
  return backupPath;
1333
1471
  }
@@ -1336,7 +1474,7 @@ function cleanupOldBackups(configPath, keepCount) {
1336
1474
  const basename = path7.basename(configPath);
1337
1475
  const backupPrefix = `${basename}.backup.`;
1338
1476
  try {
1339
- const files = fs6.readdirSync(dir);
1477
+ const files = fs7.readdirSync(dir);
1340
1478
  const backups = files.filter((f) => f.startsWith(backupPrefix)).map((f) => {
1341
1479
  const timestampStr = f.substring(backupPrefix.length);
1342
1480
  const timestamp = parseInt(timestampStr, 10);
@@ -1352,7 +1490,7 @@ function cleanupOldBackups(configPath, keepCount) {
1352
1490
  const toDelete = backups.slice(keepCount);
1353
1491
  for (const backup of toDelete) {
1354
1492
  try {
1355
- fs6.unlinkSync(backup.path);
1493
+ fs7.unlinkSync(backup.path);
1356
1494
  } catch (error) {
1357
1495
  console.warn(`\u65E0\u6CD5\u5220\u9664\u65E7\u5907\u4EFD\u6587\u4EF6 ${backup.name}: ${error.message}`);
1358
1496
  }
@@ -1368,7 +1506,7 @@ var init_merge = __esm({
1368
1506
  });
1369
1507
 
1370
1508
  // ../core/dist/sync/sync-v2.js
1371
- import fs7 from "fs";
1509
+ import fs8 from "fs";
1372
1510
  import path8 from "path";
1373
1511
  async function uploadToCloud(config, password) {
1374
1512
  const ccmanDir2 = getCcmanDir();
@@ -1424,10 +1562,10 @@ async function downloadFromCloud(config, password) {
1424
1562
  const codexConfigPath = path8.join(ccmanDir2, "codex.json");
1425
1563
  const claudeConfigPath = path8.join(ccmanDir2, "claude.json");
1426
1564
  try {
1427
- if (fs7.existsSync(codexConfigPath)) {
1565
+ if (fs8.existsSync(codexConfigPath)) {
1428
1566
  backupPaths.push(backupConfig(codexConfigPath));
1429
1567
  }
1430
- if (fs7.existsSync(claudeConfigPath)) {
1568
+ if (fs8.existsSync(claudeConfigPath)) {
1431
1569
  backupPaths.push(backupConfig(claudeConfigPath));
1432
1570
  }
1433
1571
  } catch (error) {
@@ -1460,8 +1598,8 @@ async function downloadFromCloud(config, password) {
1460
1598
  } catch (error) {
1461
1599
  for (const backupPath of backupPaths) {
1462
1600
  const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
1463
- if (fs7.existsSync(backupPath)) {
1464
- fs7.copyFileSync(backupPath, originalPath);
1601
+ if (fs8.existsSync(backupPath)) {
1602
+ fs8.copyFileSync(backupPath, originalPath);
1465
1603
  }
1466
1604
  }
1467
1605
  throw new Error(`\u8986\u76D6\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
@@ -1511,10 +1649,10 @@ async function mergeSync(config, password) {
1511
1649
  }
1512
1650
  const backupPaths = [];
1513
1651
  try {
1514
- if (fs7.existsSync(codexConfigPath)) {
1652
+ if (fs8.existsSync(codexConfigPath)) {
1515
1653
  backupPaths.push(backupConfig(codexConfigPath));
1516
1654
  }
1517
- if (fs7.existsSync(claudeConfigPath)) {
1655
+ if (fs8.existsSync(claudeConfigPath)) {
1518
1656
  backupPaths.push(backupConfig(claudeConfigPath));
1519
1657
  }
1520
1658
  } catch (error) {
@@ -1570,8 +1708,8 @@ async function mergeSync(config, password) {
1570
1708
  } catch (error) {
1571
1709
  for (const backupPath of backupPaths) {
1572
1710
  const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
1573
- if (fs7.existsSync(backupPath)) {
1574
- fs7.copyFileSync(backupPath, originalPath);
1711
+ if (fs8.existsSync(backupPath)) {
1712
+ fs8.copyFileSync(backupPath, originalPath);
1575
1713
  }
1576
1714
  }
1577
1715
  throw new Error(`\u5408\u5E76\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
@@ -1610,7 +1748,7 @@ var init_sync_v2 = __esm({
1610
1748
  });
1611
1749
 
1612
1750
  // ../core/dist/export.js
1613
- import * as fs8 from "fs";
1751
+ import * as fs9 from "fs";
1614
1752
  import * as path9 from "path";
1615
1753
  function validateExport() {
1616
1754
  const ccmanDir2 = getCcmanDir();
@@ -1640,7 +1778,7 @@ function validateImportDir(sourceDir) {
1640
1778
  foundFiles: []
1641
1779
  };
1642
1780
  }
1643
- const stats = fs8.statSync(sourceDir);
1781
+ const stats = fs9.statSync(sourceDir);
1644
1782
  if (!stats.isDirectory()) {
1645
1783
  return {
1646
1784
  valid: false,
@@ -1680,13 +1818,13 @@ function exportConfig(targetDir) {
1680
1818
  const codexSrc = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
1681
1819
  const codexDst = path9.join(targetDir, CODEX_CONFIG_FILE);
1682
1820
  if (fileExists(codexSrc)) {
1683
- fs8.copyFileSync(codexSrc, codexDst);
1821
+ fs9.copyFileSync(codexSrc, codexDst);
1684
1822
  exportedFiles.push(CODEX_CONFIG_FILE);
1685
1823
  }
1686
1824
  const claudeSrc = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
1687
1825
  const claudeDst = path9.join(targetDir, CLAUDE_CONFIG_FILE);
1688
1826
  if (fileExists(claudeSrc)) {
1689
- fs8.copyFileSync(claudeSrc, claudeDst);
1827
+ fs9.copyFileSync(claudeSrc, claudeDst);
1690
1828
  exportedFiles.push(CLAUDE_CONFIG_FILE);
1691
1829
  }
1692
1830
  return {
@@ -1712,7 +1850,7 @@ function importConfig(sourceDir) {
1712
1850
  backupPaths.push(backupPath);
1713
1851
  }
1714
1852
  const codexSrc = path9.join(sourceDir, CODEX_CONFIG_FILE);
1715
- fs8.copyFileSync(codexSrc, codexDst);
1853
+ fs9.copyFileSync(codexSrc, codexDst);
1716
1854
  importedFiles.push(CODEX_CONFIG_FILE);
1717
1855
  }
1718
1856
  if (validation.foundFiles.includes(CLAUDE_CONFIG_FILE)) {
@@ -1722,7 +1860,7 @@ function importConfig(sourceDir) {
1722
1860
  backupPaths.push(backupPath);
1723
1861
  }
1724
1862
  const claudeSrc = path9.join(sourceDir, CLAUDE_CONFIG_FILE);
1725
- fs8.copyFileSync(claudeSrc, claudeDst);
1863
+ fs9.copyFileSync(claudeSrc, claudeDst);
1726
1864
  importedFiles.push(CLAUDE_CONFIG_FILE);
1727
1865
  }
1728
1866
  return {
@@ -1734,7 +1872,7 @@ function importConfig(sourceDir) {
1734
1872
  for (const backupPath of backupPaths) {
1735
1873
  const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
1736
1874
  if (fileExists(backupPath)) {
1737
- fs8.copyFileSync(backupPath, originalPath);
1875
+ fs9.copyFileSync(backupPath, originalPath);
1738
1876
  }
1739
1877
  }
1740
1878
  throw new Error(`\u5BFC\u5165\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
@@ -1753,7 +1891,7 @@ var init_export = __esm({
1753
1891
  });
1754
1892
 
1755
1893
  // ../core/dist/claude-clean.js
1756
- import * as fs9 from "fs";
1894
+ import * as fs10 from "fs";
1757
1895
  function formatBytes(bytes) {
1758
1896
  if (bytes < 1024)
1759
1897
  return `${bytes} B`;
@@ -1763,7 +1901,7 @@ function formatBytes(bytes) {
1763
1901
  }
1764
1902
  function getFileSize(filePath) {
1765
1903
  try {
1766
- const stats = fs9.statSync(filePath);
1904
+ const stats = fs10.statSync(filePath);
1767
1905
  return stats.size;
1768
1906
  } catch {
1769
1907
  return 0;
@@ -1772,18 +1910,18 @@ function getFileSize(filePath) {
1772
1910
  function backupFile(filePath) {
1773
1911
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-").split(".")[0];
1774
1912
  const backupPath = `${filePath}.backup-${timestamp}`;
1775
- fs9.copyFileSync(filePath, backupPath);
1913
+ fs10.copyFileSync(filePath, backupPath);
1776
1914
  return backupPath;
1777
1915
  }
1778
1916
  function saveJsonAtomic(filePath, data) {
1779
1917
  const tempPath = `${filePath}.tmp`;
1780
1918
  const content = JSON.stringify(data, null, 2);
1781
- fs9.writeFileSync(tempPath, content, { mode: 384 });
1782
- fs9.renameSync(tempPath, filePath);
1919
+ fs10.writeFileSync(tempPath, content, { mode: 384 });
1920
+ fs10.renameSync(tempPath, filePath);
1783
1921
  }
1784
1922
  function analyzeClaudeJson() {
1785
1923
  const filePath = getClaudeJsonPath();
1786
- if (!fs9.existsSync(filePath)) {
1924
+ if (!fs10.existsSync(filePath)) {
1787
1925
  return {
1788
1926
  fileSize: 0,
1789
1927
  fileSizeFormatted: "0 B",
@@ -1799,7 +1937,7 @@ function analyzeClaudeJson() {
1799
1937
  };
1800
1938
  }
1801
1939
  const fileSize = getFileSize(filePath);
1802
- const content = fs9.readFileSync(filePath, "utf-8");
1940
+ const content = fs10.readFileSync(filePath, "utf-8");
1803
1941
  const config = JSON.parse(content);
1804
1942
  const projects = config.projects || {};
1805
1943
  const projectHistory = [];
@@ -1833,12 +1971,12 @@ function analyzeClaudeJson() {
1833
1971
  }
1834
1972
  function cleanClaudeJson(options = {}) {
1835
1973
  const filePath = getClaudeJsonPath();
1836
- if (!fs9.existsSync(filePath)) {
1974
+ if (!fs10.existsSync(filePath)) {
1837
1975
  throw new Error(`${filePath} \u6587\u4EF6\u4E0D\u5B58\u5728`);
1838
1976
  }
1839
1977
  const backupPath = backupFile(filePath);
1840
1978
  const sizeBefore = getFileSize(filePath);
1841
- const content = fs9.readFileSync(filePath, "utf-8");
1979
+ const content = fs10.readFileSync(filePath, "utf-8");
1842
1980
  const config = JSON.parse(content);
1843
1981
  const cleanedItems = applyCleanOptions(config, options);
1844
1982
  saveJsonAtomic(filePath, config);
@@ -1923,6 +2061,7 @@ var init_dist = __esm({
1923
2061
  init_codex2();
1924
2062
  init_claude2();
1925
2063
  init_mcp2();
2064
+ init_gemini();
1926
2065
  init_mcp();
1927
2066
  init_migrate();
1928
2067
  init_paths();
@@ -2646,7 +2785,7 @@ var init_sync = __esm({
2646
2785
 
2647
2786
  // src/index.ts
2648
2787
  import { Command as Command3 } from "commander";
2649
- import chalk33 from "chalk";
2788
+ import chalk40 from "chalk";
2650
2789
 
2651
2790
  // src/utils/logo.ts
2652
2791
  init_dist();
@@ -2705,6 +2844,11 @@ function formatProviderTable(providers, currentId) {
2705
2844
  }
2706
2845
 
2707
2846
  // src/interactive.ts
2847
+ var TOOL_CONFIG = {
2848
+ codex: { name: "Codex", emoji: "\u{1F536}", cmd: "cx" },
2849
+ claude: { name: "Claude", emoji: "\u{1F537}", cmd: "cc" },
2850
+ gemini: { name: "Gemini", emoji: "\u{1F48E}", cmd: "gm" }
2851
+ };
2708
2852
  async function promptProviderForm(defaults) {
2709
2853
  const answers = await inquirer7.prompt([
2710
2854
  {
@@ -2766,6 +2910,7 @@ async function startMainMenu() {
2766
2910
  choices: [
2767
2911
  { name: "\u{1F537} Claude \u7BA1\u7406", value: "claude" },
2768
2912
  { name: "\u{1F536} Codex \u7BA1\u7406", value: "codex" },
2913
+ { name: "\u{1F48E} Gemini \u7BA1\u7406", value: "gemini" },
2769
2914
  { name: "\u{1F504} WebDAV \u540C\u6B65", value: "sync" },
2770
2915
  { name: "\u{1F4E6} \u9884\u7F6E\u670D\u52A1\u5546\u7BA1\u7406", value: "presets" },
2771
2916
  { name: "\u274C \u9000\u51FA", value: "exit" }
@@ -2780,6 +2925,8 @@ async function startMainMenu() {
2780
2925
  await startClaudeMenu();
2781
2926
  } else if (choice === "codex") {
2782
2927
  await startCodexMenu();
2928
+ } else if (choice === "gemini") {
2929
+ await startGeminiMenu();
2783
2930
  } else if (choice === "sync") {
2784
2931
  const { startSyncMenu: startSyncMenu2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
2785
2932
  await startSyncMenu2();
@@ -2794,9 +2941,11 @@ async function startClaudeMenu() {
2794
2941
  async function startCodexMenu() {
2795
2942
  await showToolMenu("codex");
2796
2943
  }
2944
+ async function startGeminiMenu() {
2945
+ await showToolMenu("gemini");
2946
+ }
2797
2947
  async function showToolMenu(tool) {
2798
- const toolName = tool === "claude" ? "Claude" : "Codex";
2799
- const toolEmoji = tool === "claude" ? "\u{1F537}" : "\u{1F536}";
2948
+ const { name: toolName, emoji: toolEmoji } = TOOL_CONFIG[tool];
2800
2949
  while (true) {
2801
2950
  console.log();
2802
2951
  const { action } = await inquirer7.prompt([
@@ -2861,8 +3010,8 @@ async function showPresetsMenu() {
2861
3010
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u9884\u7F6E\u670D\u52A1\u5546\u7BA1\u7406\u529F\u80FD\u5373\u5C06\u63A8\u51FA\n"));
2862
3011
  }
2863
3012
  async function handleAdd(tool) {
2864
- const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
2865
- const toolName = tool === "claude" ? "Claude" : "Codex";
3013
+ const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3014
+ const { name: toolName, cmd } = TOOL_CONFIG[tool];
2866
3015
  const presets = manager.listPresets();
2867
3016
  console.log(chalk11.bold(`
2868
3017
  \u{1F4DD} \u6DFB\u52A0 ${toolName} \u670D\u52A1\u5546
@@ -2961,13 +3110,13 @@ async function handleAdd(tool) {
2961
3110
  console.log(chalk11.green("\u2705 \u5DF2\u5207\u6362\u5230\u65B0\u670D\u52A1\u5546\n"));
2962
3111
  } else {
2963
3112
  console.log(
2964
- chalk11.blue("\u{1F4A1} \u7A0D\u540E\u5207\u6362:") + chalk11.white(` ccman ${tool === "codex" ? "cx" : "cc"} use "${provider.name}"
3113
+ chalk11.blue("\u{1F4A1} \u7A0D\u540E\u5207\u6362:") + chalk11.white(` ccman ${cmd} use "${provider.name}"
2965
3114
  `)
2966
3115
  );
2967
3116
  }
2968
3117
  }
2969
3118
  async function handleSwitch(tool) {
2970
- const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
3119
+ const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
2971
3120
  const providers = manager.list();
2972
3121
  const current = manager.getCurrent();
2973
3122
  if (providers.length === 0) {
@@ -2992,10 +3141,10 @@ async function handleSwitch(tool) {
2992
3141
  `));
2993
3142
  }
2994
3143
  async function handleList(tool) {
2995
- const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
3144
+ const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
2996
3145
  const providers = manager.list();
2997
3146
  const current = manager.getCurrent();
2998
- const toolName = tool === "claude" ? "Claude" : "Codex";
3147
+ const { name: toolName } = TOOL_CONFIG[tool];
2999
3148
  if (providers.length === 0) {
3000
3149
  console.log(chalk11.yellow(`
3001
3150
  \u26A0\uFE0F \u6682\u65E0 ${toolName} \u670D\u52A1\u5546
@@ -3007,9 +3156,9 @@ async function handleList(tool) {
3007
3156
  console.log(formatProviderTable(providers, current?.id));
3008
3157
  }
3009
3158
  async function handleCurrent(tool) {
3010
- const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
3159
+ const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3011
3160
  const current = manager.getCurrent();
3012
- const toolName = tool === "claude" ? "Claude" : "Codex";
3161
+ const { name: toolName } = TOOL_CONFIG[tool];
3013
3162
  if (!current) {
3014
3163
  console.log(chalk11.yellow(`
3015
3164
  \u26A0\uFE0F \u672A\u9009\u62E9\u4EFB\u4F55 ${toolName} \u670D\u52A1\u5546
@@ -3028,7 +3177,7 @@ async function handleCurrent(tool) {
3028
3177
  console.log();
3029
3178
  }
3030
3179
  async function handleEdit(tool) {
3031
- const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
3180
+ const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3032
3181
  const providers = manager.list();
3033
3182
  if (providers.length === 0) {
3034
3183
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
@@ -3089,7 +3238,7 @@ async function handleEdit(tool) {
3089
3238
  console.log(chalk11.green("\n\u2705 \u7F16\u8F91\u6210\u529F\n"));
3090
3239
  }
3091
3240
  async function handleClone(tool) {
3092
- const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
3241
+ const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3093
3242
  const providers = manager.list();
3094
3243
  if (providers.length === 0) {
3095
3244
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
@@ -3136,7 +3285,7 @@ async function handleClone(tool) {
3136
3285
  console.log();
3137
3286
  }
3138
3287
  async function handleRemove(tool) {
3139
- const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
3288
+ const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3140
3289
  const providers = manager.list();
3141
3290
  if (providers.length === 0) {
3142
3291
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
@@ -4648,7 +4797,7 @@ function editCommand3(program2) {
4648
4797
  targetId = selectedId;
4649
4798
  }
4650
4799
  const provider = manager.get(targetId);
4651
- const currentCommand3 = provider.baseUrl;
4800
+ const currentCommand4 = provider.baseUrl;
4652
4801
  const currentArgs = provider.apiKey;
4653
4802
  const currentEnv = provider.model;
4654
4803
  console.log(chalk30.bold("\n\u270F\uFE0F \u7F16\u8F91 MCP \u670D\u52A1\u5668\n"));
@@ -4664,7 +4813,7 @@ function editCommand3(program2) {
4664
4813
  type: "input",
4665
4814
  name: "command",
4666
4815
  message: "\u542F\u52A8\u547D\u4EE4:",
4667
- default: currentCommand3
4816
+ default: currentCommand4
4668
4817
  },
4669
4818
  {
4670
4819
  type: "input",
@@ -4683,7 +4832,7 @@ function editCommand3(program2) {
4683
4832
  if (answers.name && answers.name !== provider.name) {
4684
4833
  updates.name = answers.name;
4685
4834
  }
4686
- if (answers.command && answers.command !== currentCommand3) {
4835
+ if (answers.command && answers.command !== currentCommand4) {
4687
4836
  updates.baseUrl = answers.command;
4688
4837
  }
4689
4838
  if (answers.args && answers.args !== currentArgs) {
@@ -4732,44 +4881,480 @@ function createMCPCommands(program2) {
4732
4881
  editCommand3(program2);
4733
4882
  }
4734
4883
 
4884
+ // src/commands/gemini/add.ts
4885
+ init_dist();
4886
+ import chalk31 from "chalk";
4887
+ import inquirer22 from "inquirer";
4888
+ function addCommand4(program2) {
4889
+ program2.command("add").description("\u6DFB\u52A0\u65B0\u7684 Gemini CLI \u670D\u52A1\u5546(\u4EA4\u4E92\u5F0F)").action(async () => {
4890
+ try {
4891
+ const manager = createGeminiManager();
4892
+ console.log(chalk31.bold("\n\u{1F4DD} \u6DFB\u52A0 Gemini CLI \u670D\u52A1\u5546\n"));
4893
+ const { usePreset } = await inquirer22.prompt([
4894
+ {
4895
+ type: "list",
4896
+ name: "usePreset",
4897
+ message: "\u9009\u62E9\u914D\u7F6E\u6765\u6E90:",
4898
+ choices: [
4899
+ { name: "\u{1F4E6} \u4F7F\u7528\u9884\u7F6E\u670D\u52A1\u5546", value: true },
4900
+ { name: "\u270F\uFE0F \u81EA\u5B9A\u4E49\u914D\u7F6E", value: false }
4901
+ ]
4902
+ }
4903
+ ]);
4904
+ let name;
4905
+ let desc;
4906
+ let baseUrl;
4907
+ let apiKey;
4908
+ if (usePreset) {
4909
+ const { presetName } = await inquirer22.prompt([
4910
+ {
4911
+ type: "list",
4912
+ name: "presetName",
4913
+ message: "\u9009\u62E9\u9884\u7F6E\u670D\u52A1\u5546:",
4914
+ choices: GEMINI_PRESETS.map((p) => ({
4915
+ name: `${p.name} - ${p.description}`,
4916
+ value: p.name
4917
+ }))
4918
+ }
4919
+ ]);
4920
+ const preset = GEMINI_PRESETS.find((p) => p.name === presetName);
4921
+ console.log(chalk31.blue(`
4922
+ \u4F7F\u7528\u9884\u8BBE: ${preset.name} - ${preset.description}
4923
+ `));
4924
+ const input = await promptProviderForm({
4925
+ name: preset.name,
4926
+ desc: "",
4927
+ baseUrl: preset.baseUrl,
4928
+ apiKey: ""
4929
+ });
4930
+ name = input.name;
4931
+ desc = input.desc;
4932
+ baseUrl = input.baseUrl;
4933
+ apiKey = input.apiKey;
4934
+ } else {
4935
+ const answers = await inquirer22.prompt([
4936
+ {
4937
+ type: "input",
4938
+ name: "name",
4939
+ message: "\u670D\u52A1\u5546\u540D\u79F0:",
4940
+ validate: (value) => {
4941
+ if (!value) return "\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
4942
+ return true;
4943
+ }
4944
+ },
4945
+ {
4946
+ type: "input",
4947
+ name: "baseUrl",
4948
+ message: "API \u5730\u5740 (\u53EF\u4E3A\u7A7A\uFF0C\u4F7F\u7528\u5B98\u65B9\u9ED8\u8BA4):",
4949
+ validate: (value) => {
4950
+ if (!value) return true;
4951
+ if (!value.startsWith("http://") && !value.startsWith("https://")) {
4952
+ return "API \u5730\u5740\u5FC5\u987B\u4EE5 http:// \u6216 https:// \u5F00\u5934";
4953
+ }
4954
+ return true;
4955
+ }
4956
+ },
4957
+ {
4958
+ type: "password",
4959
+ name: "apiKey",
4960
+ message: "API \u5BC6\u94A5 (\u53EF\u4E3A\u7A7A\uFF0C\u4F7F\u7528\u73AF\u5883\u5DF2\u914D\u7F6E\u7684 Key):",
4961
+ mask: "*"
4962
+ }
4963
+ ]);
4964
+ name = answers.name;
4965
+ desc = void 0;
4966
+ baseUrl = answers.baseUrl || "";
4967
+ apiKey = answers.apiKey || "";
4968
+ }
4969
+ const provider = manager.add({ name, desc, baseUrl, apiKey });
4970
+ console.log();
4971
+ console.log(chalk31.green("\u2705 \u6DFB\u52A0\u6210\u529F"));
4972
+ console.log();
4973
+ console.log(` ${chalk31.bold(provider.name)} ${chalk31.blue("[Gemini CLI]")}`);
4974
+ console.log(` ${chalk31.gray(provider.baseUrl || "(\u4F7F\u7528\u9ED8\u8BA4\u7AEF\u70B9)")}`);
4975
+ console.log();
4976
+ const { switchNow } = await inquirer22.prompt([
4977
+ {
4978
+ type: "confirm",
4979
+ name: "switchNow",
4980
+ message: "\u662F\u5426\u7ACB\u5373\u5207\u6362\u5230\u6B64\u670D\u52A1\u5546?",
4981
+ default: true
4982
+ }
4983
+ ]);
4984
+ if (switchNow) {
4985
+ manager.switch(provider.id);
4986
+ console.log(chalk31.green("\u2705 \u5DF2\u5207\u6362\u5230\u65B0\u670D\u52A1\u5546"));
4987
+ console.log();
4988
+ console.log(chalk31.gray("\u914D\u7F6E\u5DF2\u66F4\u65B0:"));
4989
+ console.log(chalk31.gray(` - ${getGeminiSettingsPath()}`));
4990
+ console.log(chalk31.gray(` - ${getGeminiEnvPath()}`));
4991
+ } else {
4992
+ console.log(chalk31.blue("\u{1F4A1} \u7A0D\u540E\u5207\u6362:") + chalk31.white(` ccman gm use "${provider.name}"`));
4993
+ }
4994
+ } catch (error) {
4995
+ console.error(chalk31.red(`
4996
+ \u274C ${error.message}
4997
+ `));
4998
+ process.exit(1);
4999
+ }
5000
+ });
5001
+ }
5002
+
5003
+ // src/commands/gemini/list.ts
5004
+ init_dist();
5005
+ import chalk32 from "chalk";
5006
+ function listCommand4(program2) {
5007
+ program2.command("list").alias("ls").description("\u5217\u51FA\u6240\u6709 Gemini CLI \u670D\u52A1\u5546").action(async () => {
5008
+ try {
5009
+ const manager = createGeminiManager();
5010
+ const providers = manager.list();
5011
+ const current = manager.getCurrent();
5012
+ if (providers.length === 0) {
5013
+ console.log(chalk32.yellow("\n\u26A0\uFE0F \u6682\u65E0 Gemini CLI \u670D\u52A1\u5546\n"));
5014
+ console.log(chalk32.blue("\u{1F4A1} \u6DFB\u52A0\u670D\u52A1\u5546:") + chalk32.white(" ccman gm add\n"));
5015
+ return;
5016
+ }
5017
+ console.log(chalk32.bold(`
5018
+ \u{1F4CB} Gemini CLI \u670D\u52A1\u5546 (${providers.length} \u4E2A)`));
5019
+ console.log(formatProviderTable(providers, current?.id));
5020
+ } catch (error) {
5021
+ console.error(chalk32.red(`
5022
+ \u274C ${error.message}
5023
+ `));
5024
+ process.exit(1);
5025
+ }
5026
+ });
5027
+ }
5028
+
5029
+ // src/commands/gemini/use.ts
5030
+ init_dist();
5031
+ import chalk33 from "chalk";
5032
+ import inquirer23 from "inquirer";
5033
+ function useCommand3(program2) {
5034
+ program2.command("use [name]").description("\u5207\u6362 Gemini CLI \u670D\u52A1\u5546").action(async (name) => {
5035
+ try {
5036
+ const manager = createGeminiManager();
5037
+ const providers = manager.list();
5038
+ if (providers.length === 0) {
5039
+ console.log(chalk33.yellow("\n\u26A0\uFE0F \u6682\u65E0 Gemini CLI \u670D\u52A1\u5546\n"));
5040
+ console.log(chalk33.blue("\u{1F4A1} \u6DFB\u52A0\u670D\u52A1\u5546:") + chalk33.white(" ccman gm add\n"));
5041
+ return;
5042
+ }
5043
+ let targetId;
5044
+ if (name) {
5045
+ const provider2 = manager.findByName(name);
5046
+ if (!provider2) {
5047
+ throw new ProviderNotFoundError(name);
5048
+ }
5049
+ targetId = provider2.id;
5050
+ } else {
5051
+ const { selectedId } = await inquirer23.prompt([
5052
+ {
5053
+ type: "list",
5054
+ name: "selectedId",
5055
+ message: "\u9009\u62E9\u8981\u5207\u6362\u7684\u670D\u52A1\u5546:",
5056
+ choices: providers.map((p) => ({
5057
+ name: `${p.name} - ${p.baseUrl || "(\u9ED8\u8BA4\u7AEF\u70B9)"}`,
5058
+ value: p.id
5059
+ }))
5060
+ }
5061
+ ]);
5062
+ targetId = selectedId;
5063
+ }
5064
+ manager.switch(targetId);
5065
+ const provider = manager.get(targetId);
5066
+ console.log();
5067
+ console.log(chalk33.green("\u2705 \u5207\u6362\u6210\u529F"));
5068
+ console.log();
5069
+ console.log(` ${chalk33.bold(provider.name)} ${chalk33.blue("[Gemini CLI]")}`);
5070
+ console.log(` ${chalk33.gray(`URL: ${provider.baseUrl || "(\u9ED8\u8BA4\u7AEF\u70B9)"}`)}`);
5071
+ console.log();
5072
+ console.log(chalk33.gray("\u914D\u7F6E\u5DF2\u66F4\u65B0:"));
5073
+ console.log(chalk33.gray(` - ${getGeminiSettingsPath()}`));
5074
+ console.log(chalk33.gray(` - ${getGeminiEnvPath()}`));
5075
+ console.log();
5076
+ } catch (error) {
5077
+ if (error instanceof ProviderNotFoundError) {
5078
+ console.error(chalk33.red(`
5079
+ \u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728: ${error.message}
5080
+ `));
5081
+ console.log(chalk33.blue("\u{1F4A1} \u67E5\u770B\u6240\u6709\u670D\u52A1\u5546:") + chalk33.white(" ccman gm list\n"));
5082
+ } else {
5083
+ console.error(chalk33.red(`
5084
+ \u274C ${error.message}
5085
+ `));
5086
+ }
5087
+ process.exit(1);
5088
+ }
5089
+ });
5090
+ }
5091
+
5092
+ // src/commands/gemini/current.ts
5093
+ init_dist();
5094
+ import chalk34 from "chalk";
5095
+ function currentCommand3(program2) {
5096
+ program2.command("current").description("\u663E\u793A\u5F53\u524D Gemini CLI \u670D\u52A1\u5546").action(async () => {
5097
+ try {
5098
+ const manager = createGeminiManager();
5099
+ const current = manager.getCurrent();
5100
+ if (!current) {
5101
+ console.log(chalk34.yellow("\n\u26A0\uFE0F \u5F53\u524D\u6CA1\u6709\u6FC0\u6D3B\u7684 Gemini CLI \u670D\u52A1\u5546\n"));
5102
+ console.log(chalk34.blue("\u{1F4A1} \u5217\u51FA\u670D\u52A1\u5546:") + chalk34.white(" ccman gm list\n"));
5103
+ return;
5104
+ }
5105
+ console.log(chalk34.bold("\n\u{1F3AF} \u5F53\u524D Gemini CLI \u670D\u52A1\u5546\n"));
5106
+ console.log(` \u540D\u79F0: ${chalk34.bold(current.name)}`);
5107
+ console.log(` \u5730\u5740: ${chalk34.gray(current.baseUrl || "(\u9ED8\u8BA4\u7AEF\u70B9)")}`);
5108
+ console.log();
5109
+ } catch (error) {
5110
+ console.error(chalk34.red(`
5111
+ \u274C ${error.message}
5112
+ `));
5113
+ process.exit(1);
5114
+ }
5115
+ });
5116
+ }
5117
+
5118
+ // src/commands/gemini/remove.ts
5119
+ init_dist();
5120
+ import chalk35 from "chalk";
5121
+ import inquirer24 from "inquirer";
5122
+ function removeCommand4(program2) {
5123
+ program2.command("remove [name]").alias("rm").description("\u5220\u9664 Gemini CLI \u670D\u52A1\u5546").action(async (name) => {
5124
+ try {
5125
+ const manager = createGeminiManager();
5126
+ const providers = manager.list();
5127
+ if (providers.length === 0) {
5128
+ console.log(chalk35.yellow("\n\u26A0\uFE0F \u6682\u65E0 Gemini CLI \u670D\u52A1\u5546\n"));
5129
+ console.log(chalk35.blue("\u{1F4A1} \u6DFB\u52A0\u670D\u52A1\u5546:") + chalk35.white(" ccman gm add\n"));
5130
+ return;
5131
+ }
5132
+ let targetId;
5133
+ let targetName;
5134
+ if (name) {
5135
+ const provider = manager.findByName(name);
5136
+ if (!provider) {
5137
+ console.log(chalk35.red(`
5138
+ \u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728: ${name}
5139
+ `));
5140
+ process.exit(1);
5141
+ }
5142
+ targetId = provider.id;
5143
+ targetName = provider.name;
5144
+ } else {
5145
+ const { selectedId } = await inquirer24.prompt([
5146
+ {
5147
+ type: "list",
5148
+ name: "selectedId",
5149
+ message: "\u9009\u62E9\u8981\u5220\u9664\u7684\u670D\u52A1\u5546:",
5150
+ choices: providers.map((p) => ({
5151
+ name: `${p.name} - ${p.baseUrl || "(\u9ED8\u8BA4\u7AEF\u70B9)"}`,
5152
+ value: p.id
5153
+ }))
5154
+ }
5155
+ ]);
5156
+ const provider = manager.get(selectedId);
5157
+ targetId = provider.id;
5158
+ targetName = provider.name;
5159
+ }
5160
+ const { confirm } = await inquirer24.prompt([
5161
+ {
5162
+ type: "confirm",
5163
+ name: "confirm",
5164
+ message: `\u786E\u5B9A\u8981\u5220\u9664\u670D\u52A1\u5546 "${targetName}" \u5417\uFF1F`,
5165
+ default: false
5166
+ }
5167
+ ]);
5168
+ if (!confirm) {
5169
+ console.log(chalk35.gray("\n\u5DF2\u53D6\u6D88\u5220\u9664\n"));
5170
+ return;
5171
+ }
5172
+ manager.remove(targetId);
5173
+ console.log(chalk35.green("\n\u2705 \u5DF2\u5220\u9664\u670D\u52A1\u5546\n"));
5174
+ } catch (error) {
5175
+ console.error(chalk35.red(`
5176
+ \u274C ${error.message}
5177
+ `));
5178
+ process.exit(1);
5179
+ }
5180
+ });
5181
+ }
5182
+
5183
+ // src/commands/gemini/edit.ts
5184
+ init_dist();
5185
+ import chalk36 from "chalk";
5186
+ import inquirer25 from "inquirer";
5187
+ function editCommand4(program2) {
5188
+ program2.command("edit [name]").description("\u7F16\u8F91 Gemini CLI \u670D\u52A1\u5546").action(async (name) => {
5189
+ try {
5190
+ const manager = createGeminiManager();
5191
+ const providers = manager.list();
5192
+ if (providers.length === 0) {
5193
+ console.log(chalk36.yellow("\n\u26A0\uFE0F \u6682\u65E0 Gemini CLI \u670D\u52A1\u5546\n"));
5194
+ console.log(chalk36.blue("\u{1F4A1} \u6DFB\u52A0\u670D\u52A1\u5546:") + chalk36.white(" ccman gm add\n"));
5195
+ return;
5196
+ }
5197
+ let targetId;
5198
+ if (name) {
5199
+ const provider2 = manager.findByName(name);
5200
+ if (!provider2) {
5201
+ console.log(chalk36.red(`
5202
+ \u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728: ${name}
5203
+ `));
5204
+ process.exit(1);
5205
+ }
5206
+ targetId = provider2.id;
5207
+ } else {
5208
+ const { selectedId } = await inquirer25.prompt([
5209
+ {
5210
+ type: "list",
5211
+ name: "selectedId",
5212
+ message: "\u9009\u62E9\u8981\u7F16\u8F91\u7684\u670D\u52A1\u5546:",
5213
+ choices: providers.map((p) => ({
5214
+ name: `${p.name} - ${p.baseUrl || "(\u9ED8\u8BA4\u7AEF\u70B9)"}`,
5215
+ value: p.id
5216
+ }))
5217
+ }
5218
+ ]);
5219
+ targetId = selectedId;
5220
+ }
5221
+ const provider = manager.get(targetId);
5222
+ const input = await promptProviderForm({
5223
+ name: provider.name,
5224
+ desc: provider.desc ?? "",
5225
+ baseUrl: provider.baseUrl,
5226
+ apiKey: provider.apiKey
5227
+ });
5228
+ manager.edit(targetId, {
5229
+ name: input.name,
5230
+ desc: input.desc,
5231
+ baseUrl: input.baseUrl,
5232
+ apiKey: input.apiKey
5233
+ });
5234
+ console.log(chalk36.green("\n\u2705 \u7F16\u8F91\u6210\u529F\n"));
5235
+ } catch (error) {
5236
+ console.error(chalk36.red(`
5237
+ \u274C ${error.message}
5238
+ `));
5239
+ process.exit(1);
5240
+ }
5241
+ });
5242
+ }
5243
+
5244
+ // src/commands/gemini/clone.ts
5245
+ init_dist();
5246
+ import chalk37 from "chalk";
5247
+ import inquirer26 from "inquirer";
5248
+ function cloneCommand3(program2) {
5249
+ program2.command("clone [name]").description("\u514B\u9686 Gemini CLI \u670D\u52A1\u5546").action(async (name) => {
5250
+ try {
5251
+ const manager = createGeminiManager();
5252
+ const providers = manager.list();
5253
+ if (providers.length === 0) {
5254
+ console.log(chalk37.yellow("\n\u26A0\uFE0F \u6682\u65E0 Gemini CLI \u670D\u52A1\u5546\n"));
5255
+ console.log(chalk37.blue("\u{1F4A1} \u6DFB\u52A0\u670D\u52A1\u5546:") + chalk37.white(" ccman gm add\n"));
5256
+ return;
5257
+ }
5258
+ let sourceId;
5259
+ if (name) {
5260
+ const provider = manager.findByName(name);
5261
+ if (!provider) {
5262
+ console.log(chalk37.red(`
5263
+ \u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728: ${name}
5264
+ `));
5265
+ process.exit(1);
5266
+ }
5267
+ sourceId = provider.id;
5268
+ } else {
5269
+ const { selectedId } = await inquirer26.prompt([
5270
+ {
5271
+ type: "list",
5272
+ name: "selectedId",
5273
+ message: "\u9009\u62E9\u8981\u514B\u9686\u7684\u670D\u52A1\u5546:",
5274
+ choices: providers.map((p) => ({
5275
+ name: `${p.name} - ${p.baseUrl || "(\u9ED8\u8BA4\u7AEF\u70B9)"}`,
5276
+ value: p.id
5277
+ }))
5278
+ }
5279
+ ]);
5280
+ sourceId = selectedId;
5281
+ }
5282
+ const { newName } = await inquirer26.prompt([
5283
+ {
5284
+ type: "input",
5285
+ name: "newName",
5286
+ message: "\u8F93\u5165\u65B0\u670D\u52A1\u5546\u540D\u79F0:",
5287
+ validate: (value) => {
5288
+ if (!value) return "\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
5289
+ return true;
5290
+ }
5291
+ }
5292
+ ]);
5293
+ const newProvider = manager.clone(sourceId, newName);
5294
+ console.log();
5295
+ console.log(chalk37.green("\u2705 \u514B\u9686\u6210\u529F"));
5296
+ console.log();
5297
+ console.log(` ${chalk37.bold(newProvider.name)} ${chalk37.blue("[Gemini CLI]")}`);
5298
+ console.log(` ${chalk37.gray(newProvider.baseUrl || "(\u9ED8\u8BA4\u7AEF\u70B9)")}`);
5299
+ console.log();
5300
+ } catch (error) {
5301
+ console.error(chalk37.red(`
5302
+ \u274C ${error.message}
5303
+ `));
5304
+ process.exit(1);
5305
+ }
5306
+ });
5307
+ }
5308
+
5309
+ // src/commands/gemini/index.ts
5310
+ function createGeminiCommands(program2) {
5311
+ addCommand4(program2);
5312
+ listCommand4(program2);
5313
+ useCommand3(program2);
5314
+ currentCommand3(program2);
5315
+ removeCommand4(program2);
5316
+ editCommand4(program2);
5317
+ cloneCommand3(program2);
5318
+ }
5319
+
4735
5320
  // src/index.ts
4736
5321
  init_sync();
4737
5322
 
4738
5323
  // src/commands/export.ts
4739
5324
  init_dist();
4740
- import chalk31 from "chalk";
5325
+ import chalk38 from "chalk";
4741
5326
  import path10 from "path";
4742
5327
  function exportCommand(program2) {
4743
5328
  program2.command("export <\u76EE\u6807\u76EE\u5F55>").description("\u5BFC\u51FA\u914D\u7F6E\u5230\u672C\u5730\u76EE\u5F55\uFF08\u5305\u542B API Key\uFF09").action(async (targetDir) => {
4744
5329
  try {
4745
- console.log(chalk31.bold("\n\u{1F4E6} \u5BFC\u51FA\u914D\u7F6E\n"));
5330
+ console.log(chalk38.bold("\n\u{1F4E6} \u5BFC\u51FA\u914D\u7F6E\n"));
4746
5331
  const validation = validateExport();
4747
5332
  if (!validation.valid) {
4748
- console.log(chalk31.red(`\u274C ${validation.message}
5333
+ console.log(chalk38.red(`\u274C ${validation.message}
4749
5334
  `));
4750
5335
  process.exit(1);
4751
5336
  }
4752
5337
  const resolvedPath = targetDir.startsWith("~") ? path10.join(process.env.HOME || "", targetDir.slice(1)) : path10.resolve(targetDir);
4753
5338
  console.log("\u5BFC\u51FA\u6587\u4EF6:");
4754
- console.log(` ${chalk31.cyan("codex.json")} - Codex \u914D\u7F6E`);
4755
- console.log(` ${chalk31.cyan("claude.json")} - Claude \u914D\u7F6E`);
5339
+ console.log(` ${chalk38.cyan("codex.json")} - Codex \u914D\u7F6E`);
5340
+ console.log(` ${chalk38.cyan("claude.json")} - Claude \u914D\u7F6E`);
4756
5341
  console.log();
4757
- console.log(`\u76EE\u6807\u76EE\u5F55: ${chalk31.cyan(resolvedPath)}`);
5342
+ console.log(`\u76EE\u6807\u76EE\u5F55: ${chalk38.cyan(resolvedPath)}`);
4758
5343
  console.log();
4759
- console.log(chalk31.yellow("\u26A0\uFE0F \u5BFC\u51FA\u6587\u4EF6\u5305\u542B API Key\uFF0C\u8BF7\u59A5\u5584\u4FDD\u7BA1"));
5344
+ console.log(chalk38.yellow("\u26A0\uFE0F \u5BFC\u51FA\u6587\u4EF6\u5305\u542B API Key\uFF0C\u8BF7\u59A5\u5584\u4FDD\u7BA1"));
4760
5345
  console.log();
4761
5346
  const result = exportConfig(resolvedPath);
4762
- console.log(chalk31.green("\u2705 \u5BFC\u51FA\u6210\u529F"));
5347
+ console.log(chalk38.green("\u2705 \u5BFC\u51FA\u6210\u529F"));
4763
5348
  console.log();
4764
5349
  console.log("\u5DF2\u5BFC\u51FA\u6587\u4EF6:");
4765
5350
  for (const file of result.exportedFiles) {
4766
- console.log(` ${chalk31.cyan("\u2713")} ${file}`);
5351
+ console.log(` ${chalk38.cyan("\u2713")} ${file}`);
4767
5352
  }
4768
5353
  console.log();
4769
- console.log(chalk31.blue(`\u{1F4A1} \u5BFC\u5165\u547D\u4EE4: ccman import ${resolvedPath}
5354
+ console.log(chalk38.blue(`\u{1F4A1} \u5BFC\u5165\u547D\u4EE4: ccman import ${resolvedPath}
4770
5355
  `));
4771
5356
  } catch (error) {
4772
- console.error(chalk31.red(`
5357
+ console.error(chalk38.red(`
4773
5358
  \u274C ${error.message}
4774
5359
  `));
4775
5360
  process.exit(1);
@@ -4779,31 +5364,31 @@ function exportCommand(program2) {
4779
5364
 
4780
5365
  // src/commands/import.ts
4781
5366
  init_dist();
4782
- import chalk32 from "chalk";
4783
- import inquirer22 from "inquirer";
5367
+ import chalk39 from "chalk";
5368
+ import inquirer27 from "inquirer";
4784
5369
  import path11 from "path";
4785
5370
  function importCommand(program2) {
4786
5371
  program2.command("import <\u6E90\u76EE\u5F55>").description("\u4ECE\u672C\u5730\u76EE\u5F55\u5BFC\u5165\u914D\u7F6E\uFF08\u4F1A\u8986\u76D6\u5F53\u524D\u914D\u7F6E\uFF09").action(async (sourceDir) => {
4787
5372
  try {
4788
5373
  const resolvedPath = sourceDir.startsWith("~") ? path11.join(process.env.HOME || "", sourceDir.slice(1)) : path11.resolve(sourceDir);
4789
- console.log(chalk32.bold("\n\u{1F4E5} \u5BFC\u5165\u914D\u7F6E\n"));
5374
+ console.log(chalk39.bold("\n\u{1F4E5} \u5BFC\u5165\u914D\u7F6E\n"));
4790
5375
  const validation = validateImportDir(resolvedPath);
4791
5376
  if (!validation.valid) {
4792
- console.log(chalk32.red(`\u274C ${validation.message}
5377
+ console.log(chalk39.red(`\u274C ${validation.message}
4793
5378
  `));
4794
5379
  process.exit(1);
4795
5380
  }
4796
- console.log(chalk32.yellow("\u26A0\uFE0F \u8B66\u544A\uFF1A\u5BFC\u5165\u5C06\u8986\u76D6\u5F53\u524D\u914D\u7F6E\n"));
4797
- console.log(`\u6E90\u76EE\u5F55: ${chalk32.cyan(resolvedPath)}`);
5381
+ console.log(chalk39.yellow("\u26A0\uFE0F \u8B66\u544A\uFF1A\u5BFC\u5165\u5C06\u8986\u76D6\u5F53\u524D\u914D\u7F6E\n"));
5382
+ console.log(`\u6E90\u76EE\u5F55: ${chalk39.cyan(resolvedPath)}`);
4798
5383
  console.log();
4799
5384
  console.log("\u627E\u5230\u914D\u7F6E\u6587\u4EF6:");
4800
5385
  for (const file of validation.foundFiles) {
4801
- console.log(` ${chalk32.cyan("\u2713")} ${file}`);
5386
+ console.log(` ${chalk39.cyan("\u2713")} ${file}`);
4802
5387
  }
4803
5388
  console.log();
4804
- console.log(chalk32.gray("\u5F53\u524D\u914D\u7F6E\u5C06\u88AB\u8986\u76D6\uFF08\u81EA\u52A8\u5907\u4EFD\uFF09"));
5389
+ console.log(chalk39.gray("\u5F53\u524D\u914D\u7F6E\u5C06\u88AB\u8986\u76D6\uFF08\u81EA\u52A8\u5907\u4EFD\uFF09"));
4805
5390
  console.log();
4806
- const { confirmFirst } = await inquirer22.prompt([
5391
+ const { confirmFirst } = await inquirer27.prompt([
4807
5392
  {
4808
5393
  type: "confirm",
4809
5394
  name: "confirmFirst",
@@ -4812,13 +5397,13 @@ function importCommand(program2) {
4812
5397
  }
4813
5398
  ]);
4814
5399
  if (!confirmFirst) {
4815
- console.log(chalk32.gray("\n\u274C \u5DF2\u53D6\u6D88\n"));
5400
+ console.log(chalk39.gray("\n\u274C \u5DF2\u53D6\u6D88\n"));
4816
5401
  return;
4817
5402
  }
4818
5403
  console.log();
4819
- console.log(chalk32.red.bold("\u26A0\uFE0F \u6700\u540E\u786E\u8BA4\uFF1A\u6B64\u64CD\u4F5C\u5C06\u8986\u76D6\u6240\u6709\u5F53\u524D\u914D\u7F6E\uFF01"));
5404
+ console.log(chalk39.red.bold("\u26A0\uFE0F \u6700\u540E\u786E\u8BA4\uFF1A\u6B64\u64CD\u4F5C\u5C06\u8986\u76D6\u6240\u6709\u5F53\u524D\u914D\u7F6E\uFF01"));
4820
5405
  console.log();
4821
- const { confirmSecond } = await inquirer22.prompt([
5406
+ const { confirmSecond } = await inquirer27.prompt([
4822
5407
  {
4823
5408
  type: "confirm",
4824
5409
  name: "confirmSecond",
@@ -4827,31 +5412,31 @@ function importCommand(program2) {
4827
5412
  }
4828
5413
  ]);
4829
5414
  if (!confirmSecond) {
4830
- console.log(chalk32.gray("\n\u274C \u5DF2\u53D6\u6D88\n"));
5415
+ console.log(chalk39.gray("\n\u274C \u5DF2\u53D6\u6D88\n"));
4831
5416
  return;
4832
5417
  }
4833
5418
  console.log();
4834
- console.log(chalk32.gray("\u{1F4BE} \u5907\u4EFD\u5F53\u524D\u914D\u7F6E..."));
4835
- console.log(chalk32.gray("\u{1F4E5} \u5BFC\u5165\u65B0\u914D\u7F6E..."));
5419
+ console.log(chalk39.gray("\u{1F4BE} \u5907\u4EFD\u5F53\u524D\u914D\u7F6E..."));
5420
+ console.log(chalk39.gray("\u{1F4E5} \u5BFC\u5165\u65B0\u914D\u7F6E..."));
4836
5421
  const result = importConfig(resolvedPath);
4837
5422
  console.log();
4838
- console.log(chalk32.green("\u2705 \u5BFC\u5165\u6210\u529F"));
5423
+ console.log(chalk39.green("\u2705 \u5BFC\u5165\u6210\u529F"));
4839
5424
  console.log();
4840
5425
  if (result.backupPaths.length > 0) {
4841
5426
  console.log("\u5907\u4EFD\u6587\u4EF6:");
4842
5427
  for (const backupPath of result.backupPaths) {
4843
- console.log(` ${chalk32.gray(backupPath)}`);
5428
+ console.log(` ${chalk39.gray(backupPath)}`);
4844
5429
  }
4845
5430
  console.log();
4846
5431
  }
4847
5432
  console.log("\u5DF2\u5BFC\u5165\u6587\u4EF6:");
4848
5433
  for (const file of result.importedFiles) {
4849
- console.log(` ${chalk32.cyan("\u2713")} ${file}`);
5434
+ console.log(` ${chalk39.cyan("\u2713")} ${file}`);
4850
5435
  }
4851
5436
  console.log();
4852
- console.log(chalk32.blue("\u{1F4A1} \u8BF7\u4F7F\u7528 'ccman cx use' \u6216 'ccman cc use' \u5207\u6362\u670D\u52A1\u5546\n"));
5437
+ console.log(chalk39.blue("\u{1F4A1} \u8BF7\u4F7F\u7528 'ccman cx use' \u6216 'ccman cc use' \u5207\u6362\u670D\u52A1\u5546\n"));
4853
5438
  } catch (error) {
4854
- console.error(chalk32.red(`
5439
+ console.error(chalk39.red(`
4855
5440
  \u274C ${error.message}
4856
5441
  `));
4857
5442
  process.exit(1);
@@ -4862,10 +5447,10 @@ function importCommand(program2) {
4862
5447
  // src/index.ts
4863
5448
  init_dist();
4864
5449
  if (process.env.NODE_ENV === "development") {
4865
- console.log(chalk33.gray("\n[\u5F00\u53D1\u6A21\u5F0F] \u914D\u7F6E\u76EE\u5F55:"));
4866
- console.log(chalk33.gray(` ccman: ${getCcmanDir()}`));
4867
- console.log(chalk33.gray(` codex: ${getCodexDir()}`));
4868
- console.log(chalk33.gray(` claude: ${getClaudeDir()}`));
5450
+ console.log(chalk40.gray("\n[\u5F00\u53D1\u6A21\u5F0F] \u914D\u7F6E\u76EE\u5F55:"));
5451
+ console.log(chalk40.gray(` ccman: ${getCcmanDir()}`));
5452
+ console.log(chalk40.gray(` codex: ${getCodexDir()}`));
5453
+ console.log(chalk40.gray(` claude: ${getClaudeDir()}`));
4869
5454
  console.log();
4870
5455
  }
4871
5456
  var program = new Command3();
@@ -4877,21 +5462,21 @@ program.name("ccman").description("Codex/Claude Code API \u670D\u52A1\u5546\u914
4877
5462
  });
4878
5463
  program.on("command:*", (operands) => {
4879
5464
  const unknownCommand = operands[0];
4880
- console.error(chalk33.red(`
5465
+ console.error(chalk40.red(`
4881
5466
  \u274C \u672A\u77E5\u547D\u4EE4: ${unknownCommand}
4882
5467
  `));
4883
- const availableCommands = ["cx", "cc", "mcp", "sync", "export", "import"];
5468
+ const availableCommands = ["cx", "cc", "gm", "mcp", "sync", "export", "import"];
4884
5469
  const suggestions = availableCommands.filter(
4885
5470
  (cmd) => cmd.includes(unknownCommand) || unknownCommand.includes(cmd)
4886
5471
  );
4887
5472
  if (suggestions.length > 0) {
4888
- console.log(chalk33.yellow("\u{1F4A1} \u4F60\u662F\u4E0D\u662F\u60F3\u8F93\u5165:"));
5473
+ console.log(chalk40.yellow("\u{1F4A1} \u4F60\u662F\u4E0D\u662F\u60F3\u8F93\u5165:"));
4889
5474
  suggestions.forEach((cmd) => {
4890
- console.log(chalk33.cyan(` ccman ${cmd}`));
5475
+ console.log(chalk40.cyan(` ccman ${cmd}`));
4891
5476
  });
4892
5477
  console.log();
4893
5478
  }
4894
- console.log(chalk33.gray("\u67E5\u770B\u6240\u6709\u53EF\u7528\u547D\u4EE4: ") + chalk33.cyan("ccman --help"));
5479
+ console.log(chalk40.gray("\u67E5\u770B\u6240\u6709\u53EF\u7528\u547D\u4EE4: ") + chalk40.cyan("ccman --help"));
4895
5480
  console.log();
4896
5481
  process.exit(1);
4897
5482
  });
@@ -4907,6 +5492,12 @@ cc.action(async () => {
4907
5492
  printLogo();
4908
5493
  await startClaudeMenu();
4909
5494
  });
5495
+ var gm = program.command("gm").description("\u7BA1\u7406 Gemini CLI \u670D\u52A1\u5546");
5496
+ createGeminiCommands(gm);
5497
+ gm.action(async () => {
5498
+ printLogo();
5499
+ await startGeminiMenu();
5500
+ });
4910
5501
  var mcp = program.command("mcp").description("\u7BA1\u7406 MCP \u670D\u52A1\u5668");
4911
5502
  createMCPCommands(mcp);
4912
5503
  mcp.action(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccman",
3
- "version": "3.0.33",
3
+ "version": "3.1.0",
4
4
  "type": "module",
5
5
  "description": "Manage Codex and Claude Code API service provider configurations",
6
6
  "main": "./dist/index.js",
@@ -25,12 +25,12 @@
25
25
  "license": "MIT",
26
26
  "repository": {
27
27
  "type": "git",
28
- "url": "https://github.com/2ue/ccm.git",
28
+ "url": "https://github.com/2ue/ccman.git",
29
29
  "directory": "packages/cli"
30
30
  },
31
- "homepage": "https://github.com/2ue/ccm#readme",
31
+ "homepage": "https://github.com/2ue/ccman#readme",
32
32
  "bugs": {
33
- "url": "https://github.com/2ue/ccm/issues"
33
+ "url": "https://github.com/2ue/ccman/issues"
34
34
  },
35
35
  "dependencies": {
36
36
  "@iarna/toml": "^2.2.5",