zcf 2.0.1 → 2.1.2

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.
@@ -1,4 +1,4 @@
1
- import prompts from '@posva/prompts';
1
+ import inquirer from 'inquirer';
2
2
  import ansis from 'ansis';
3
3
  import { existsSync, mkdirSync, copyFileSync, writeFileSync, readFileSync, readdirSync, statSync } from 'node:fs';
4
4
  import { homedir, platform } from 'node:os';
@@ -7,7 +7,7 @@ import dayjs from 'dayjs';
7
7
  import { fileURLToPath } from 'node:url';
8
8
  import { exec } from 'tinyexec';
9
9
 
10
- const version = "2.0.1";
10
+ const version = "2.1.2";
11
11
  const homepage = "https://github.com/UfoMiao/zcf";
12
12
 
13
13
  const CLAUDE_DIR = join(homedir(), ".claude");
@@ -33,14 +33,18 @@ const I18N = {
33
33
  aiOutputLangHint: "AI \u5C06\u4F7F\u7528\u6B64\u8BED\u8A00\u56DE\u590D\u4F60\u7684\u95EE\u9898",
34
34
  enterCustomLanguage: "\u8BF7\u8F93\u5165\u81EA\u5B9A\u4E49\u8BED\u8A00\uFF08\u4F8B\u5982\uFF1AJapanese, French \u7B49\uFF09",
35
35
  configLangHint: {
36
- "zh-CN": "\u4E2D\u6587\u7248\uFF08\u4FBF\u4E8E\u4E2D\u6587\u7528\u6237\u81EA\u5B9A\u4E49\uFF09",
37
- en: "\u82F1\u6587\u7248\uFF08\u63A8\u8350\uFF0Ctoken \u6D88\u8017\u66F4\u4F4E\uFF09"
36
+ "zh-CN": "\u4FBF\u4E8E\u4E2D\u6587\u7528\u6237\u81EA\u5B9A\u4E49",
37
+ en: "\u63A8\u8350\uFF0Ctoken \u6D88\u8017\u66F4\u4F4E"
38
38
  },
39
39
  installPrompt: "\u68C0\u6D4B\u5230 Claude Code \u672A\u5B89\u88C5\uFF0C\u662F\u5426\u81EA\u52A8\u5B89\u88C5\uFF1F",
40
40
  installing: "\u6B63\u5728\u5B89\u88C5 Claude Code...",
41
41
  installSuccess: "Claude Code \u5B89\u88C5\u6210\u529F",
42
42
  installFailed: "Claude Code \u5B89\u88C5\u5931\u8D25",
43
43
  npmNotFound: "npm \u672A\u5B89\u88C5\u3002\u8BF7\u5148\u5B89\u88C5 Node.js \u548C npm\u3002",
44
+ termuxDetected: "\u68C0\u6D4B\u5230 Termux \u73AF\u5883",
45
+ termuxInstallHint: "\u5728 Termux \u4E2D\uFF0C\u8BF7\u5148\u8FD0\u884C: pkg install nodejs \u6216 pkg install nodejs-lts",
46
+ termuxPathInfo: "\u4F7F\u7528 Termux \u8DEF\u5F84: {path}",
47
+ termuxEnvironmentInfo: "Termux \u73AF\u5883\u901A\u8FC7 pkg \u7BA1\u7406\u5668\u63D0\u4F9B Node.js \u548C npm",
44
48
  configureApi: "\u9009\u62E9 API \u8BA4\u8BC1\u65B9\u5F0F",
45
49
  useAuthToken: "\u4F7F\u7528 Auth Token (OAuth \u8BA4\u8BC1)",
46
50
  authTokenDesc: "\u9002\u7528\u4E8E\u901A\u8FC7 OAuth \u6216\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u7684\u4EE4\u724C",
@@ -78,7 +82,7 @@ const I18N = {
78
82
  configSuccess: "\u914D\u7F6E\u6587\u4EF6\u5DF2\u590D\u5236\u5230",
79
83
  apiConfigSuccess: "API \u914D\u7F6E\u5B8C\u6210",
80
84
  mcpConfigSuccess: "MCP \u670D\u52A1\u5DF2\u914D\u7F6E",
81
- selectMcpServices: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 MCP \u670D\u52A1\uFF08\u7A7A\u683C\u9009\u62E9\uFF0C\u56DE\u8F66\u786E\u8BA4\uFF09",
85
+ selectMcpServices: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 MCP \u670D\u52A1\uFF08\u7A7A\u683C\u9009\u62E9\uFF0Ca\u5168\u9009\uFF0Ci\u53CD\u9009\uFF0C\u56DE\u8F66\u786E\u8BA4\uFF09",
82
86
  allServices: "\u5168\u90E8\u5B89\u88C5",
83
87
  mcpServiceInstalled: "\u5DF2\u9009\u62E9\u7684 MCP \u670D\u52A1",
84
88
  enterExaApiKey: "\u8BF7\u8F93\u5165 Exa API Key\uFF08\u53EF\u4ECE https://dashboard.exa.ai/api-keys \u83B7\u53D6\uFF09",
@@ -126,7 +130,7 @@ const I18N = {
126
130
  changeLanguage: "\u66F4\u6539 ZCF \u754C\u9762\u8BED\u8A00"
127
131
  },
128
132
  returnToMenu: "\u8FD4\u56DE\u4E3B\u83DC\u5355\uFF1F",
129
- goodbye: "\u518D\u89C1\uFF01\u{1F44B}",
133
+ goodbye: "\u{1F44B} \u611F\u8C22\u4F7F\u7528 ZCF\uFF01\u518D\u89C1\uFF01",
130
134
  // Model config
131
135
  selectDefaultModel: "\u9009\u62E9\u9ED8\u8BA4\u6A21\u578B",
132
136
  modelConfigSuccess: "\u9ED8\u8BA4\u6A21\u578B\u5DF2\u914D\u7F6E",
@@ -204,14 +208,18 @@ const I18N = {
204
208
  aiOutputLangHint: "AI will respond to you in this language",
205
209
  enterCustomLanguage: "Enter custom language (e.g., Japanese, French, etc.)",
206
210
  configLangHint: {
207
- "zh-CN": "Chinese (easier for Chinese users to customize)",
208
- en: "English (recommended, lower token consumption)"
211
+ "zh-CN": "easier for Chinese users to customize",
212
+ en: "recommended, lower token consumption"
209
213
  },
210
214
  installPrompt: "Claude Code not found. Install automatically?",
211
215
  installing: "Installing Claude Code...",
212
216
  installSuccess: "Claude Code installed successfully",
213
217
  installFailed: "Failed to install Claude Code",
214
218
  npmNotFound: "npm is not installed. Please install Node.js and npm first.",
219
+ termuxDetected: "Termux environment detected",
220
+ termuxInstallHint: "In Termux, please run first: pkg install nodejs or pkg install nodejs-lts",
221
+ termuxPathInfo: "Using Termux path: {path}",
222
+ termuxEnvironmentInfo: "Termux environment provides Node.js and npm through pkg manager",
215
223
  configureApi: "Select API authentication method",
216
224
  useAuthToken: "Use Auth Token (OAuth authentication)",
217
225
  authTokenDesc: "For tokens obtained via OAuth or browser login",
@@ -249,7 +257,7 @@ const I18N = {
249
257
  configSuccess: "Config files copied to",
250
258
  apiConfigSuccess: "API configured",
251
259
  mcpConfigSuccess: "MCP services configured",
252
- selectMcpServices: "Select MCP services to install (space to select, enter to confirm)",
260
+ selectMcpServices: "Select MCP services to install (space to select, a to select all, i to deselect, enter to confirm)",
253
261
  allServices: "Install all",
254
262
  mcpServiceInstalled: "Selected MCP services",
255
263
  enterExaApiKey: "Enter Exa API Key (get from https://dashboard.exa.ai/api-keys)",
@@ -297,7 +305,7 @@ const I18N = {
297
305
  changeLanguage: "Change ZCF interface language"
298
306
  },
299
307
  returnToMenu: "Return to main menu?",
300
- goodbye: "Goodbye! \u{1F44B}",
308
+ goodbye: "\u{1F44B} Thanks for using ZCF! Goodbye!",
301
309
  // Model config
302
310
  selectDefaultModel: "Select default model",
303
311
  modelConfigSuccess: "Default model configured",
@@ -663,54 +671,54 @@ async function configureAiPersonality(scriptLang, showExisting = true) {
663
671
  console.log(
664
672
  ansis.gray(` ${i18n.currentPersonality || "Current personality"}: ${personalityInfo.name[scriptLang]}`)
665
673
  );
666
- const modifyResponse = await prompts({
674
+ const { modify } = await inquirer.prompt({
667
675
  type: "confirm",
668
676
  name: "modify",
669
677
  message: i18n.modifyPersonality || "Modify AI personality?",
670
- initial: false
678
+ default: false
671
679
  });
672
- if (!modifyResponse.modify) {
680
+ if (!modify) {
673
681
  console.log(ansis.green(`\u2714 ${i18n.keepPersonality || "Keeping existing personality"}`));
674
682
  return;
675
683
  }
676
684
  }
677
685
  }
678
- const personalityResponse = await prompts({
679
- type: "select",
686
+ const { personality } = await inquirer.prompt({
687
+ type: "list",
680
688
  name: "personality",
681
689
  message: i18n.selectAiPersonality || "Select AI personality",
682
690
  choices: AI_PERSONALITIES.map((p) => ({
683
- title: p.name[scriptLang],
691
+ name: p.id !== "custom" ? `${p.name[scriptLang]} - ${ansis.gray(p.directive[scriptLang].substring(0, 50) + "...")}` : `${p.name[scriptLang]} - ${ansis.gray(i18n.customPersonalityHint || "Define your own personality")}`,
684
692
  value: p.id,
685
- description: p.id !== "custom" ? ansis.gray(p.directive[scriptLang].substring(0, 50) + "...") : ansis.gray(i18n.customPersonalityHint || "Define your own personality")
693
+ short: p.name[scriptLang]
686
694
  })),
687
- initial: existingPersonality ? AI_PERSONALITIES.findIndex((p) => p.id === existingPersonality) : 0
695
+ default: existingPersonality ? AI_PERSONALITIES.findIndex((p) => p.id === existingPersonality) : 0
688
696
  });
689
- if (!personalityResponse.personality) {
697
+ if (!personality) {
690
698
  console.log(ansis.yellow(i18n.cancelled));
691
699
  return;
692
700
  }
693
701
  let directive = "";
694
- if (personalityResponse.personality === "custom") {
695
- const customResponse = await prompts({
696
- type: "text",
697
- name: "directive",
702
+ if (personality === "custom") {
703
+ const { customDirective } = await inquirer.prompt({
704
+ type: "input",
705
+ name: "customDirective",
698
706
  message: i18n.enterCustomPersonality || "Enter custom personality directive",
699
707
  validate: (value) => !!value || i18n.directiveCannotBeEmpty
700
708
  });
701
- if (!customResponse.directive) {
709
+ if (!customDirective) {
702
710
  console.log(ansis.yellow(i18n.cancelled));
703
711
  return;
704
712
  }
705
- directive = customResponse.directive;
713
+ directive = customDirective;
706
714
  } else {
707
- const selected = AI_PERSONALITIES.find((p) => p.id === personalityResponse.personality);
715
+ const selected = AI_PERSONALITIES.find((p) => p.id === personality);
708
716
  if (selected) {
709
717
  directive = selected.directive[scriptLang];
710
718
  }
711
719
  }
712
720
  await applyPersonalityDirective(directive);
713
- updateZcfConfig({ aiPersonality: personalityResponse.personality });
721
+ updateZcfConfig({ aiPersonality: personality });
714
722
  console.log(ansis.green(`\u2714 ${i18n.personalityConfigured || "AI personality configured"}`));
715
723
  }
716
724
  async function applyPersonalityDirective(directive) {
@@ -750,6 +758,29 @@ function displayBannerWithInfo(subtitle) {
750
758
  `));
751
759
  }
752
760
 
761
+ function handleExitPromptError(error) {
762
+ if (error instanceof Error && error.name === "ExitPromptError") {
763
+ const zcfConfig = readZcfConfig();
764
+ const defaultLang = zcfConfig?.preferredLang || "zh-CN";
765
+ const i18n = I18N[defaultLang];
766
+ console.log(ansis.cyan(`
767
+ ${i18n.goodbye}
768
+ `));
769
+ process.exit(0);
770
+ }
771
+ return false;
772
+ }
773
+ function handleGeneralError(error, lang) {
774
+ const zcfConfig = readZcfConfig();
775
+ const defaultLang = lang || zcfConfig?.preferredLang || "en";
776
+ const errorMsg = I18N[defaultLang].error;
777
+ console.error(ansis.red(`${errorMsg}:`), error);
778
+ if (error instanceof Error) {
779
+ console.error(ansis.gray(`Stack: ${error.stack}`));
780
+ }
781
+ process.exit(1);
782
+ }
783
+
753
784
  function mergeArraysUnique(arr1, arr2) {
754
785
  const combined = [...arr1 || [], ...arr2 || []];
755
786
  return [...new Set(combined)];
@@ -1006,31 +1037,31 @@ function formatApiKeyDisplay(apiKey) {
1006
1037
  async function configureApiCompletely(i18n, scriptLang, preselectedAuthType) {
1007
1038
  let authType = preselectedAuthType;
1008
1039
  if (!authType) {
1009
- const authResponse = await prompts({
1010
- type: "select",
1040
+ const { authType: selectedAuthType } = await inquirer.prompt({
1041
+ type: "list",
1011
1042
  name: "authType",
1012
1043
  message: i18n.configureApi,
1013
1044
  choices: [
1014
1045
  {
1015
- title: i18n.useAuthToken,
1046
+ name: `${i18n.useAuthToken} - ${ansis.gray(i18n.authTokenDesc)}`,
1016
1047
  value: "auth_token",
1017
- description: ansis.gray(i18n.authTokenDesc)
1048
+ short: i18n.useAuthToken
1018
1049
  },
1019
1050
  {
1020
- title: i18n.useApiKey,
1051
+ name: `${i18n.useApiKey} - ${ansis.gray(i18n.apiKeyDesc)}`,
1021
1052
  value: "api_key",
1022
- description: ansis.gray(i18n.apiKeyDesc)
1053
+ short: i18n.useApiKey
1023
1054
  }
1024
1055
  ]
1025
1056
  });
1026
- if (!authResponse.authType) {
1057
+ if (!selectedAuthType) {
1027
1058
  console.log(ansis.yellow(i18n.cancelled));
1028
1059
  return null;
1029
1060
  }
1030
- authType = authResponse.authType;
1061
+ authType = selectedAuthType;
1031
1062
  }
1032
- const urlResponse = await prompts({
1033
- type: "text",
1063
+ const { url } = await inquirer.prompt({
1064
+ type: "input",
1034
1065
  name: "url",
1035
1066
  message: i18n.enterApiUrl,
1036
1067
  validate: (value) => {
@@ -1043,13 +1074,13 @@ async function configureApiCompletely(i18n, scriptLang, preselectedAuthType) {
1043
1074
  }
1044
1075
  }
1045
1076
  });
1046
- if (urlResponse.url === void 0) {
1077
+ if (url === void 0) {
1047
1078
  console.log(ansis.yellow(i18n.cancelled));
1048
1079
  return null;
1049
1080
  }
1050
1081
  const keyMessage = authType === "auth_token" ? i18n.enterAuthToken : i18n.enterApiKey;
1051
- const keyResponse = await prompts({
1052
- type: "text",
1082
+ const { key } = await inquirer.prompt({
1083
+ type: "input",
1053
1084
  name: "key",
1054
1085
  message: keyMessage,
1055
1086
  validate: (value) => {
@@ -1063,115 +1094,107 @@ async function configureApiCompletely(i18n, scriptLang, preselectedAuthType) {
1063
1094
  return true;
1064
1095
  }
1065
1096
  });
1066
- if (keyResponse.key === void 0) {
1097
+ if (key === void 0) {
1067
1098
  console.log(ansis.yellow(i18n.cancelled));
1068
1099
  return null;
1069
1100
  }
1070
- console.log(ansis.gray(` API Key: ${formatApiKeyDisplay(keyResponse.key)}`));
1071
- return { url: urlResponse.url, key: keyResponse.key, authType };
1101
+ console.log(ansis.gray(` API Key: ${formatApiKeyDisplay(key)}`));
1102
+ return { url, key, authType };
1072
1103
  }
1073
1104
  async function modifyApiConfigPartially(existingConfig, i18n, scriptLang) {
1074
1105
  let currentConfig = { ...existingConfig };
1075
- while (true) {
1076
- const latestConfig = getExistingApiConfig();
1077
- if (latestConfig) {
1078
- currentConfig = latestConfig;
1079
- }
1080
- const modifyResponse = await prompts({
1081
- type: "select",
1082
- name: "item",
1083
- message: i18n.selectModifyItems,
1084
- choices: [
1085
- { title: i18n.modifyApiUrl, value: "url" },
1086
- { title: i18n.modifyApiKey, value: "key" },
1087
- { title: i18n.modifyAuthType, value: "authType" }
1088
- ]
1106
+ const latestConfig = getExistingApiConfig();
1107
+ if (latestConfig) {
1108
+ currentConfig = latestConfig;
1109
+ }
1110
+ const { item } = await inquirer.prompt({
1111
+ type: "list",
1112
+ name: "item",
1113
+ message: i18n.selectModifyItems,
1114
+ choices: [
1115
+ { name: i18n.modifyApiUrl, value: "url" },
1116
+ { name: i18n.modifyApiKey, value: "key" },
1117
+ { name: i18n.modifyAuthType, value: "authType" }
1118
+ ]
1119
+ });
1120
+ if (!item) {
1121
+ console.log(ansis.yellow(i18n.cancelled));
1122
+ return;
1123
+ }
1124
+ if (item === "url") {
1125
+ const { url } = await inquirer.prompt({
1126
+ type: "input",
1127
+ name: "url",
1128
+ message: i18n.enterNewApiUrl.replace("{url}", currentConfig.url || i18n.none),
1129
+ default: currentConfig.url,
1130
+ validate: (value) => {
1131
+ if (!value) return i18n.urlRequired;
1132
+ try {
1133
+ new URL(value);
1134
+ return true;
1135
+ } catch {
1136
+ return i18n.invalidUrl;
1137
+ }
1138
+ }
1089
1139
  });
1090
- if (!modifyResponse.item) {
1140
+ if (url === void 0) {
1091
1141
  console.log(ansis.yellow(i18n.cancelled));
1092
1142
  return;
1093
1143
  }
1094
- if (modifyResponse.item === "url") {
1095
- const urlResponse = await prompts({
1096
- type: "text",
1097
- name: "url",
1098
- message: i18n.enterNewApiUrl.replace("{url}", currentConfig.url || i18n.none),
1099
- initial: currentConfig.url,
1100
- validate: (value) => {
1101
- if (!value) return i18n.urlRequired;
1102
- try {
1103
- new URL(value);
1104
- return true;
1105
- } catch {
1106
- return i18n.invalidUrl;
1107
- }
1144
+ currentConfig.url = url;
1145
+ const savedConfig = configureApi(currentConfig);
1146
+ if (savedConfig) {
1147
+ console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
1148
+ console.log(ansis.gray(` ${i18n.apiConfigUrl}: ${savedConfig.url}`));
1149
+ }
1150
+ } else if (item === "key") {
1151
+ const authType = currentConfig.authType || "auth_token";
1152
+ const keyMessage = authType === "auth_token" ? i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none) : i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none);
1153
+ const { key } = await inquirer.prompt({
1154
+ type: "input",
1155
+ name: "key",
1156
+ message: keyMessage,
1157
+ validate: (value) => {
1158
+ if (!value) {
1159
+ return i18n.keyRequired;
1108
1160
  }
1109
- });
1110
- if (urlResponse.url === void 0) {
1111
- continue;
1112
- }
1113
- currentConfig.url = urlResponse.url;
1114
- const savedConfig = configureApi(currentConfig);
1115
- if (savedConfig) {
1116
- console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
1117
- console.log(ansis.gray(` ${i18n.apiConfigUrl}: ${savedConfig.url}`));
1118
- }
1119
- } else if (modifyResponse.item === "key") {
1120
- const authType = currentConfig.authType || "auth_token";
1121
- const keyMessage = authType === "auth_token" ? i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none) : i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none);
1122
- const keyResponse = await prompts({
1123
- type: "text",
1124
- name: "key",
1125
- message: keyMessage,
1126
- validate: (value) => {
1127
- if (!value) {
1128
- return i18n.keyRequired;
1129
- }
1130
- const validation = validateApiKey(value, scriptLang);
1131
- if (!validation.isValid) {
1132
- return validation.error || i18n.invalidKeyFormat;
1133
- }
1134
- return true;
1161
+ const validation = validateApiKey(value, scriptLang);
1162
+ if (!validation.isValid) {
1163
+ return validation.error || i18n.invalidKeyFormat;
1135
1164
  }
1136
- });
1137
- if (keyResponse.key === void 0) {
1138
- continue;
1139
- }
1140
- currentConfig.key = keyResponse.key;
1141
- const savedConfig = configureApi(currentConfig);
1142
- if (savedConfig) {
1143
- console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
1144
- console.log(ansis.gray(` ${i18n.apiConfigKey}: ${formatApiKeyDisplay(savedConfig.key)}`));
1145
- }
1146
- } else if (modifyResponse.item === "authType") {
1147
- const authResponse = await prompts({
1148
- type: "select",
1149
- name: "authType",
1150
- message: i18n.selectNewAuthType.replace("{type}", currentConfig.authType || i18n.none),
1151
- choices: [
1152
- { title: "Auth Token (OAuth)", value: "auth_token" },
1153
- { title: "API Key", value: "api_key" }
1154
- ],
1155
- initial: currentConfig.authType === "api_key" ? 1 : 0
1156
- });
1157
- if (authResponse.authType === void 0) {
1158
- continue;
1159
- }
1160
- currentConfig.authType = authResponse.authType;
1161
- const savedConfig = configureApi(currentConfig);
1162
- if (savedConfig) {
1163
- console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
1164
- console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${savedConfig.authType}`));
1165
+ return true;
1165
1166
  }
1167
+ });
1168
+ if (key === void 0) {
1169
+ console.log(ansis.yellow(i18n.cancelled));
1170
+ return;
1171
+ }
1172
+ currentConfig.key = key;
1173
+ const savedConfig = configureApi(currentConfig);
1174
+ if (savedConfig) {
1175
+ console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
1176
+ console.log(ansis.gray(` ${i18n.apiConfigKey}: ${formatApiKeyDisplay(savedConfig.key)}`));
1166
1177
  }
1167
- const continueResponse = await prompts({
1168
- type: "confirm",
1169
- name: "continue",
1170
- message: i18n.continueModification,
1171
- initial: true
1178
+ } else if (item === "authType") {
1179
+ const { authType } = await inquirer.prompt({
1180
+ type: "list",
1181
+ name: "authType",
1182
+ message: i18n.selectNewAuthType.replace("{type}", currentConfig.authType || i18n.none),
1183
+ choices: [
1184
+ { name: "Auth Token (OAuth)", value: "auth_token" },
1185
+ { name: "API Key", value: "api_key" }
1186
+ ],
1187
+ default: currentConfig.authType === "api_key" ? 1 : 0
1172
1188
  });
1173
- if (!continueResponse.continue) {
1174
- break;
1189
+ if (authType === void 0) {
1190
+ console.log(ansis.yellow(i18n.cancelled));
1191
+ return;
1192
+ }
1193
+ currentConfig.authType = authType;
1194
+ const savedConfig = configureApi(currentConfig);
1195
+ if (savedConfig) {
1196
+ console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
1197
+ console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${savedConfig.authType}`));
1175
1198
  }
1176
1199
  }
1177
1200
  }
@@ -1196,6 +1219,12 @@ function getPlatform() {
1196
1219
  if (p === "darwin") return "macos";
1197
1220
  return "linux";
1198
1221
  }
1222
+ function isTermux() {
1223
+ return !!(process.env.PREFIX && process.env.PREFIX.includes("com.termux")) || !!process.env.TERMUX_VERSION || existsSync("/data/data/com.termux/files/usr");
1224
+ }
1225
+ function getTermuxPrefix() {
1226
+ return process.env.PREFIX || "/data/data/com.termux/files/usr";
1227
+ }
1199
1228
  function isWindows() {
1200
1229
  return getPlatform() === "windows";
1201
1230
  }
@@ -1209,10 +1238,38 @@ async function commandExists(command) {
1209
1238
  try {
1210
1239
  const cmd = getPlatform() === "windows" ? "where" : "which";
1211
1240
  const res = await exec(cmd, [command]);
1212
- return res.exitCode === 0;
1241
+ if (res.exitCode === 0) {
1242
+ return true;
1243
+ }
1213
1244
  } catch {
1214
- return false;
1215
1245
  }
1246
+ if (isTermux()) {
1247
+ const termuxPrefix = getTermuxPrefix();
1248
+ const possiblePaths = [
1249
+ `${termuxPrefix}/bin/${command}`,
1250
+ `${termuxPrefix}/usr/bin/${command}`,
1251
+ `/data/data/com.termux/files/usr/bin/${command}`
1252
+ ];
1253
+ for (const path of possiblePaths) {
1254
+ if (existsSync(path)) {
1255
+ return true;
1256
+ }
1257
+ }
1258
+ }
1259
+ if (getPlatform() !== "windows") {
1260
+ const commonPaths = [
1261
+ `/usr/local/bin/${command}`,
1262
+ `/usr/bin/${command}`,
1263
+ `/bin/${command}`,
1264
+ `${process.env.HOME}/.local/bin/${command}`
1265
+ ];
1266
+ for (const path of commonPaths) {
1267
+ if (existsSync(path)) {
1268
+ return true;
1269
+ }
1270
+ }
1271
+ }
1272
+ return false;
1216
1273
  }
1217
1274
 
1218
1275
  async function isClaudeCodeInstalled() {
@@ -1220,15 +1277,28 @@ async function isClaudeCodeInstalled() {
1220
1277
  }
1221
1278
  async function installClaudeCode(lang) {
1222
1279
  const i18n = I18N[lang];
1280
+ if (isTermux()) {
1281
+ console.log(ansis.yellow(`\u2139 ${i18n.termuxDetected}`));
1282
+ const termuxPrefix = getTermuxPrefix();
1283
+ console.log(ansis.gray(i18n.termuxPathInfo.replace("{path}", termuxPrefix)));
1284
+ console.log(ansis.gray(`Node.js: ${termuxPrefix}/bin/node`));
1285
+ console.log(ansis.gray(`npm: ${termuxPrefix}/bin/npm`));
1286
+ }
1223
1287
  console.log(i18n.installing);
1224
1288
  try {
1225
- if (!await commandExists("npm")) {
1226
- throw new Error(i18n.npmNotFound);
1227
- }
1228
1289
  await exec("npm", ["install", "-g", "@anthropic-ai/claude-code"]);
1229
1290
  console.log(`\u2714 ${i18n.installSuccess}`);
1291
+ if (isTermux()) {
1292
+ console.log(ansis.gray(`
1293
+ Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
1294
+ }
1230
1295
  } catch (error) {
1231
1296
  console.error(`\u2716 ${i18n.installFailed}`);
1297
+ if (isTermux()) {
1298
+ console.error(ansis.yellow(`
1299
+ ${i18n.termuxInstallHint}
1300
+ `));
1301
+ }
1232
1302
  throw error;
1233
1303
  }
1234
1304
  }
@@ -1312,30 +1382,33 @@ async function selectAiOutputLanguage(scriptLang, defaultLang) {
1312
1382
  value: key
1313
1383
  }));
1314
1384
  const defaultChoice = defaultLang || (scriptLang === "zh-CN" ? "zh-CN" : "en");
1315
- const aiLangResponse = await prompts({
1316
- type: "select",
1385
+ const { lang } = await inquirer.prompt({
1386
+ type: "list",
1317
1387
  name: "lang",
1318
1388
  message: i18n.selectAiOutputLang,
1319
- choices: aiLangChoices,
1320
- initial: aiLangChoices.findIndex((c) => c.value === defaultChoice)
1389
+ choices: aiLangChoices.map((choice) => ({
1390
+ name: choice.title,
1391
+ value: choice.value
1392
+ })),
1393
+ default: defaultChoice
1321
1394
  });
1322
- if (!aiLangResponse.lang) {
1395
+ if (!lang) {
1323
1396
  console.log(ansis.yellow(i18n.cancelled));
1324
1397
  process.exit(0);
1325
1398
  }
1326
- let aiOutputLang = aiLangResponse.lang;
1399
+ let aiOutputLang = lang;
1327
1400
  if (aiOutputLang === "custom") {
1328
- const customLangResponse = await prompts({
1329
- type: "text",
1401
+ const { customLang } = await inquirer.prompt({
1402
+ type: "input",
1330
1403
  name: "customLang",
1331
1404
  message: i18n.enterCustomLanguage,
1332
1405
  validate: (value) => !!value || i18n.languageRequired
1333
1406
  });
1334
- if (!customLangResponse.customLang) {
1407
+ if (!customLang) {
1335
1408
  console.log(ansis.yellow(i18n.cancelled));
1336
1409
  process.exit(0);
1337
1410
  }
1338
- return customLangResponse.customLang;
1411
+ return customLang;
1339
1412
  }
1340
1413
  return aiOutputLang;
1341
1414
  }
@@ -1347,20 +1420,20 @@ async function selectScriptLanguage(currentLang) {
1347
1420
  if (currentLang) {
1348
1421
  return currentLang;
1349
1422
  }
1350
- const response = await prompts({
1351
- type: "select",
1423
+ const { lang } = await inquirer.prompt({
1424
+ type: "list",
1352
1425
  name: "lang",
1353
1426
  message: "Select ZCF display language / \u9009\u62E9ZCF\u663E\u793A\u8BED\u8A00",
1354
1427
  choices: SUPPORTED_LANGS.map((l) => ({
1355
- title: LANG_LABELS[l],
1428
+ name: LANG_LABELS[l],
1356
1429
  value: l
1357
1430
  }))
1358
1431
  });
1359
- if (!response.lang) {
1432
+ if (!lang) {
1360
1433
  console.log(ansis.yellow("Operation cancelled / \u64CD\u4F5C\u5DF2\u53D6\u6D88"));
1361
1434
  process.exit(0);
1362
1435
  }
1363
- const scriptLang = response.lang;
1436
+ const scriptLang = lang;
1364
1437
  updateZcfConfig({
1365
1438
  version,
1366
1439
  preferredLang: scriptLang
@@ -1379,6 +1452,26 @@ async function resolveAiOutputLanguage(scriptLang, commandLineOption, savedConfi
1379
1452
  return await selectAiOutputLanguage(scriptLang, scriptLang);
1380
1453
  }
1381
1454
 
1455
+ async function selectMcpServices(scriptLang) {
1456
+ const i18n = I18N[scriptLang];
1457
+ const choices = MCP_SERVICES.map((service) => ({
1458
+ name: `${service.name[scriptLang]} - ${ansis.gray(service.description[scriptLang])}`,
1459
+ value: service.id,
1460
+ selected: false
1461
+ }));
1462
+ const { services } = await inquirer.prompt({
1463
+ type: "checkbox",
1464
+ name: "services",
1465
+ message: i18n.selectMcpServices,
1466
+ choices
1467
+ });
1468
+ if (services === void 0) {
1469
+ console.log(ansis.yellow(i18n.cancelled));
1470
+ return void 0;
1471
+ }
1472
+ return services;
1473
+ }
1474
+
1382
1475
  async function init(options = {}) {
1383
1476
  try {
1384
1477
  if (!options.skipBanner) {
@@ -1386,38 +1479,43 @@ async function init(options = {}) {
1386
1479
  }
1387
1480
  const scriptLang = await selectScriptLanguage(options.lang);
1388
1481
  const i18n = I18N[scriptLang];
1482
+ if (isTermux()) {
1483
+ console.log(ansis.yellow(`
1484
+ \u2139 ${i18n.termuxDetected}`));
1485
+ console.log(ansis.gray(i18n.termuxEnvironmentInfo));
1486
+ }
1389
1487
  let configLang = options.configLang;
1390
1488
  if (!configLang) {
1391
- const response = await prompts({
1392
- type: "select",
1489
+ const { lang } = await inquirer.prompt({
1490
+ type: "list",
1393
1491
  name: "lang",
1394
1492
  message: i18n.selectConfigLang,
1395
1493
  choices: SUPPORTED_LANGS.map((l) => ({
1396
- title: `${LANG_LABELS[l]} - ${i18n.configLangHint[l]}`,
1494
+ name: `${LANG_LABELS[l]} - ${i18n.configLangHint[l]}`,
1397
1495
  value: l
1398
1496
  }))
1399
1497
  });
1400
- if (!response.lang) {
1498
+ if (!lang) {
1401
1499
  console.log(ansis.yellow(i18n.cancelled));
1402
1500
  process.exit(0);
1403
1501
  }
1404
- configLang = response.lang;
1502
+ configLang = lang;
1405
1503
  }
1406
1504
  const zcfConfig = readZcfConfig();
1407
1505
  const aiOutputLang = await resolveAiOutputLanguage(scriptLang, options.aiOutputLang, zcfConfig);
1408
1506
  const installed = await isClaudeCodeInstalled();
1409
1507
  if (!installed) {
1410
- const response = await prompts({
1508
+ const { shouldInstall } = await inquirer.prompt({
1411
1509
  type: "confirm",
1412
1510
  name: "shouldInstall",
1413
1511
  message: i18n.installPrompt,
1414
- initial: true
1512
+ default: true
1415
1513
  });
1416
- if (response.shouldInstall === void 0) {
1514
+ if (shouldInstall === void 0) {
1417
1515
  console.log(ansis.yellow(i18n.cancelled));
1418
1516
  process.exit(0);
1419
1517
  }
1420
- if (response.shouldInstall) {
1518
+ if (shouldInstall) {
1421
1519
  await installClaudeCode(scriptLang);
1422
1520
  } else {
1423
1521
  console.log(ansis.yellow(i18n.skip));
@@ -1426,36 +1524,32 @@ async function init(options = {}) {
1426
1524
  console.log(ansis.green(`\u2714 ${i18n.installSuccess}`));
1427
1525
  }
1428
1526
  ensureClaudeDir();
1429
- let onlyUpdateDocs = false;
1430
1527
  let action = "new";
1431
1528
  if (existsSync(SETTINGS_FILE) && !options.force) {
1432
- const actionResponse = await prompts({
1433
- type: "select",
1529
+ const { action: userAction } = await inquirer.prompt({
1530
+ type: "list",
1434
1531
  name: "action",
1435
1532
  message: i18n.existingConfig,
1436
1533
  choices: [
1437
- { title: i18n.backupAndOverwrite, value: "backup" },
1438
- { title: i18n.updateDocsOnly, value: "docs-only" },
1439
- { title: i18n.mergeConfig, value: "merge" },
1440
- { title: i18n.skip, value: "skip" }
1534
+ { name: i18n.backupAndOverwrite, value: "backup" },
1535
+ { name: i18n.updateDocsOnly, value: "docs-only" },
1536
+ { name: i18n.mergeConfig, value: "merge" },
1537
+ { name: i18n.skip, value: "skip" }
1441
1538
  ]
1442
1539
  });
1443
- if (!actionResponse.action) {
1540
+ if (!userAction) {
1444
1541
  console.log(ansis.yellow(i18n.cancelled));
1445
1542
  process.exit(0);
1446
1543
  }
1447
- action = actionResponse.action;
1544
+ action = userAction;
1448
1545
  if (action === "skip") {
1449
1546
  console.log(ansis.yellow(i18n.skip));
1450
1547
  return;
1451
1548
  }
1452
- if (action === "docs-only") {
1453
- onlyUpdateDocs = true;
1454
- }
1455
1549
  }
1456
1550
  let apiConfig = null;
1457
1551
  const isNewInstall = !existsSync(SETTINGS_FILE);
1458
- if (!onlyUpdateDocs && (isNewInstall || action === "backup" || action === "merge")) {
1552
+ if (action !== "docs-only" && (isNewInstall || ["backup", "merge"].includes(action))) {
1459
1553
  const existingApiConfig = getExistingApiConfig();
1460
1554
  if (existingApiConfig) {
1461
1555
  console.log("\n" + ansis.blue(`\u2139 ${i18n.existingApiConfig}`));
@@ -1467,84 +1561,74 @@ async function init(options = {}) {
1467
1561
  );
1468
1562
  console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${existingApiConfig.authType || i18n.notConfigured}
1469
1563
  `));
1470
- const actionResponse = await prompts({
1471
- type: "select",
1564
+ const { action: apiAction } = await inquirer.prompt({
1565
+ type: "list",
1472
1566
  name: "action",
1473
1567
  message: i18n.selectApiAction,
1474
1568
  choices: [
1475
- { title: i18n.keepExistingConfig, value: "keep" },
1476
- { title: i18n.modifyAllConfig, value: "modify-all" },
1477
- { title: i18n.modifyPartialConfig, value: "modify-partial" },
1478
- { title: i18n.skipApi, value: "skip" }
1569
+ { name: i18n.keepExistingConfig, value: "keep" },
1570
+ { name: i18n.modifyAllConfig, value: "modify-all" },
1571
+ { name: i18n.modifyPartialConfig, value: "modify-partial" },
1572
+ { name: i18n.skipApi, value: "skip" }
1479
1573
  ]
1480
1574
  });
1481
- if (!actionResponse.action) {
1575
+ if (!apiAction) {
1482
1576
  console.log(ansis.yellow(i18n.cancelled));
1483
1577
  process.exit(0);
1484
1578
  }
1485
- if (actionResponse.action === "keep" || actionResponse.action === "skip") {
1579
+ if (apiAction === "keep" || apiAction === "skip") {
1486
1580
  apiConfig = null;
1487
- } else if (actionResponse.action === "modify-partial") {
1581
+ } else if (apiAction === "modify-partial") {
1488
1582
  await modifyApiConfigPartially(existingApiConfig, i18n, scriptLang);
1489
1583
  apiConfig = null;
1490
- } else if (actionResponse.action === "modify-all") {
1584
+ } else if (apiAction === "modify-all") {
1491
1585
  apiConfig = await configureApiCompletely(i18n, scriptLang);
1492
1586
  }
1493
1587
  } else {
1494
- const apiResponse = await prompts({
1495
- type: "select",
1588
+ const { apiChoice } = await inquirer.prompt({
1589
+ type: "list",
1496
1590
  name: "apiChoice",
1497
1591
  message: i18n.configureApi,
1498
1592
  choices: [
1499
1593
  {
1500
- title: i18n.useAuthToken,
1594
+ name: `${i18n.useAuthToken} - ${ansis.gray(i18n.authTokenDesc)}`,
1501
1595
  value: "auth_token",
1502
- description: ansis.gray(i18n.authTokenDesc)
1596
+ short: i18n.useAuthToken
1503
1597
  },
1504
1598
  {
1505
- title: i18n.useApiKey,
1599
+ name: `${i18n.useApiKey} - ${ansis.gray(i18n.apiKeyDesc)}`,
1506
1600
  value: "api_key",
1507
- description: ansis.gray(i18n.apiKeyDesc)
1601
+ short: i18n.useApiKey
1508
1602
  },
1509
1603
  {
1510
- title: i18n.skipApi,
1604
+ name: i18n.skipApi,
1511
1605
  value: "skip"
1512
1606
  }
1513
1607
  ]
1514
1608
  });
1515
- if (!apiResponse.apiChoice) {
1609
+ if (!apiChoice) {
1516
1610
  console.log(ansis.yellow(i18n.cancelled));
1517
1611
  process.exit(0);
1518
1612
  }
1519
- if (apiResponse.apiChoice !== "skip") {
1520
- apiConfig = await configureApiCompletely(i18n, scriptLang, apiResponse.apiChoice);
1613
+ if (apiChoice !== "skip") {
1614
+ apiConfig = await configureApiCompletely(i18n, scriptLang, apiChoice);
1521
1615
  }
1522
1616
  }
1523
1617
  }
1524
- if (action === "backup") {
1525
- const backupDir = backupExistingConfig();
1526
- if (backupDir) {
1527
- console.log(ansis.gray(`\u2714 ${i18n.backupSuccess}: ${backupDir}`));
1528
- }
1529
- copyConfigFiles(configLang, false);
1530
- } else if (action === "docs-only") {
1618
+ if (["backup", "docs-only", "merge"].includes(action)) {
1531
1619
  const backupDir = backupExistingConfig();
1532
1620
  if (backupDir) {
1533
1621
  console.log(ansis.gray(`\u2714 ${i18n.backupSuccess}: ${backupDir}`));
1534
1622
  }
1623
+ }
1624
+ if (action === "docs-only") {
1535
1625
  copyConfigFiles(configLang, true);
1536
- } else if (action === "merge") {
1537
- const backupDir = backupExistingConfig();
1538
- if (backupDir) {
1539
- console.log(ansis.gray(`\u2714 ${i18n.backupSuccess}: ${backupDir}`));
1540
- }
1541
- copyConfigFiles(configLang, false);
1542
- } else if (action === "new") {
1626
+ } else if (["backup", "merge", "new"].includes(action)) {
1543
1627
  copyConfigFiles(configLang, false);
1544
1628
  }
1545
1629
  applyAiLanguageDirective(aiOutputLang);
1546
1630
  await configureAiPersonality(scriptLang);
1547
- if (apiConfig && !onlyUpdateDocs) {
1631
+ if (apiConfig && action !== "docs-only") {
1548
1632
  const configuredApi = configureApi(apiConfig);
1549
1633
  if (configuredApi) {
1550
1634
  console.log(ansis.green(`\u2714 ${i18n.apiConfigSuccess}`));
@@ -1557,18 +1641,18 @@ async function init(options = {}) {
1557
1641
  }
1558
1642
  }
1559
1643
  }
1560
- if (!onlyUpdateDocs) {
1561
- const mcpResponse = await prompts({
1644
+ if (action !== "docs-only") {
1645
+ const { shouldConfigureMcp } = await inquirer.prompt({
1562
1646
  type: "confirm",
1563
1647
  name: "shouldConfigureMcp",
1564
1648
  message: i18n.configureMcp,
1565
- initial: true
1649
+ default: true
1566
1650
  });
1567
- if (mcpResponse.shouldConfigureMcp === void 0) {
1651
+ if (shouldConfigureMcp === void 0) {
1568
1652
  console.log(ansis.yellow(i18n.cancelled));
1569
1653
  process.exit(0);
1570
1654
  }
1571
- if (mcpResponse.shouldConfigureMcp) {
1655
+ if (shouldConfigureMcp) {
1572
1656
  if (isWindows()) {
1573
1657
  console.log(
1574
1658
  ansis.blue(
@@ -1576,34 +1660,10 @@ async function init(options = {}) {
1576
1660
  )
1577
1661
  );
1578
1662
  }
1579
- const choices = [
1580
- {
1581
- title: ansis.bold(i18n.allServices),
1582
- value: "ALL",
1583
- selected: false
1584
- },
1585
- ...MCP_SERVICES.map((service) => ({
1586
- title: `${service.name[scriptLang]} - ${ansis.gray(service.description[scriptLang])}`,
1587
- value: service.id,
1588
- selected: false
1589
- }))
1590
- ];
1591
- const selectedResponse = await prompts({
1592
- type: "multiselect",
1593
- name: "services",
1594
- message: i18n.selectMcpServices,
1595
- choices,
1596
- instructions: false,
1597
- hint: i18n.spaceToSelectReturn
1598
- });
1599
- if (selectedResponse.services === void 0) {
1600
- console.log(ansis.yellow(i18n.cancelled));
1663
+ const selectedServices = await selectMcpServices(scriptLang);
1664
+ if (selectedServices === void 0) {
1601
1665
  process.exit(0);
1602
1666
  }
1603
- let selectedServices = selectedResponse.services || [];
1604
- if (selectedServices.includes("ALL")) {
1605
- selectedServices = MCP_SERVICES.map((s) => s.id);
1606
- }
1607
1667
  if (selectedServices.length > 0) {
1608
1668
  const mcpBackupPath = backupMcpConfig();
1609
1669
  if (mcpBackupPath) {
@@ -1615,18 +1675,18 @@ async function init(options = {}) {
1615
1675
  if (!service) continue;
1616
1676
  let config = service.config;
1617
1677
  if (service.requiresApiKey) {
1618
- const apiKeyResponse = await prompts({
1619
- type: "text",
1678
+ const { apiKey } = await inquirer.prompt({
1679
+ type: "input",
1620
1680
  name: "apiKey",
1621
1681
  message: service.apiKeyPrompt[scriptLang],
1622
1682
  validate: (value) => !!value || i18n.keyRequired
1623
1683
  });
1624
- if (apiKeyResponse.apiKey === void 0) {
1684
+ if (apiKey === void 0) {
1625
1685
  console.log(ansis.yellow(`${i18n.skip}: ${service.name[scriptLang]}`));
1626
1686
  continue;
1627
1687
  }
1628
- if (apiKeyResponse.apiKey) {
1629
- config = buildMcpServerConfig(service.config, apiKeyResponse.apiKey, service.apiKeyPlaceholder);
1688
+ if (apiKey) {
1689
+ config = buildMcpServerConfig(service.config, apiKey, service.apiKeyPlaceholder);
1630
1690
  } else {
1631
1691
  continue;
1632
1692
  }
@@ -1653,9 +1713,10 @@ async function init(options = {}) {
1653
1713
  console.log(ansis.green(`\u2714 ${i18n.configSuccess} ${CLAUDE_DIR}`));
1654
1714
  console.log("\n" + ansis.cyan(i18n.complete));
1655
1715
  } catch (error) {
1656
- console.error(ansis.red(`${I18N[options.lang || "en"].error}:`), error);
1657
- process.exit(1);
1716
+ if (!handleExitPromptError(error)) {
1717
+ handleGeneralError(error, options.lang);
1718
+ }
1658
1719
  }
1659
1720
  }
1660
1721
 
1661
- export { AI_OUTPUT_LANGUAGES as A, selectScriptLanguage as B, CLAUDE_DIR as C, readZcfConfig as D, resolveAiOutputLanguage as E, updatePromptOnly as F, updateZcfConfig as G, version as H, I18N as I, configureAiPersonality as J, isWindows as K, LANG_LABELS as L, MCP_SERVICES as M, formatApiKeyDisplay as N, modifyApiConfigPartially as O, validateApiKey as P, displayBannerWithInfo as Q, SETTINGS_FILE as S, ZCF_CONFIG_FILE as Z, CLAUDE_MD_FILE as a, ClAUDE_CONFIG_FILE as b, commandExists as c, SUPPORTED_LANGS as d, isClaudeCodeInstalled as e, installClaudeCode as f, getPlatform as g, ensureClaudeDir as h, init as i, backupExistingConfig as j, copyConfigFiles as k, configureApi as l, mergeConfigs as m, mergeSettingsFile as n, getExistingApiConfig as o, applyAiLanguageDirective as p, getMcpConfigPath as q, readMcpConfig as r, backupMcpConfig as s, mergeMcpServers as t, updateDefaultModel as u, buildMcpServerConfig as v, writeMcpConfig as w, fixWindowsMcpConfig as x, addCompletedOnboarding as y, displayBanner as z };
1722
+ export { AI_OUTPUT_LANGUAGES as A, readZcfConfig as B, CLAUDE_DIR as C, resolveAiOutputLanguage as D, configureAiPersonality as E, isWindows as F, selectMcpServices as G, formatApiKeyDisplay as H, I18N as I, modifyApiConfigPartially as J, validateApiKey as K, LANG_LABELS as L, MCP_SERVICES as M, displayBanner as N, selectScriptLanguage as O, updatePromptOnly as P, version as Q, handleExitPromptError as R, SETTINGS_FILE as S, handleGeneralError as T, displayBannerWithInfo as U, ZCF_CONFIG_FILE as Z, CLAUDE_MD_FILE as a, ClAUDE_CONFIG_FILE as b, commandExists as c, SUPPORTED_LANGS as d, isClaudeCodeInstalled as e, installClaudeCode as f, getPlatform as g, ensureClaudeDir as h, init as i, backupExistingConfig as j, copyConfigFiles as k, configureApi as l, mergeConfigs as m, mergeSettingsFile as n, getExistingApiConfig as o, applyAiLanguageDirective as p, getMcpConfigPath as q, readMcpConfig as r, backupMcpConfig as s, mergeMcpServers as t, updateDefaultModel as u, buildMcpServerConfig as v, writeMcpConfig as w, fixWindowsMcpConfig as x, addCompletedOnboarding as y, updateZcfConfig as z };