@benbenwu/zcf 3.6.4

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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/bin/zcf.mjs +2 -0
  4. package/dist/chunks/api-providers.mjs +137 -0
  5. package/dist/chunks/claude-code-config-manager.mjs +731 -0
  6. package/dist/chunks/claude-code-incremental-manager.mjs +601 -0
  7. package/dist/chunks/codex-config-switch.mjs +394 -0
  8. package/dist/chunks/codex-provider-manager.mjs +197 -0
  9. package/dist/chunks/codex-uninstaller.mjs +422 -0
  10. package/dist/chunks/commands.mjs +118 -0
  11. package/dist/chunks/features.mjs +632 -0
  12. package/dist/chunks/simple-config.mjs +7904 -0
  13. package/dist/cli.d.mts +1 -0
  14. package/dist/cli.d.ts +1 -0
  15. package/dist/cli.mjs +2013 -0
  16. package/dist/i18n/locales/en/api.json +53 -0
  17. package/dist/i18n/locales/en/ccr.json +65 -0
  18. package/dist/i18n/locales/en/cli.json +55 -0
  19. package/dist/i18n/locales/en/codex.json +123 -0
  20. package/dist/i18n/locales/en/cometix.json +29 -0
  21. package/dist/i18n/locales/en/common.json +20 -0
  22. package/dist/i18n/locales/en/configuration.json +85 -0
  23. package/dist/i18n/locales/en/errors.json +26 -0
  24. package/dist/i18n/locales/en/installation.json +80 -0
  25. package/dist/i18n/locales/en/language.json +19 -0
  26. package/dist/i18n/locales/en/mcp.json +24 -0
  27. package/dist/i18n/locales/en/menu.json +51 -0
  28. package/dist/i18n/locales/en/multi-config.json +79 -0
  29. package/dist/i18n/locales/en/tools.json +15 -0
  30. package/dist/i18n/locales/en/uninstall.json +56 -0
  31. package/dist/i18n/locales/en/updater.json +25 -0
  32. package/dist/i18n/locales/en/workflow.json +23 -0
  33. package/dist/i18n/locales/zh-CN/api.json +53 -0
  34. package/dist/i18n/locales/zh-CN/ccr.json +65 -0
  35. package/dist/i18n/locales/zh-CN/cli.json +55 -0
  36. package/dist/i18n/locales/zh-CN/codex.json +123 -0
  37. package/dist/i18n/locales/zh-CN/cometix.json +29 -0
  38. package/dist/i18n/locales/zh-CN/common.json +20 -0
  39. package/dist/i18n/locales/zh-CN/configuration.json +85 -0
  40. package/dist/i18n/locales/zh-CN/errors.json +26 -0
  41. package/dist/i18n/locales/zh-CN/installation.json +80 -0
  42. package/dist/i18n/locales/zh-CN/language.json +19 -0
  43. package/dist/i18n/locales/zh-CN/mcp.json +24 -0
  44. package/dist/i18n/locales/zh-CN/menu.json +51 -0
  45. package/dist/i18n/locales/zh-CN/multi-config.json +79 -0
  46. package/dist/i18n/locales/zh-CN/tools.json +15 -0
  47. package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
  48. package/dist/i18n/locales/zh-CN/updater.json +25 -0
  49. package/dist/i18n/locales/zh-CN/workflow.json +23 -0
  50. package/dist/index.d.mts +324 -0
  51. package/dist/index.d.ts +324 -0
  52. package/dist/index.mjs +19 -0
  53. package/dist/shared/zcf.DGjQxTq_.mjs +34 -0
  54. package/package.json +117 -0
  55. package/templates/CLAUDE.md +221 -0
  56. package/templates/claude-code/CLAUDE.md +250 -0
  57. package/templates/claude-code/common/settings.json +48 -0
  58. package/templates/claude-code/en/workflow/bmad/commands/bmad-init.md +275 -0
  59. package/templates/claude-code/en/workflow/common/agents/get-current-datetime.md +29 -0
  60. package/templates/claude-code/en/workflow/common/agents/init-architect.md +114 -0
  61. package/templates/claude-code/en/workflow/common/commands/init-project.md +53 -0
  62. package/templates/claude-code/en/workflow/plan/agents/planner.md +116 -0
  63. package/templates/claude-code/en/workflow/plan/agents/ui-ux-designer.md +91 -0
  64. package/templates/claude-code/en/workflow/plan/commands/feat.md +105 -0
  65. package/templates/claude-code/zh-CN/workflow/bmad/commands/bmad-init.md +275 -0
  66. package/templates/claude-code/zh-CN/workflow/common/agents/get-current-datetime.md +29 -0
  67. package/templates/claude-code/zh-CN/workflow/common/agents/init-architect.md +114 -0
  68. package/templates/claude-code/zh-CN/workflow/common/commands/init-project.md +53 -0
  69. package/templates/claude-code/zh-CN/workflow/plan/agents/planner.md +116 -0
  70. package/templates/claude-code/zh-CN/workflow/plan/agents/ui-ux-designer.md +91 -0
  71. package/templates/claude-code/zh-CN/workflow/plan/commands/feat.md +105 -0
  72. package/templates/codex/common/config.toml +0 -0
  73. package/templates/common/output-styles/en/engineer-professional.md +88 -0
  74. package/templates/common/output-styles/en/laowang-engineer.md +127 -0
  75. package/templates/common/output-styles/en/leibus-engineer.md +251 -0
  76. package/templates/common/output-styles/en/nekomata-engineer.md +120 -0
  77. package/templates/common/output-styles/en/ojousama-engineer.md +121 -0
  78. package/templates/common/output-styles/en/rem-engineer.md +173 -0
  79. package/templates/common/output-styles/zh-CN/engineer-professional.md +89 -0
  80. package/templates/common/output-styles/zh-CN/laowang-engineer.md +127 -0
  81. package/templates/common/output-styles/zh-CN/leibus-engineer.md +251 -0
  82. package/templates/common/output-styles/zh-CN/nekomata-engineer.md +120 -0
  83. package/templates/common/output-styles/zh-CN/ojousama-engineer.md +121 -0
  84. package/templates/common/output-styles/zh-CN/rem-engineer.md +179 -0
  85. package/templates/common/workflow/git/en/git-cleanBranches.md +102 -0
  86. package/templates/common/workflow/git/en/git-commit.md +205 -0
  87. package/templates/common/workflow/git/en/git-rollback.md +90 -0
  88. package/templates/common/workflow/git/en/git-worktree.md +276 -0
  89. package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +102 -0
  90. package/templates/common/workflow/git/zh-CN/git-commit.md +205 -0
  91. package/templates/common/workflow/git/zh-CN/git-rollback.md +90 -0
  92. package/templates/common/workflow/git/zh-CN/git-worktree.md +276 -0
  93. package/templates/common/workflow/sixStep/en/workflow.md +251 -0
  94. package/templates/common/workflow/sixStep/zh-CN/workflow.md +215 -0
package/dist/cli.mjs ADDED
@@ -0,0 +1,2013 @@
1
+ #!/usr/bin/env node
2
+ import cac from 'cac';
3
+ import ansis from 'ansis';
4
+ import { an as ensureI18nInitialized, ao as i18n, aQ as readCcrConfig, aL as isCcrInstalled, aM as installCcr, aR as configureCcrFeature, ar as promptBoolean, aS as handleExitPromptError, aT as handleGeneralError, aU as COMETIX_COMMAND_NAME, aV as COMETIX_COMMANDS, aW as installCometixLine, ap as addNumbersToChoices, aX as checkAndUpdateTools, aY as runCodexUpdate, aZ as resolveCodeType$1, aw as readJsonConfig, a_ as writeJsonConfig, t as ZCF_CONFIG_FILE, aG as readZcfConfig, D as DEFAULT_CODE_TOOL_TYPE, x as isCodeToolType, a$ as displayBanner, aE as updateZcfConfig, b0 as version, b1 as resolveAiOutputLanguage, b2 as updatePromptOnly, b3 as selectAndInstallWorkflows, b4 as checkClaudeCodeVersionAndPrompt, z as resolveCodeToolType$1, b5 as displayBannerWithInfo, v as CODE_TOOL_BANNERS, b6 as runCodexUninstall, b7 as configureCodexMcp, b8 as configureCodexApi, b9 as runCodexWorkflowImportWithLanguageSelection, ba as runCodexFullInit, i as init, bb as switchCodexProvider, bc as listCodexProviders, aB as readCodexConfig, bd as switchToOfficialLogin, be as switchToProvider, bf as readZcfConfigAsync, bg as initI18n, bh as selectScriptLanguage, aF as changeLanguage } from './chunks/simple-config.mjs';
5
+ import { existsSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import inquirer from 'inquirer';
8
+ import { join } from 'pathe';
9
+ import { runCcrStop, runCcrStart, runCcrRestart, runCcrStatus, runCcrUi } from './chunks/commands.mjs';
10
+ import { changeScriptLanguageFeature, configureCodexAiMemoryFeature, configureCodexDefaultModelFeature, configureEnvPermissionFeature, configureAiMemoryFeature, configureDefaultModelFeature, configureMcpFeature, configureApiFeature } from './chunks/features.mjs';
11
+ import process from 'node:process';
12
+ import { x, exec as exec$1 } from 'tinyexec';
13
+ import { exec, spawn } from 'node:child_process';
14
+ import { promisify } from 'node:util';
15
+ import { pathExists } from 'fs-extra';
16
+ import { m as moveToTrash } from './shared/zcf.DGjQxTq_.mjs';
17
+ import { ClaudeCodeConfigManager } from './chunks/claude-code-config-manager.mjs';
18
+ import 'dayjs';
19
+ import 'node:url';
20
+ import 'inquirer-toggle';
21
+ import 'ora';
22
+ import 'semver';
23
+ import '@rainbowatcher/toml-edit-js';
24
+ import 'node:fs/promises';
25
+ import 'i18next';
26
+ import 'i18next-fs-backend';
27
+ import 'trash';
28
+
29
+ function isCcrConfigured() {
30
+ const CCR_CONFIG_FILE = join(homedir(), ".claude-code-router", "config.json");
31
+ if (!existsSync(CCR_CONFIG_FILE)) {
32
+ return false;
33
+ }
34
+ const config = readCcrConfig();
35
+ return config !== null;
36
+ }
37
+ async function showCcrMenu() {
38
+ try {
39
+ ensureI18nInitialized();
40
+ console.log(`
41
+ ${ansis.cyan("\u2550".repeat(50))}`);
42
+ console.log(ansis.bold.cyan(` ${i18n.t("ccr:ccrMenuTitle")}`));
43
+ console.log(`${ansis.cyan("\u2550".repeat(50))}
44
+ `);
45
+ console.log(` ${ansis.cyan("1.")} ${i18n.t("ccr:ccrMenuOptions.initCcr")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.initCcr")}`)}`);
46
+ console.log(` ${ansis.cyan("2.")} ${i18n.t("ccr:ccrMenuOptions.startUi")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.startUi")}`)}`);
47
+ console.log(` ${ansis.cyan("3.")} ${i18n.t("ccr:ccrMenuOptions.checkStatus")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.checkStatus")}`)}`);
48
+ console.log(` ${ansis.cyan("4.")} ${i18n.t("ccr:ccrMenuOptions.restart")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.restart")}`)}`);
49
+ console.log(` ${ansis.cyan("5.")} ${i18n.t("ccr:ccrMenuOptions.start")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.start")}`)}`);
50
+ console.log(` ${ansis.cyan("6.")} ${i18n.t("ccr:ccrMenuOptions.stop")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.stop")}`)}`);
51
+ console.log(` ${ansis.yellow("0.")} ${i18n.t("ccr:ccrMenuOptions.back")}`);
52
+ console.log("");
53
+ const { choice } = await inquirer.prompt({
54
+ type: "input",
55
+ name: "choice",
56
+ message: i18n.t("common:enterChoice"),
57
+ validate: (value) => {
58
+ const valid = ["1", "2", "3", "4", "5", "6", "0"];
59
+ return valid.includes(value) || i18n.t("common:invalidChoice");
60
+ }
61
+ });
62
+ switch (choice) {
63
+ case "1": {
64
+ const ccrStatus = await isCcrInstalled();
65
+ if (!ccrStatus.hasCorrectPackage) {
66
+ await installCcr();
67
+ } else {
68
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrAlreadyInstalled")}`));
69
+ }
70
+ await configureCcrFeature();
71
+ console.log(ansis.green(`
72
+ \u2714 ${i18n.t("ccr:ccrSetupComplete")}`));
73
+ break;
74
+ }
75
+ case "2":
76
+ if (!isCcrConfigured()) {
77
+ console.log(ansis.yellow(`
78
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
79
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
80
+ `));
81
+ } else {
82
+ const config = readCcrConfig();
83
+ await runCcrUi(config?.APIKEY);
84
+ }
85
+ break;
86
+ case "3":
87
+ if (!isCcrConfigured()) {
88
+ console.log(ansis.yellow(`
89
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
90
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
91
+ `));
92
+ } else {
93
+ await runCcrStatus();
94
+ }
95
+ break;
96
+ case "4":
97
+ if (!isCcrConfigured()) {
98
+ console.log(ansis.yellow(`
99
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
100
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
101
+ `));
102
+ } else {
103
+ await runCcrRestart();
104
+ }
105
+ break;
106
+ case "5":
107
+ if (!isCcrConfigured()) {
108
+ console.log(ansis.yellow(`
109
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
110
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
111
+ `));
112
+ } else {
113
+ await runCcrStart();
114
+ }
115
+ break;
116
+ case "6":
117
+ if (!isCcrConfigured()) {
118
+ console.log(ansis.yellow(`
119
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
120
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
121
+ `));
122
+ } else {
123
+ await runCcrStop();
124
+ }
125
+ break;
126
+ case "0":
127
+ return false;
128
+ }
129
+ if (choice !== "0") {
130
+ console.log(`
131
+ ${ansis.dim("\u2500".repeat(50))}
132
+ `);
133
+ const continueInCcr = await promptBoolean({
134
+ message: i18n.t("common:returnToMenu"),
135
+ defaultValue: true
136
+ });
137
+ if (continueInCcr) {
138
+ return await showCcrMenu();
139
+ }
140
+ }
141
+ return false;
142
+ } catch (error) {
143
+ if (!handleExitPromptError(error)) {
144
+ handleGeneralError(error);
145
+ }
146
+ return false;
147
+ }
148
+ }
149
+
150
+ async function executeCcusage(args = []) {
151
+ try {
152
+ const command = "npx";
153
+ const commandArgs = ["ccusage@latest", ...args || []];
154
+ console.log(ansis.cyan(i18n.t("tools:runningCcusage")));
155
+ console.log(ansis.gray(`$ npx ccusage@latest ${(args || []).join(" ")}`));
156
+ console.log("");
157
+ await x(command, commandArgs, {
158
+ nodeOptions: {
159
+ stdio: "inherit"
160
+ }
161
+ });
162
+ } catch (error) {
163
+ console.error(ansis.red(i18n.t("tools:ccusageFailed")));
164
+ console.error(ansis.yellow(i18n.t("tools:checkNetworkConnection")));
165
+ if (process.env.DEBUG) {
166
+ console.error(ansis.gray(i18n.t("tools:errorDetails")), error);
167
+ }
168
+ if (process.env.NODE_ENV !== "test") {
169
+ process.exit(1);
170
+ }
171
+ throw error;
172
+ }
173
+ }
174
+
175
+ const execAsync = promisify(exec);
176
+ async function runCometixPrintConfig() {
177
+ ensureI18nInitialized();
178
+ try {
179
+ console.log(ansis.blue(`${i18n.t("cometix:printingConfig")}`));
180
+ const { stdout } = await execAsync(COMETIX_COMMANDS.PRINT_CONFIG);
181
+ console.log(stdout);
182
+ } catch (error) {
183
+ if (error.message.includes(`command not found: ${COMETIX_COMMAND_NAME}`)) {
184
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`));
185
+ } else {
186
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:printConfigFailed")}: ${error}`));
187
+ }
188
+ throw error;
189
+ }
190
+ }
191
+ async function runCometixTuiConfig() {
192
+ ensureI18nInitialized();
193
+ return new Promise((resolve, reject) => {
194
+ console.log(ansis.blue(`${i18n.t("cometix:enteringTuiConfig")}`));
195
+ const child = spawn(COMETIX_COMMAND_NAME, ["-c"], {
196
+ stdio: "inherit",
197
+ // This allows the TUI to interact directly with the terminal
198
+ shell: true
199
+ });
200
+ child.on("close", (code) => {
201
+ if (code === 0) {
202
+ console.log(ansis.green(`\u2713 ${i18n.t("cometix:tuiConfigSuccess")}`));
203
+ resolve();
204
+ } else {
205
+ const error = new Error(`${COMETIX_COMMAND_NAME} -c exited with code ${code}`);
206
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`));
207
+ reject(error);
208
+ }
209
+ });
210
+ child.on("error", (error) => {
211
+ if (error.message.includes(`command not found`) || error.message.includes("ENOENT")) {
212
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`));
213
+ } else {
214
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`));
215
+ }
216
+ reject(error);
217
+ });
218
+ });
219
+ }
220
+
221
+ async function showCometixMenu() {
222
+ try {
223
+ ensureI18nInitialized();
224
+ console.log(`
225
+ ${ansis.cyan("\u2550".repeat(50))}`);
226
+ console.log(ansis.bold.cyan(` ${i18n.t("cometix:cometixMenuTitle")}`));
227
+ console.log(`${ansis.cyan("\u2550".repeat(50))}
228
+ `);
229
+ console.log(` ${ansis.cyan("1.")} ${i18n.t("cometix:cometixMenuOptions.installOrUpdate")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.installOrUpdate")}`)}`);
230
+ console.log(` ${ansis.cyan("2.")} ${i18n.t("cometix:cometixMenuOptions.printConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.printConfig")}`)}`);
231
+ console.log(` ${ansis.cyan("3.")} ${i18n.t("cometix:cometixMenuOptions.customConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.customConfig")}`)}`);
232
+ console.log(` ${ansis.yellow("0.")} ${i18n.t("cometix:cometixMenuOptions.back")}`);
233
+ console.log("");
234
+ const { choice } = await inquirer.prompt({
235
+ type: "input",
236
+ name: "choice",
237
+ message: i18n.t("common:enterChoice"),
238
+ validate: async (value) => {
239
+ const valid = ["1", "2", "3", "0"];
240
+ return valid.includes(value) || i18n.t("common:invalidChoice");
241
+ }
242
+ });
243
+ switch (choice) {
244
+ case "1":
245
+ await installCometixLine();
246
+ break;
247
+ case "2":
248
+ await runCometixPrintConfig();
249
+ break;
250
+ case "3":
251
+ await runCometixTuiConfig();
252
+ break;
253
+ case "0":
254
+ return false;
255
+ }
256
+ if (choice !== "0") {
257
+ console.log(`
258
+ ${ansis.dim("\u2500".repeat(50))}
259
+ `);
260
+ const continueInCometix = await promptBoolean({
261
+ message: i18n.t("common:returnToMenu"),
262
+ defaultValue: true
263
+ });
264
+ if (continueInCometix) {
265
+ return await showCometixMenu();
266
+ }
267
+ }
268
+ return false;
269
+ } catch (error) {
270
+ if (!handleExitPromptError(error)) {
271
+ handleGeneralError(error);
272
+ }
273
+ return false;
274
+ }
275
+ }
276
+
277
+ async function runCcusageFeature() {
278
+ ensureI18nInitialized();
279
+ console.log("");
280
+ console.log(ansis.cyan(i18n.t("menu:menuOptions.ccusage")));
281
+ console.log(ansis.gray(`${i18n.t("tools:ccusageDescription")}`));
282
+ console.log("");
283
+ const choices = [
284
+ { name: i18n.t("tools:ccusageModes.daily"), value: "daily" },
285
+ { name: i18n.t("tools:ccusageModes.monthly"), value: "monthly" },
286
+ { name: i18n.t("tools:ccusageModes.session"), value: "session" },
287
+ { name: i18n.t("tools:ccusageModes.blocks"), value: "blocks" },
288
+ { name: i18n.t("tools:ccusageModes.custom"), value: "custom" },
289
+ { name: i18n.t("common:back"), value: "back" }
290
+ ];
291
+ const { mode } = await inquirer.prompt({
292
+ type: "list",
293
+ name: "mode",
294
+ message: i18n.t("tools:selectAnalysisMode"),
295
+ choices: addNumbersToChoices(choices)
296
+ });
297
+ if (mode === "back") {
298
+ return;
299
+ }
300
+ let args = [];
301
+ if (mode === "custom") {
302
+ const { customArgs } = await inquirer.prompt({
303
+ type: "input",
304
+ name: "customArgs",
305
+ message: i18n.t("tools:enterCustomArgs"),
306
+ default: ""
307
+ });
308
+ if (customArgs === null || customArgs === void 0 || customArgs === "") {
309
+ args = [];
310
+ } else {
311
+ const argsString = String(customArgs).trim();
312
+ if (!argsString) {
313
+ args = [];
314
+ } else {
315
+ const argPattern = /"([^"]*)"|'([^']*)'|(\S+)/g;
316
+ const matches = [];
317
+ let match = argPattern.exec(argsString);
318
+ while (match !== null) {
319
+ const value = match[1] || match[2] || match[3];
320
+ if (value) {
321
+ matches.push(value);
322
+ }
323
+ match = argPattern.exec(argsString);
324
+ }
325
+ args = matches;
326
+ }
327
+ }
328
+ } else {
329
+ args = [mode];
330
+ }
331
+ console.log("");
332
+ await executeCcusage(args);
333
+ console.log("");
334
+ await inquirer.prompt({
335
+ type: "input",
336
+ name: "continue",
337
+ message: ansis.gray(i18n.t("tools:pressEnterToContinue"))
338
+ });
339
+ }
340
+ async function runCcrMenuFeature() {
341
+ await showCcrMenu();
342
+ }
343
+ async function runCometixMenuFeature() {
344
+ await showCometixMenu();
345
+ }
346
+
347
+ class ToolUpdateScheduler {
348
+ /**
349
+ * Update tools based on code type
350
+ * @param codeType - The code tool type to update
351
+ * @param skipPrompt - Whether to skip interactive prompts
352
+ */
353
+ async updateByCodeType(codeType, skipPrompt = false) {
354
+ await ensureI18nInitialized();
355
+ switch (codeType) {
356
+ case "claude-code":
357
+ await this.updateClaudeCodeTools(skipPrompt);
358
+ break;
359
+ case "codex":
360
+ await this.updateCodexTools(skipPrompt);
361
+ break;
362
+ default:
363
+ throw new Error(`Unsupported code type: ${codeType}`);
364
+ }
365
+ }
366
+ /**
367
+ * Update Claude Code related tools
368
+ * @param skipPrompt - Whether to skip interactive prompts
369
+ */
370
+ async updateClaudeCodeTools(skipPrompt) {
371
+ await checkAndUpdateTools(skipPrompt);
372
+ }
373
+ /**
374
+ * Update Codex tools
375
+ * @param skipPrompt - Whether to skip interactive prompts
376
+ */
377
+ async updateCodexTools(skipPrompt) {
378
+ await runCodexUpdate(false, skipPrompt);
379
+ }
380
+ }
381
+
382
+ async function checkUpdates(options = {}) {
383
+ try {
384
+ const skipPrompt = options.skipPrompt || false;
385
+ let codeType;
386
+ try {
387
+ codeType = await resolveCodeType$1(options.codeType);
388
+ } catch (err) {
389
+ const errorMessage = err instanceof Error ? err.message : String(err);
390
+ console.error(ansis.red(`${errorMessage}
391
+ Defaulting to "claude-code".`));
392
+ codeType = "claude-code";
393
+ }
394
+ const scheduler = new ToolUpdateScheduler();
395
+ await scheduler.updateByCodeType(codeType, skipPrompt);
396
+ } catch (error) {
397
+ const errorMessage = error instanceof Error ? error.message : String(error);
398
+ console.error(ansis.red(`${i18n.t("updater:errorCheckingUpdates")} ${errorMessage}`));
399
+ process.exit(1);
400
+ }
401
+ }
402
+
403
+ class ZcfUninstaller {
404
+ _lang;
405
+ // Reserved for future i18n support
406
+ conflictResolution = /* @__PURE__ */ new Map();
407
+ constructor(lang = "en") {
408
+ this._lang = lang;
409
+ this.conflictResolution.set("claude-code", ["mcps"]);
410
+ void this._lang;
411
+ }
412
+ /**
413
+ * 1. Remove outputStyle field from settings.json and output-styles directory
414
+ */
415
+ async removeOutputStyles() {
416
+ const result = {
417
+ success: false,
418
+ removed: [],
419
+ removedConfigs: [],
420
+ errors: [],
421
+ warnings: []
422
+ };
423
+ try {
424
+ const settingsPath = join(homedir(), ".claude", "settings.json");
425
+ const outputStylesPath = join(homedir(), ".claude", "output-styles");
426
+ if (await pathExists(settingsPath)) {
427
+ const settings = readJsonConfig(settingsPath) || {};
428
+ if (settings.outputStyle) {
429
+ delete settings.outputStyle;
430
+ writeJsonConfig(settingsPath, settings);
431
+ result.removedConfigs.push("outputStyle field from settings.json");
432
+ }
433
+ } else {
434
+ result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
435
+ }
436
+ if (await pathExists(outputStylesPath)) {
437
+ const trashResult = await moveToTrash(outputStylesPath);
438
+ if (!trashResult[0]?.success) {
439
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
440
+ }
441
+ result.removed.push("~/.claude/output-styles/");
442
+ } else {
443
+ result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound"));
444
+ }
445
+ result.success = true;
446
+ } catch (error) {
447
+ result.errors.push(`Failed to remove output styles: ${error.message}`);
448
+ }
449
+ return result;
450
+ }
451
+ /**
452
+ * 2. Remove custom commands directory (commands/zcf/)
453
+ */
454
+ async removeCustomCommands() {
455
+ const result = {
456
+ success: false,
457
+ removed: [],
458
+ removedConfigs: [],
459
+ errors: [],
460
+ warnings: []
461
+ };
462
+ try {
463
+ const commandsPath = join(homedir(), ".claude", "commands", "zcf");
464
+ if (await pathExists(commandsPath)) {
465
+ const trashResult = await moveToTrash(commandsPath);
466
+ if (!trashResult[0]?.success) {
467
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
468
+ }
469
+ result.removed.push("commands/zcf/");
470
+ result.success = true;
471
+ } else {
472
+ result.warnings.push(i18n.t("uninstall:commandsNotFound"));
473
+ result.success = true;
474
+ }
475
+ } catch (error) {
476
+ result.errors.push(`Failed to remove custom commands: ${error.message}`);
477
+ }
478
+ return result;
479
+ }
480
+ /**
481
+ * 3. Remove custom agents directory (agents/zcf/)
482
+ */
483
+ async removeCustomAgents() {
484
+ const result = {
485
+ success: false,
486
+ removed: [],
487
+ removedConfigs: [],
488
+ errors: [],
489
+ warnings: []
490
+ };
491
+ try {
492
+ const agentsPath = join(homedir(), ".claude", "agents", "zcf");
493
+ if (await pathExists(agentsPath)) {
494
+ const trashResult = await moveToTrash(agentsPath);
495
+ if (!trashResult[0]?.success) {
496
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
497
+ }
498
+ result.removed.push("agents/zcf/");
499
+ result.success = true;
500
+ } else {
501
+ result.warnings.push(i18n.t("uninstall:agentsNotFound"));
502
+ result.success = true;
503
+ }
504
+ } catch (error) {
505
+ result.errors.push(`Failed to remove custom agents: ${error.message}`);
506
+ }
507
+ return result;
508
+ }
509
+ /**
510
+ * 4. Remove global memory file (CLAUDE.md)
511
+ */
512
+ async removeClaudeMd() {
513
+ const result = {
514
+ success: false,
515
+ removed: [],
516
+ removedConfigs: [],
517
+ errors: [],
518
+ warnings: []
519
+ };
520
+ try {
521
+ const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
522
+ if (await pathExists(claudeMdPath)) {
523
+ const trashResult = await moveToTrash(claudeMdPath);
524
+ if (!trashResult[0]?.success) {
525
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
526
+ }
527
+ result.removed.push("CLAUDE.md");
528
+ result.success = true;
529
+ } else {
530
+ result.warnings.push(i18n.t("uninstall:claudeMdNotFound"));
531
+ result.success = true;
532
+ }
533
+ } catch (error) {
534
+ result.errors.push(`Failed to remove CLAUDE.md: ${error.message}`);
535
+ }
536
+ return result;
537
+ }
538
+ /**
539
+ * 5. Remove permissions and environment variables
540
+ */
541
+ async removePermissionsAndEnvs() {
542
+ const result = {
543
+ success: false,
544
+ removed: [],
545
+ removedConfigs: [],
546
+ errors: [],
547
+ warnings: []
548
+ };
549
+ try {
550
+ const settingsPath = join(homedir(), ".claude", "settings.json");
551
+ if (await pathExists(settingsPath)) {
552
+ const settings = readJsonConfig(settingsPath) || {};
553
+ let modified = false;
554
+ if (settings.permissions) {
555
+ delete settings.permissions;
556
+ result.removedConfigs.push("permissions configuration");
557
+ modified = true;
558
+ }
559
+ if (settings.env) {
560
+ delete settings.env;
561
+ result.removedConfigs.push("environment variables");
562
+ modified = true;
563
+ }
564
+ if (modified) {
565
+ writeJsonConfig(settingsPath, settings);
566
+ }
567
+ result.success = true;
568
+ } else {
569
+ result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
570
+ result.success = true;
571
+ }
572
+ } catch (error) {
573
+ result.errors.push(`Failed to remove permissions and envs: ${error.message}`);
574
+ }
575
+ return result;
576
+ }
577
+ /**
578
+ * 6. Remove MCP servers from .claude.json (mcpServers field only)
579
+ */
580
+ async removeMcps() {
581
+ const result = {
582
+ success: false,
583
+ removed: [],
584
+ removedConfigs: [],
585
+ errors: [],
586
+ warnings: []
587
+ };
588
+ try {
589
+ const claudeJsonPath = join(homedir(), ".claude.json");
590
+ if (await pathExists(claudeJsonPath)) {
591
+ const config = readJsonConfig(claudeJsonPath) || {};
592
+ if (config.mcpServers) {
593
+ delete config.mcpServers;
594
+ writeJsonConfig(claudeJsonPath, config);
595
+ result.removedConfigs.push("mcpServers from .claude.json");
596
+ }
597
+ result.success = true;
598
+ } else {
599
+ result.warnings.push(i18n.t("uninstall:claudeJsonNotFound"));
600
+ result.success = true;
601
+ }
602
+ } catch (error) {
603
+ result.errors.push(`Failed to remove MCP servers: ${error.message}`);
604
+ }
605
+ return result;
606
+ }
607
+ /**
608
+ * 7. Uninstall Claude Code Router and remove configuration
609
+ */
610
+ async uninstallCcr() {
611
+ const result = {
612
+ success: false,
613
+ removed: [],
614
+ removedConfigs: [],
615
+ errors: [],
616
+ warnings: []
617
+ };
618
+ try {
619
+ const ccrPath = join(homedir(), ".claude-code-router");
620
+ if (await pathExists(ccrPath)) {
621
+ const trashResult = await moveToTrash(ccrPath);
622
+ if (!trashResult[0]?.success) {
623
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
624
+ }
625
+ result.removed.push(".claude-code-router/");
626
+ }
627
+ try {
628
+ await exec$1("npm", ["uninstall", "-g", "@musistudio/claude-code-router"]);
629
+ result.removed.push("@musistudio/claude-code-router package");
630
+ result.success = true;
631
+ } catch (npmError) {
632
+ if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
633
+ result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
634
+ result.success = true;
635
+ } else {
636
+ result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`);
637
+ }
638
+ }
639
+ } catch (error) {
640
+ result.errors.push(`Failed to uninstall CCR: ${error.message}`);
641
+ }
642
+ return result;
643
+ }
644
+ /**
645
+ * 8. Uninstall CCometixLine
646
+ */
647
+ async uninstallCcline() {
648
+ const result = {
649
+ success: false,
650
+ removed: [],
651
+ removedConfigs: [],
652
+ errors: [],
653
+ warnings: []
654
+ };
655
+ try {
656
+ await exec$1("npm", ["uninstall", "-g", "@cometix/ccline"]);
657
+ result.removed.push("@cometix/ccline package");
658
+ result.success = true;
659
+ } catch (error) {
660
+ if (error.message.includes("not found") || error.message.includes("not installed")) {
661
+ result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
662
+ result.success = true;
663
+ } else {
664
+ result.errors.push(`Failed to uninstall CCometixLine: ${error.message}`);
665
+ }
666
+ }
667
+ return result;
668
+ }
669
+ /**
670
+ * 9. Uninstall Claude Code and remove entire .claude.json
671
+ */
672
+ async uninstallClaudeCode() {
673
+ const result = {
674
+ success: false,
675
+ removed: [],
676
+ removedConfigs: [],
677
+ errors: [],
678
+ warnings: []
679
+ };
680
+ try {
681
+ const claudeJsonPath = join(homedir(), ".claude.json");
682
+ if (await pathExists(claudeJsonPath)) {
683
+ const trashResult = await moveToTrash(claudeJsonPath);
684
+ if (!trashResult[0]?.success) {
685
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
686
+ }
687
+ result.removed.push(".claude.json (includes MCP configuration)");
688
+ }
689
+ try {
690
+ const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.br; });
691
+ const success = await uninstallCodeTool("claude-code");
692
+ if (success) {
693
+ result.removed.push("@anthropic-ai/claude-code");
694
+ result.success = true;
695
+ } else {
696
+ result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: "" }));
697
+ }
698
+ } catch (npmError) {
699
+ if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
700
+ result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
701
+ result.success = true;
702
+ } else {
703
+ result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${npmError.message}` }));
704
+ }
705
+ }
706
+ } catch (error) {
707
+ result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${error.message}` }));
708
+ }
709
+ return result;
710
+ }
711
+ /**
712
+ * 10. Remove backup files
713
+ */
714
+ async removeBackups() {
715
+ const result = {
716
+ success: false,
717
+ removed: [],
718
+ removedConfigs: [],
719
+ errors: [],
720
+ warnings: []
721
+ };
722
+ try {
723
+ const backupPath = join(homedir(), ".claude", "backup");
724
+ if (await pathExists(backupPath)) {
725
+ const trashResult = await moveToTrash(backupPath);
726
+ if (!trashResult[0]?.success) {
727
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
728
+ }
729
+ result.removed.push("backup/");
730
+ result.success = true;
731
+ } else {
732
+ result.warnings.push(i18n.t("uninstall:backupsNotFound"));
733
+ result.success = true;
734
+ }
735
+ } catch (error) {
736
+ result.errors.push(`Failed to remove backups: ${error.message}`);
737
+ }
738
+ return result;
739
+ }
740
+ /**
741
+ * 11. Remove ZCF preference configuration
742
+ */
743
+ async removeZcfConfig() {
744
+ const result = {
745
+ success: false,
746
+ removed: [],
747
+ removedConfigs: [],
748
+ errors: [],
749
+ warnings: []
750
+ };
751
+ try {
752
+ const zcfConfigPath = ZCF_CONFIG_FILE;
753
+ const relativeName = zcfConfigPath.replace(homedir(), "~");
754
+ if (await pathExists(zcfConfigPath)) {
755
+ const trashResult = await moveToTrash(zcfConfigPath);
756
+ if (!trashResult[0]?.success) {
757
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
758
+ }
759
+ result.removed.push(relativeName);
760
+ result.success = true;
761
+ } else {
762
+ result.warnings.push(i18n.t("uninstall:zcfConfigNotFound"));
763
+ result.success = true;
764
+ }
765
+ } catch (error) {
766
+ result.errors.push(`Failed to remove ZCF config: ${error.message}`);
767
+ }
768
+ return result;
769
+ }
770
+ /**
771
+ * Complete uninstall - remove all directories and packages
772
+ */
773
+ async completeUninstall() {
774
+ const result = {
775
+ success: true,
776
+ removed: [],
777
+ removedConfigs: [],
778
+ errors: [],
779
+ warnings: []
780
+ };
781
+ try {
782
+ const directoriesToRemove = [
783
+ { path: join(homedir(), ".claude"), name: "~/.claude/" },
784
+ { path: join(homedir(), ".claude.json"), name: "~/.claude.json" },
785
+ { path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" }
786
+ ];
787
+ for (const dir of directoriesToRemove) {
788
+ try {
789
+ if (await pathExists(dir.path)) {
790
+ const trashResult = await moveToTrash(dir.path);
791
+ if (!trashResult[0]?.success) {
792
+ result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`);
793
+ }
794
+ result.removed.push(dir.name);
795
+ }
796
+ } catch (error) {
797
+ result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`);
798
+ }
799
+ }
800
+ const packagesToUninstall = [
801
+ "@musistudio/claude-code-router",
802
+ "@cometix/ccline",
803
+ "@anthropic-ai/claude-code"
804
+ ];
805
+ for (const pkg of packagesToUninstall) {
806
+ try {
807
+ await exec$1("npm", ["uninstall", "-g", pkg]);
808
+ result.removed.push(`${pkg} package`);
809
+ } catch (error) {
810
+ if (error.message.includes("not found") || error.message.includes("not installed")) {
811
+ if (pkg.includes("claude-code-router")) {
812
+ result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
813
+ } else if (pkg.includes("ccline")) {
814
+ result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
815
+ } else {
816
+ result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
817
+ }
818
+ } else {
819
+ result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`);
820
+ }
821
+ }
822
+ }
823
+ } catch (error) {
824
+ result.errors.push(`Complete uninstall failed: ${error.message}`);
825
+ result.success = false;
826
+ }
827
+ return result;
828
+ }
829
+ /**
830
+ * Custom uninstall with conflict resolution
831
+ */
832
+ async customUninstall(selectedItems) {
833
+ const resolvedItems = this.resolveConflicts(selectedItems);
834
+ const results = [];
835
+ for (const item of resolvedItems) {
836
+ try {
837
+ const result = await this.executeUninstallItem(item);
838
+ results.push(result);
839
+ } catch (error) {
840
+ results.push({
841
+ success: false,
842
+ removed: [],
843
+ removedConfigs: [],
844
+ errors: [`Failed to execute ${item}: ${error.message}`],
845
+ warnings: []
846
+ });
847
+ }
848
+ }
849
+ return results;
850
+ }
851
+ /**
852
+ * Resolve conflicts between uninstall items
853
+ */
854
+ resolveConflicts(items) {
855
+ const resolved = [...items];
856
+ for (const [primary, conflicts] of this.conflictResolution) {
857
+ if (resolved.includes(primary)) {
858
+ conflicts.forEach((conflict) => {
859
+ const index = resolved.indexOf(conflict);
860
+ if (index > -1) {
861
+ resolved.splice(index, 1);
862
+ }
863
+ });
864
+ }
865
+ }
866
+ return resolved;
867
+ }
868
+ /**
869
+ * Execute uninstall for a specific item
870
+ */
871
+ async executeUninstallItem(item) {
872
+ switch (item) {
873
+ case "output-styles":
874
+ return await this.removeOutputStyles();
875
+ case "commands":
876
+ return await this.removeCustomCommands();
877
+ case "agents":
878
+ return await this.removeCustomAgents();
879
+ case "claude-md":
880
+ return await this.removeClaudeMd();
881
+ case "permissions-envs":
882
+ return await this.removePermissionsAndEnvs();
883
+ case "mcps":
884
+ return await this.removeMcps();
885
+ case "ccr":
886
+ return await this.uninstallCcr();
887
+ case "ccline":
888
+ return await this.uninstallCcline();
889
+ case "claude-code":
890
+ return await this.uninstallClaudeCode();
891
+ case "backups":
892
+ return await this.removeBackups();
893
+ case "zcf-config":
894
+ return await this.removeZcfConfig();
895
+ default:
896
+ return {
897
+ success: false,
898
+ removed: [],
899
+ removedConfigs: [],
900
+ errors: [`Unknown uninstall item: ${item}`],
901
+ warnings: []
902
+ };
903
+ }
904
+ }
905
+ }
906
+
907
+ async function uninstall(options = {}) {
908
+ try {
909
+ ensureI18nInitialized();
910
+ let codeType;
911
+ if (options.codeType) {
912
+ try {
913
+ codeType = await resolveCodeType$1(options.codeType);
914
+ } catch (error) {
915
+ const errorMessage = error instanceof Error ? error.message : String(error);
916
+ console.error(ansis.red(`${i18n.t("errors:generalError")} ${errorMessage}`));
917
+ const config = readZcfConfig();
918
+ codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
919
+ }
920
+ } else {
921
+ const config = readZcfConfig();
922
+ codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
923
+ }
924
+ const uninstaller = new ZcfUninstaller(options.lang || "en");
925
+ if (codeType === "codex") {
926
+ const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.bq; });
927
+ await runCodexUninstall();
928
+ return;
929
+ }
930
+ if (options.mode && options.mode !== "interactive") {
931
+ if (options.mode === "complete") {
932
+ await executeCompleteUninstall(uninstaller);
933
+ return;
934
+ } else if (options.mode === "custom" && options.items) {
935
+ let items;
936
+ if (typeof options.items === "string") {
937
+ items = options.items.split(",").map((item) => item.trim());
938
+ } else {
939
+ items = options.items;
940
+ }
941
+ await executeCustomUninstall(uninstaller, items);
942
+ return;
943
+ }
944
+ }
945
+ await showInteractiveUninstall(uninstaller);
946
+ } catch (error) {
947
+ if (!handleExitPromptError(error)) {
948
+ handleGeneralError(error);
949
+ }
950
+ }
951
+ }
952
+ async function showInteractiveUninstall(uninstaller) {
953
+ console.log(ansis.cyan.bold(i18n.t("uninstall:title")));
954
+ console.log("");
955
+ const { mainChoice } = await inquirer.prompt({
956
+ type: "list",
957
+ name: "mainChoice",
958
+ message: i18n.t("uninstall:selectMainOption"),
959
+ choices: addNumbersToChoices([
960
+ {
961
+ name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`,
962
+ value: "complete",
963
+ short: i18n.t("uninstall:completeUninstall")
964
+ },
965
+ {
966
+ name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`,
967
+ value: "custom",
968
+ short: i18n.t("uninstall:customUninstall")
969
+ }
970
+ ])
971
+ });
972
+ if (!mainChoice) {
973
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
974
+ return;
975
+ }
976
+ if (mainChoice === "complete") {
977
+ await executeCompleteUninstall(uninstaller);
978
+ } else {
979
+ await showCustomUninstallMenu(uninstaller);
980
+ }
981
+ }
982
+ async function showCustomUninstallMenu(uninstaller) {
983
+ console.log("");
984
+ console.log(ansis.cyan(i18n.t("uninstall:selectCustomItems")));
985
+ const { customItems } = await inquirer.prompt({
986
+ type: "checkbox",
987
+ name: "customItems",
988
+ message: `${i18n.t("uninstall:selectItemsToRemove")} ${i18n.t("common:multiSelectHint")}`,
989
+ choices: [
990
+ {
991
+ name: i18n.t("uninstall:outputStyles"),
992
+ value: "output-styles"
993
+ },
994
+ {
995
+ name: i18n.t("uninstall:commands"),
996
+ value: "commands"
997
+ },
998
+ {
999
+ name: i18n.t("uninstall:agents"),
1000
+ value: "agents"
1001
+ },
1002
+ {
1003
+ name: i18n.t("uninstall:claudeMd"),
1004
+ value: "claude-md"
1005
+ },
1006
+ {
1007
+ name: i18n.t("uninstall:permissionsEnvs"),
1008
+ value: "permissions-envs"
1009
+ },
1010
+ {
1011
+ name: i18n.t("uninstall:mcps"),
1012
+ value: "mcps"
1013
+ },
1014
+ {
1015
+ name: i18n.t("uninstall:ccr"),
1016
+ value: "ccr"
1017
+ },
1018
+ {
1019
+ name: i18n.t("uninstall:ccline"),
1020
+ value: "ccline"
1021
+ },
1022
+ {
1023
+ name: i18n.t("uninstall:claudeCode"),
1024
+ value: "claude-code"
1025
+ },
1026
+ {
1027
+ name: i18n.t("uninstall:backups"),
1028
+ value: "backups"
1029
+ },
1030
+ {
1031
+ name: i18n.t("uninstall:zcfConfig"),
1032
+ value: "zcf-config"
1033
+ }
1034
+ ],
1035
+ validate: (answers) => {
1036
+ if (answers.length === 0) {
1037
+ return i18n.t("uninstall:selectAtLeastOne");
1038
+ }
1039
+ return true;
1040
+ }
1041
+ });
1042
+ if (!customItems || customItems.length === 0) {
1043
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1044
+ return;
1045
+ }
1046
+ await executeCustomUninstall(uninstaller, customItems);
1047
+ }
1048
+ async function executeCompleteUninstall(uninstaller) {
1049
+ console.log("");
1050
+ console.log(ansis.red.bold(i18n.t("uninstall:executingComplete")));
1051
+ console.log(ansis.yellow(i18n.t("uninstall:completeWarning")));
1052
+ const confirm = await promptBoolean({
1053
+ message: i18n.t("uninstall:confirmComplete"),
1054
+ defaultValue: false
1055
+ });
1056
+ if (!confirm) {
1057
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1058
+ return;
1059
+ }
1060
+ console.log("");
1061
+ console.log(ansis.cyan(i18n.t("uninstall:processingComplete")));
1062
+ const result = await uninstaller.completeUninstall();
1063
+ displayUninstallResult("complete", [result]);
1064
+ }
1065
+ async function executeCustomUninstall(uninstaller, items) {
1066
+ console.log("");
1067
+ console.log(ansis.cyan(i18n.t("uninstall:executingCustom")));
1068
+ console.log(ansis.gray(i18n.t("uninstall:selectedItems")));
1069
+ items.forEach((item) => {
1070
+ console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`);
1071
+ });
1072
+ const confirm = await promptBoolean({
1073
+ message: i18n.t("uninstall:confirmCustom"),
1074
+ defaultValue: false
1075
+ });
1076
+ if (!confirm) {
1077
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1078
+ return;
1079
+ }
1080
+ console.log("");
1081
+ console.log(ansis.cyan(i18n.t("uninstall:processingCustom")));
1082
+ const results = await uninstaller.customUninstall(items);
1083
+ displayUninstallResult("custom", results);
1084
+ }
1085
+ function displayUninstallResult(mode, results) {
1086
+ console.log("");
1087
+ console.log(ansis.cyan("\u2500".repeat(50)));
1088
+ let totalSuccess = 0;
1089
+ let totalErrors = 0;
1090
+ let totalWarnings = 0;
1091
+ results.forEach((result) => {
1092
+ if (result.success) {
1093
+ totalSuccess++;
1094
+ }
1095
+ if (result.removed && result.removed.length > 0) {
1096
+ console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`));
1097
+ result.removed.forEach((item) => {
1098
+ console.log(ansis.gray(` \u2022 ${item}`));
1099
+ });
1100
+ }
1101
+ if (result.removedConfigs && result.removedConfigs.length > 0) {
1102
+ console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`));
1103
+ result.removedConfigs.forEach((item) => {
1104
+ console.log(ansis.gray(` \u2022 ${item}`));
1105
+ });
1106
+ }
1107
+ if (result.errors && result.errors.length > 0) {
1108
+ totalErrors += result.errors.length;
1109
+ console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`));
1110
+ result.errors.forEach((error) => {
1111
+ console.log(ansis.red(` \u2022 ${error}`));
1112
+ });
1113
+ }
1114
+ if (result.warnings && result.warnings.length > 0) {
1115
+ totalWarnings += result.warnings.length;
1116
+ console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`));
1117
+ result.warnings.forEach((warning) => {
1118
+ console.log(ansis.yellow(` \u2022 ${warning}`));
1119
+ });
1120
+ }
1121
+ });
1122
+ const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0);
1123
+ const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0);
1124
+ console.log("");
1125
+ console.log(ansis.cyan("\u2500".repeat(50)));
1126
+ if (mode === "complete") {
1127
+ if (totalErrors === 0) {
1128
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:completeSuccess")}`));
1129
+ } else {
1130
+ console.log(ansis.yellow.bold(`\u26A0 ${i18n.t("uninstall:completePartialSuccess")}`));
1131
+ }
1132
+ } else {
1133
+ if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) {
1134
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", {
1135
+ fileCount: totalRemovedFiles,
1136
+ configCount: totalRemovedConfigs
1137
+ })}`));
1138
+ } else if (totalRemovedFiles > 0) {
1139
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", {
1140
+ count: totalRemovedFiles
1141
+ })}`));
1142
+ } else if (totalRemovedConfigs > 0) {
1143
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", {
1144
+ count: totalRemovedConfigs
1145
+ })}`));
1146
+ } else {
1147
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`));
1148
+ }
1149
+ if (totalErrors > 0) {
1150
+ console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errorsCount", { count: totalErrors })}`));
1151
+ }
1152
+ if (totalWarnings > 0) {
1153
+ console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warningsCount", { count: totalWarnings })}`));
1154
+ }
1155
+ }
1156
+ console.log("");
1157
+ }
1158
+
1159
+ function resolveCodeToolType(optionValue, savedValue) {
1160
+ if (optionValue !== void 0) {
1161
+ const resolved = resolveCodeToolType$1(optionValue);
1162
+ if (resolved !== DEFAULT_CODE_TOOL_TYPE || optionValue === DEFAULT_CODE_TOOL_TYPE) {
1163
+ return resolved;
1164
+ }
1165
+ }
1166
+ if (savedValue && isCodeToolType(savedValue)) {
1167
+ return savedValue;
1168
+ }
1169
+ return DEFAULT_CODE_TOOL_TYPE;
1170
+ }
1171
+ async function update(options = {}) {
1172
+ try {
1173
+ if (!options.skipBanner) {
1174
+ displayBanner(i18n.t("cli:banner.updateSubtitle"));
1175
+ }
1176
+ const zcfConfig = readZcfConfig();
1177
+ const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType);
1178
+ options.codeType = codeToolType;
1179
+ if (codeToolType === "codex") {
1180
+ await runCodexUpdate();
1181
+ const newPreferredLang = options.configLang || zcfConfig?.preferredLang;
1182
+ if (newPreferredLang) {
1183
+ updateZcfConfig({
1184
+ version,
1185
+ preferredLang: newPreferredLang,
1186
+ codeToolType
1187
+ });
1188
+ } else {
1189
+ updateZcfConfig({
1190
+ version,
1191
+ codeToolType
1192
+ });
1193
+ }
1194
+ return;
1195
+ }
1196
+ const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.bo; });
1197
+ const configLang = await resolveTemplateLanguage(
1198
+ options.configLang,
1199
+ // Command line option
1200
+ zcfConfig,
1201
+ options.skipPrompt
1202
+ // Non-interactive mode flag
1203
+ );
1204
+ const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig, options.skipPrompt);
1205
+ console.log(ansis.cyan(`
1206
+ ${i18n.t("configuration:updatingPrompts")}
1207
+ `));
1208
+ await updatePromptOnly(aiOutputLang);
1209
+ await selectAndInstallWorkflows(configLang);
1210
+ await checkClaudeCodeVersionAndPrompt(false);
1211
+ updateZcfConfig({
1212
+ version,
1213
+ templateLang: configLang,
1214
+ // 保存模板语言选择
1215
+ aiOutputLang,
1216
+ codeToolType
1217
+ });
1218
+ } catch (error) {
1219
+ if (!handleExitPromptError(error)) {
1220
+ handleGeneralError(error);
1221
+ }
1222
+ }
1223
+ }
1224
+
1225
+ const CODE_TOOL_LABELS = {
1226
+ "claude-code": "Claude Code",
1227
+ "codex": "Codex"
1228
+ };
1229
+ function getCurrentCodeTool() {
1230
+ const config = readZcfConfig();
1231
+ if (config?.codeToolType && isCodeToolType(config.codeToolType)) {
1232
+ return config.codeToolType;
1233
+ }
1234
+ return DEFAULT_CODE_TOOL_TYPE;
1235
+ }
1236
+ function printSeparator() {
1237
+ console.log(`
1238
+ ${ansis.dim("\u2500".repeat(50))}
1239
+ `);
1240
+ }
1241
+ function getCodeToolLabel(codeTool) {
1242
+ return CODE_TOOL_LABELS[codeTool] || codeTool;
1243
+ }
1244
+ async function promptCodeToolSelection(current) {
1245
+ const choices = addNumbersToChoices(Object.entries(CODE_TOOL_LABELS).map(([value, label]) => ({
1246
+ name: label,
1247
+ value,
1248
+ short: label
1249
+ })));
1250
+ const { tool } = await inquirer.prompt({
1251
+ type: "list",
1252
+ name: "tool",
1253
+ message: i18n.t("menu:switchCodeToolPrompt"),
1254
+ default: current,
1255
+ choices
1256
+ });
1257
+ if (!tool) {
1258
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1259
+ return null;
1260
+ }
1261
+ return tool;
1262
+ }
1263
+ async function handleCodeToolSwitch(current) {
1264
+ const newTool = await promptCodeToolSelection(current);
1265
+ if (!newTool || newTool === current) {
1266
+ return false;
1267
+ }
1268
+ updateZcfConfig({ codeToolType: newTool });
1269
+ console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(newTool) })}`));
1270
+ return true;
1271
+ }
1272
+ function printOtherToolsSection() {
1273
+ console.log(` --------- ${i18n.t("menu:menuSections.otherTools")} ----------`);
1274
+ console.log(
1275
+ ` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}`
1276
+ );
1277
+ console.log(
1278
+ ` ${ansis.cyan("U.")} ${i18n.t("menu:menuOptions.ccusage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccusage")}`)}`
1279
+ );
1280
+ console.log(
1281
+ ` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}`
1282
+ );
1283
+ console.log("");
1284
+ }
1285
+ function printZcfSection(options) {
1286
+ console.log(" ------------ ZCF ------------");
1287
+ console.log(
1288
+ ` ${ansis.cyan("0.")} ${i18n.t("menu:menuOptions.changeLanguage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.changeLanguage")}`)}`
1289
+ );
1290
+ console.log(
1291
+ ` ${ansis.cyan("S.")} ${i18n.t("menu:menuOptions.switchCodeTool")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.switchCodeTool")}`)}`
1292
+ );
1293
+ console.log(
1294
+ ` ${ansis.cyan("-.")} ${options.uninstallOption} ${ansis.gray(`- ${options.uninstallDescription}`)}`
1295
+ );
1296
+ console.log(
1297
+ ` ${ansis.cyan("+.")} ${options.updateOption} ${ansis.gray(`- ${options.updateDescription}`)}`
1298
+ );
1299
+ console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.t("menu:menuOptions.exit"))}`);
1300
+ console.log("");
1301
+ }
1302
+ async function showClaudeCodeMenu() {
1303
+ console.log(ansis.cyan(i18n.t("menu:selectFunction")));
1304
+ console.log(" -------- Claude Code --------");
1305
+ console.log(
1306
+ ` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.fullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.fullInit")}`)}`
1307
+ );
1308
+ console.log(
1309
+ ` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.importWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.importWorkflow")}`)}`
1310
+ );
1311
+ console.log(
1312
+ ` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.configureApiOrCcr")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureApiOrCcr")}`)}`
1313
+ );
1314
+ console.log(
1315
+ ` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.configureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureMcp")}`)}`
1316
+ );
1317
+ console.log(
1318
+ ` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.configureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureModel")}`)}`
1319
+ );
1320
+ console.log(
1321
+ ` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.configureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureAiMemory")}`)}`
1322
+ );
1323
+ console.log(
1324
+ ` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`)}`
1325
+ );
1326
+ console.log("");
1327
+ printOtherToolsSection();
1328
+ printZcfSection({
1329
+ uninstallOption: i18n.t("menu:menuOptions.uninstall"),
1330
+ uninstallDescription: i18n.t("menu:menuDescriptions.uninstall"),
1331
+ updateOption: i18n.t("menu:menuOptions.checkUpdates"),
1332
+ updateDescription: i18n.t("menu:menuDescriptions.checkUpdates")
1333
+ });
1334
+ const { choice } = await inquirer.prompt({
1335
+ type: "input",
1336
+ name: "choice",
1337
+ message: i18n.t("common:enterChoice"),
1338
+ validate: (value) => {
1339
+ const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "s", "S", "q", "Q"];
1340
+ return valid.includes(value) || i18n.t("common:invalidChoice");
1341
+ }
1342
+ });
1343
+ if (!choice) {
1344
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1345
+ return "exit";
1346
+ }
1347
+ const normalized = choice.toLowerCase();
1348
+ switch (normalized) {
1349
+ case "1":
1350
+ await init({ skipBanner: true });
1351
+ break;
1352
+ case "2":
1353
+ await update({ skipBanner: true });
1354
+ break;
1355
+ case "3":
1356
+ await configureApiFeature();
1357
+ break;
1358
+ case "4":
1359
+ await configureMcpFeature();
1360
+ break;
1361
+ case "5":
1362
+ await configureDefaultModelFeature();
1363
+ break;
1364
+ case "6":
1365
+ await configureAiMemoryFeature();
1366
+ break;
1367
+ case "7":
1368
+ await configureEnvPermissionFeature();
1369
+ break;
1370
+ case "r":
1371
+ await runCcrMenuFeature();
1372
+ printSeparator();
1373
+ return void 0;
1374
+ case "u":
1375
+ await runCcusageFeature();
1376
+ printSeparator();
1377
+ return void 0;
1378
+ case "l":
1379
+ await runCometixMenuFeature();
1380
+ printSeparator();
1381
+ return void 0;
1382
+ case "0": {
1383
+ const currentLang = i18n.language;
1384
+ await changeScriptLanguageFeature(currentLang);
1385
+ printSeparator();
1386
+ return void 0;
1387
+ }
1388
+ case "-":
1389
+ await uninstall();
1390
+ printSeparator();
1391
+ return void 0;
1392
+ case "+":
1393
+ await checkUpdates();
1394
+ printSeparator();
1395
+ return void 0;
1396
+ case "s": {
1397
+ const switched = await handleCodeToolSwitch("claude-code");
1398
+ if (switched) {
1399
+ return "switch";
1400
+ }
1401
+ printSeparator();
1402
+ return void 0;
1403
+ }
1404
+ case "q":
1405
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
1406
+ return "exit";
1407
+ default:
1408
+ return void 0;
1409
+ }
1410
+ printSeparator();
1411
+ const shouldContinue = await promptBoolean({
1412
+ message: i18n.t("common:returnToMenu"),
1413
+ defaultValue: true
1414
+ });
1415
+ if (!shouldContinue) {
1416
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
1417
+ return "exit";
1418
+ }
1419
+ return void 0;
1420
+ }
1421
+ async function showCodexMenu() {
1422
+ console.log(ansis.cyan(i18n.t("menu:selectFunction")));
1423
+ console.log(" -------- Codex --------");
1424
+ console.log(
1425
+ ` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}`
1426
+ );
1427
+ console.log(
1428
+ ` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}`
1429
+ );
1430
+ console.log(
1431
+ ` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}`
1432
+ );
1433
+ console.log(
1434
+ ` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}`
1435
+ );
1436
+ console.log(
1437
+ ` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}`
1438
+ );
1439
+ console.log(
1440
+ ` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}`
1441
+ );
1442
+ console.log("");
1443
+ printZcfSection({
1444
+ uninstallOption: i18n.t("menu:menuOptions.codexUninstall"),
1445
+ uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"),
1446
+ updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"),
1447
+ updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates")
1448
+ });
1449
+ const { choice } = await inquirer.prompt({
1450
+ type: "input",
1451
+ name: "choice",
1452
+ message: i18n.t("common:enterChoice"),
1453
+ validate: (value) => {
1454
+ const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"];
1455
+ return valid.includes(value) || i18n.t("common:invalidChoice");
1456
+ }
1457
+ });
1458
+ if (!choice) {
1459
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1460
+ return "exit";
1461
+ }
1462
+ const normalized = choice.toLowerCase();
1463
+ switch (normalized) {
1464
+ case "1":
1465
+ await runCodexFullInit();
1466
+ break;
1467
+ case "2":
1468
+ await runCodexWorkflowImportWithLanguageSelection();
1469
+ break;
1470
+ case "3":
1471
+ await configureCodexApi();
1472
+ break;
1473
+ case "4":
1474
+ await configureCodexMcp();
1475
+ break;
1476
+ case "5":
1477
+ await configureCodexDefaultModelFeature();
1478
+ break;
1479
+ case "6":
1480
+ await configureCodexAiMemoryFeature();
1481
+ break;
1482
+ case "0": {
1483
+ const currentLang = i18n.language;
1484
+ await changeScriptLanguageFeature(currentLang);
1485
+ printSeparator();
1486
+ return void 0;
1487
+ }
1488
+ case "-":
1489
+ await runCodexUninstall();
1490
+ printSeparator();
1491
+ return void 0;
1492
+ case "+":
1493
+ await runCodexUpdate();
1494
+ printSeparator();
1495
+ return void 0;
1496
+ case "s": {
1497
+ const switched = await handleCodeToolSwitch("codex");
1498
+ if (switched) {
1499
+ return "switch";
1500
+ }
1501
+ printSeparator();
1502
+ return void 0;
1503
+ }
1504
+ case "q":
1505
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
1506
+ return "exit";
1507
+ default:
1508
+ return void 0;
1509
+ }
1510
+ printSeparator();
1511
+ const shouldContinue = await promptBoolean({
1512
+ message: i18n.t("common:returnToMenu"),
1513
+ defaultValue: true
1514
+ });
1515
+ if (!shouldContinue) {
1516
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
1517
+ return "exit";
1518
+ }
1519
+ return void 0;
1520
+ }
1521
+ async function showMainMenu(options = {}) {
1522
+ try {
1523
+ if (options.codeType) {
1524
+ try {
1525
+ const resolvedType = await resolveCodeType$1(options.codeType);
1526
+ const currentType = getCurrentCodeTool();
1527
+ if (resolvedType !== currentType) {
1528
+ updateZcfConfig({ codeToolType: resolvedType });
1529
+ console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(resolvedType) })}`));
1530
+ }
1531
+ } catch (err) {
1532
+ const errorMessage = err instanceof Error ? err.message : String(err);
1533
+ console.error(ansis.yellow(errorMessage));
1534
+ }
1535
+ }
1536
+ let exitMenu = false;
1537
+ while (!exitMenu) {
1538
+ const codeTool = getCurrentCodeTool();
1539
+ displayBannerWithInfo(CODE_TOOL_BANNERS[codeTool] || "ZCF");
1540
+ const result = codeTool === "codex" ? await showCodexMenu() : await showClaudeCodeMenu();
1541
+ if (result === "exit") {
1542
+ exitMenu = true;
1543
+ } else if (result === "switch") {
1544
+ continue;
1545
+ }
1546
+ }
1547
+ } catch (error) {
1548
+ if (!handleExitPromptError(error)) {
1549
+ handleGeneralError(error);
1550
+ }
1551
+ }
1552
+ }
1553
+
1554
+ async function ccr(options = {}) {
1555
+ try {
1556
+ if (!options.skipBanner) {
1557
+ displayBannerWithInfo();
1558
+ }
1559
+ const continueInCcr = await showCcrMenu();
1560
+ if (!continueInCcr && !options.skipBanner) {
1561
+ await showMainMenu();
1562
+ }
1563
+ } catch (error) {
1564
+ if (!handleExitPromptError(error)) {
1565
+ handleGeneralError(error);
1566
+ }
1567
+ }
1568
+ }
1569
+
1570
+ async function configSwitchCommand(options) {
1571
+ try {
1572
+ ensureI18nInitialized();
1573
+ if (options.list) {
1574
+ await handleList(options.codeType);
1575
+ return;
1576
+ }
1577
+ if (options.target) {
1578
+ const resolvedCodeType = resolveCodeType(options.codeType);
1579
+ await handleDirectSwitch(resolvedCodeType, options.target);
1580
+ return;
1581
+ }
1582
+ await handleInteractiveSwitch(options.codeType);
1583
+ } catch (error) {
1584
+ if (process.env.NODE_ENV === "test" || process.env.VITEST) {
1585
+ throw error;
1586
+ }
1587
+ handleGeneralError(error);
1588
+ }
1589
+ }
1590
+ function resolveCodeType(codeType) {
1591
+ if (codeType !== void 0) {
1592
+ const resolved = resolveCodeToolType$1(codeType);
1593
+ return resolved;
1594
+ }
1595
+ const zcfConfig = readZcfConfig();
1596
+ if (zcfConfig?.codeToolType && isCodeToolType(zcfConfig.codeToolType)) {
1597
+ return zcfConfig.codeToolType;
1598
+ }
1599
+ return DEFAULT_CODE_TOOL_TYPE;
1600
+ }
1601
+ async function handleList(codeType) {
1602
+ const targetCodeType = resolveCodeType(codeType);
1603
+ if (targetCodeType === "claude-code") {
1604
+ await listClaudeCodeProfiles();
1605
+ } else if (targetCodeType === "codex") {
1606
+ await listCodexProvidersWithDisplay();
1607
+ }
1608
+ }
1609
+ async function listCodexProvidersWithDisplay() {
1610
+ const providers = await listCodexProviders();
1611
+ const existingConfig = readCodexConfig();
1612
+ const currentProvider = existingConfig?.modelProvider;
1613
+ const isCommented = existingConfig?.modelProviderCommented;
1614
+ if (!providers || providers.length === 0) {
1615
+ console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
1616
+ return;
1617
+ }
1618
+ console.log(ansis.bold(i18n.t("codex:listProvidersTitle")));
1619
+ console.log();
1620
+ if (currentProvider && !isCommented) {
1621
+ console.log(ansis.cyan(i18n.t("codex:currentProvider", { provider: currentProvider })));
1622
+ console.log();
1623
+ }
1624
+ providers.forEach((provider) => {
1625
+ const isCurrent = currentProvider === provider.id && !isCommented;
1626
+ const status = isCurrent ? ansis.green("\u25CF ") : " ";
1627
+ const current = isCurrent ? ansis.yellow(` (${i18n.t("common:current")})`) : "";
1628
+ console.log(`${status}${ansis.white(provider.name)}${current}`);
1629
+ console.log(` ${ansis.cyan(`ID: ${provider.id}`)} ${ansis.gray(`(${provider.baseUrl})`)}`);
1630
+ if (provider.tempEnvKey) {
1631
+ console.log(` ${ansis.gray(`Env: ${provider.tempEnvKey}`)}`);
1632
+ }
1633
+ console.log();
1634
+ });
1635
+ }
1636
+ async function listClaudeCodeProfiles() {
1637
+ const config = ClaudeCodeConfigManager.readConfig();
1638
+ if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
1639
+ console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
1640
+ return;
1641
+ }
1642
+ console.log(ansis.bold(i18n.t("multi-config:availableClaudeCodeProfiles")));
1643
+ console.log();
1644
+ const currentProfileId = config.currentProfileId;
1645
+ Object.values(config.profiles).forEach((profile) => {
1646
+ const isCurrent = profile.id === currentProfileId;
1647
+ const status = isCurrent ? ansis.green("\u25CF ") : " ";
1648
+ const current = isCurrent ? ansis.yellow(i18n.t("common:current")) : "";
1649
+ console.log(`${status}${ansis.white(profile.name)}${current}`);
1650
+ console.log(` ${ansis.cyan(`ID: ${profile.id}`)} ${ansis.gray(`(${profile.authType})`)}`);
1651
+ console.log();
1652
+ });
1653
+ }
1654
+ async function handleDirectSwitch(codeType, target) {
1655
+ const resolvedCodeType = resolveCodeType(codeType);
1656
+ if (resolvedCodeType === "claude-code") {
1657
+ await handleClaudeCodeDirectSwitch(target);
1658
+ } else if (resolvedCodeType === "codex") {
1659
+ await switchCodexProvider(target);
1660
+ }
1661
+ }
1662
+ async function handleClaudeCodeDirectSwitch(target) {
1663
+ if (target === "official") {
1664
+ const result = await ClaudeCodeConfigManager.switchToOfficial();
1665
+ if (result.success) {
1666
+ try {
1667
+ await ClaudeCodeConfigManager.applyProfileSettings(null);
1668
+ console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToOfficial")));
1669
+ } catch (error) {
1670
+ const reason = error instanceof Error ? error.message : String(error);
1671
+ console.log(ansis.red(reason));
1672
+ }
1673
+ } else {
1674
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
1675
+ }
1676
+ } else if (target === "ccr") {
1677
+ const result = await ClaudeCodeConfigManager.switchToCcr();
1678
+ if (result.success) {
1679
+ try {
1680
+ const profile = ClaudeCodeConfigManager.getProfileById("ccr-proxy");
1681
+ await ClaudeCodeConfigManager.applyProfileSettings(profile);
1682
+ console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToCcr")));
1683
+ } catch (error) {
1684
+ const reason = error instanceof Error ? error.message : String(error);
1685
+ console.log(ansis.red(reason));
1686
+ }
1687
+ } else {
1688
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
1689
+ }
1690
+ } else {
1691
+ const config = ClaudeCodeConfigManager.readConfig();
1692
+ if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
1693
+ console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
1694
+ return;
1695
+ }
1696
+ const normalizedTarget = target.trim();
1697
+ let resolvedId = normalizedTarget;
1698
+ let resolvedProfile = config.profiles[normalizedTarget];
1699
+ if (!resolvedProfile) {
1700
+ const match = Object.entries(config.profiles).find(([, profile]) => profile.name === normalizedTarget);
1701
+ if (match) {
1702
+ resolvedId = match[0];
1703
+ resolvedProfile = match[1];
1704
+ }
1705
+ }
1706
+ if (!resolvedProfile) {
1707
+ console.log(ansis.red(i18n.t("multi-config:profileNameNotFound", { name: target })));
1708
+ return;
1709
+ }
1710
+ const result = await ClaudeCodeConfigManager.switchProfile(resolvedId);
1711
+ if (result.success) {
1712
+ try {
1713
+ await ClaudeCodeConfigManager.applyProfileSettings({ ...resolvedProfile, id: resolvedId });
1714
+ console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToProfile", { name: resolvedProfile.name })));
1715
+ } catch (error) {
1716
+ const reason = error instanceof Error ? error.message : String(error);
1717
+ console.log(ansis.red(reason));
1718
+ }
1719
+ } else {
1720
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
1721
+ }
1722
+ }
1723
+ }
1724
+ async function handleInteractiveSwitch(codeType) {
1725
+ const resolvedCodeType = resolveCodeType(codeType);
1726
+ if (resolvedCodeType === "claude-code") {
1727
+ await handleClaudeCodeInteractiveSwitch();
1728
+ } else if (resolvedCodeType === "codex") {
1729
+ await handleCodexInteractiveSwitch();
1730
+ }
1731
+ }
1732
+ async function handleClaudeCodeInteractiveSwitch() {
1733
+ const config = ClaudeCodeConfigManager.readConfig();
1734
+ if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
1735
+ console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
1736
+ return;
1737
+ }
1738
+ const currentProfileId = config.currentProfileId;
1739
+ const createClaudeCodeChoices = (profiles, currentProfileId2) => {
1740
+ const choices2 = [];
1741
+ const isOfficialMode = !currentProfileId2 || currentProfileId2 === "official";
1742
+ choices2.push({
1743
+ name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("codex:useOfficialLogin")}`,
1744
+ value: "official"
1745
+ });
1746
+ const isCcrMode = currentProfileId2 === "ccr-proxy";
1747
+ choices2.push({
1748
+ name: isCcrMode ? `${ansis.green("\u25CF ")}${i18n.t("multi-config:ccrProxyOption")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("multi-config:ccrProxyOption")}`,
1749
+ value: "ccr"
1750
+ });
1751
+ Object.values(profiles).filter((profile) => profile.id !== "ccr-proxy").forEach((profile) => {
1752
+ const isCurrent = profile.id === currentProfileId2;
1753
+ choices2.push({
1754
+ name: isCurrent ? `${ansis.green("\u25CF ")}${profile.name} ${ansis.yellow("(current)")}` : ` ${profile.name}`,
1755
+ value: profile.id
1756
+ });
1757
+ });
1758
+ return choices2;
1759
+ };
1760
+ const choices = createClaudeCodeChoices(config.profiles, currentProfileId);
1761
+ try {
1762
+ const { selectedConfig } = await inquirer.prompt([{
1763
+ type: "list",
1764
+ name: "selectedConfig",
1765
+ message: i18n.t("multi-config:selectClaudeCodeConfiguration"),
1766
+ choices: addNumbersToChoices(choices)
1767
+ }]);
1768
+ if (!selectedConfig) {
1769
+ console.log(ansis.yellow(i18n.t("multi-config:cancelled")));
1770
+ return;
1771
+ }
1772
+ await handleClaudeCodeDirectSwitch(selectedConfig);
1773
+ } catch (error) {
1774
+ if (error.name === "ExitPromptError") {
1775
+ console.log(ansis.cyan(`
1776
+ ${i18n.t("common:goodbye")}`));
1777
+ return;
1778
+ }
1779
+ throw error;
1780
+ }
1781
+ }
1782
+ async function handleCodexInteractiveSwitch() {
1783
+ const providers = await listCodexProviders();
1784
+ if (!providers || providers.length === 0) {
1785
+ console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
1786
+ return;
1787
+ }
1788
+ const existingConfig = readCodexConfig();
1789
+ const currentProvider = existingConfig?.modelProvider;
1790
+ const isCommented = existingConfig?.modelProviderCommented;
1791
+ const createApiConfigChoices = (providers2, currentProvider2, isCommented2) => {
1792
+ const choices2 = [];
1793
+ const isOfficialMode = !currentProvider2 || isCommented2;
1794
+ choices2.push({
1795
+ name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
1796
+ value: "official"
1797
+ });
1798
+ providers2.forEach((provider) => {
1799
+ const isCurrent = currentProvider2 === provider.id && !isCommented2;
1800
+ choices2.push({
1801
+ name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
1802
+ value: provider.id
1803
+ });
1804
+ });
1805
+ return choices2;
1806
+ };
1807
+ const choices = createApiConfigChoices(providers, currentProvider, isCommented);
1808
+ try {
1809
+ const { selectedConfig } = await inquirer.prompt([{
1810
+ type: "list",
1811
+ name: "selectedConfig",
1812
+ message: i18n.t("codex:apiConfigSwitchPrompt"),
1813
+ choices: addNumbersToChoices(choices)
1814
+ }]);
1815
+ if (!selectedConfig) {
1816
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1817
+ return;
1818
+ }
1819
+ let success = false;
1820
+ if (selectedConfig === "official") {
1821
+ success = await switchToOfficialLogin();
1822
+ } else {
1823
+ success = await switchToProvider(selectedConfig);
1824
+ }
1825
+ if (!success) {
1826
+ console.log(ansis.red(i18n.t("common:operationFailed")));
1827
+ }
1828
+ } catch (error) {
1829
+ if (error.name === "ExitPromptError") {
1830
+ console.log(ansis.cyan(`
1831
+ ${i18n.t("common:goodbye")}`));
1832
+ return;
1833
+ }
1834
+ throw error;
1835
+ }
1836
+ }
1837
+
1838
+ const configSwitch = {
1839
+ __proto__: null,
1840
+ configSwitchCommand: configSwitchCommand
1841
+ };
1842
+
1843
+ async function resolveAndSwitchLanguage(lang, options, skipPrompt = false) {
1844
+ const zcfConfig = await readZcfConfigAsync();
1845
+ const targetLang = options?.allLang || lang || options?.lang || zcfConfig?.preferredLang || (skipPrompt ? "en" : await selectScriptLanguage());
1846
+ if (i18n.isInitialized && i18n.language !== targetLang) {
1847
+ await changeLanguage(targetLang);
1848
+ }
1849
+ return targetLang;
1850
+ }
1851
+ async function withLanguageResolution(action, skipPrompt = false) {
1852
+ return async (...args) => {
1853
+ const options = args[0];
1854
+ const languageOptions = extractLanguageOptions(options);
1855
+ await resolveAndSwitchLanguage(void 0, languageOptions, skipPrompt || languageOptions.skipPrompt);
1856
+ return await action(...args);
1857
+ };
1858
+ }
1859
+ function extractLanguageOptions(options) {
1860
+ if (!options || typeof options !== "object" || options === null) {
1861
+ return {};
1862
+ }
1863
+ const obj = options;
1864
+ return {
1865
+ lang: typeof obj.lang === "string" ? obj.lang : void 0,
1866
+ allLang: typeof obj.allLang === "string" ? obj.allLang : void 0,
1867
+ skipPrompt: typeof obj.skipPrompt === "boolean" ? obj.skipPrompt : void 0
1868
+ };
1869
+ }
1870
+ function customizeHelp(sections) {
1871
+ sections.unshift({
1872
+ title: "",
1873
+ body: ansis.cyan.bold(`ZCF - Zero-Config Code Flow v${version}`)
1874
+ });
1875
+ sections.push({
1876
+ title: ansis.yellow(i18n.t("cli:help.commands")),
1877
+ body: [
1878
+ ` ${ansis.cyan("zcf")} ${i18n.t("cli:help.commandDescriptions.showInteractiveMenuDefault")}`,
1879
+ ` ${ansis.cyan("zcf init")} | ${ansis.cyan(
1880
+ "i"
1881
+ )} ${i18n.t("cli:help.commandDescriptions.initClaudeCodeConfig")}`,
1882
+ ` ${ansis.cyan("zcf update")} | ${ansis.cyan("u")} ${i18n.t("cli:help.commandDescriptions.updateWorkflowFiles")}`,
1883
+ ` ${ansis.cyan("zcf ccr")} ${i18n.t("cli:help.commandDescriptions.configureCcrProxy")}`,
1884
+ ` ${ansis.cyan("zcf ccu")} [args] ${i18n.t("cli:help.commandDescriptions.claudeCodeUsageAnalysis")}`,
1885
+ ` ${ansis.cyan("zcf uninstall")} ${i18n.t("cli:help.commandDescriptions.uninstallConfigurations")}`,
1886
+ ` ${ansis.cyan("zcf check-updates")} ${i18n.t("cli:help.commandDescriptions.checkUpdateVersions")}`,
1887
+ "",
1888
+ ansis.gray(` ${i18n.t("cli:help.shortcuts")}`),
1889
+ ` ${ansis.cyan("zcf i")} ${i18n.t("cli:help.shortcutDescriptions.quickInit")}`,
1890
+ ` ${ansis.cyan("zcf u")} ${i18n.t("cli:help.shortcutDescriptions.quickUpdate")}`,
1891
+ ` ${ansis.cyan("zcf check")} ${i18n.t("cli:help.shortcutDescriptions.quickCheckUpdates")}`
1892
+ ].join("\n")
1893
+ });
1894
+ sections.push({
1895
+ title: ansis.yellow(i18n.t("cli:help.options")),
1896
+ body: [
1897
+ ` ${ansis.green("--lang, -l")} <lang> ${i18n.t("cli:help.optionDescriptions.displayLanguage")} (zh-CN, en)`,
1898
+ ` ${ansis.green("--config-lang, -c")} <lang> ${i18n.t("cli:help.optionDescriptions.configurationLanguage")} (zh-CN, en)`,
1899
+ ` ${ansis.green("--force, -f")} ${i18n.t("cli:help.optionDescriptions.forceOverwrite")}`,
1900
+ ` ${ansis.green("--help, -h")} ${i18n.t("cli:help.optionDescriptions.displayHelp")}`,
1901
+ ` ${ansis.green("--version, -v")} ${i18n.t("cli:help.optionDescriptions.displayVersion")}`,
1902
+ "",
1903
+ ansis.gray(` ${i18n.t("cli:help.nonInteractiveMode")}`),
1904
+ ` ${ansis.green("--skip-prompt, -s")} ${i18n.t("cli:help.optionDescriptions.skipAllPrompts")}`,
1905
+ ` ${ansis.green("--api-type, -t")} <type> ${i18n.t("cli:help.optionDescriptions.apiType")} (auth_token, api_key, ccr_proxy, skip)`,
1906
+ ` ${ansis.green("--api-key, -k")} <key> ${i18n.t("cli:help.optionDescriptions.apiKey")}`,
1907
+ ` ${ansis.green("--api-url, -u")} <url> ${i18n.t("cli:help.optionDescriptions.customApiUrl")}`,
1908
+ ` ${ansis.green("--api-model, -M")} <model> ${i18n.t("cli:help.optionDescriptions.apiModel")} (e.g., claude-sonnet-4-5)`,
1909
+ ` ${ansis.green("--api-haiku-model, -H")} <model> ${i18n.t("cli:help.optionDescriptions.apiHaikuModel")} (e.g., claude-haiku-4-5)`,
1910
+ ` ${ansis.green("--api-sonnet-model, -S")} <model> ${i18n.t("cli:help.optionDescriptions.apiSonnetModel")} (e.g., claude-sonnet-4-5)`,
1911
+ ` ${ansis.green("--api-opus-model, -O")} <model> ${i18n.t("cli:help.optionDescriptions.apiOpusModel")} (e.g., claude-opus-4-5)`,
1912
+ ` ${ansis.green("--ai-output-lang, -a")} <lang> ${i18n.t("cli:help.optionDescriptions.aiOutputLanguage")}`,
1913
+ ` ${ansis.green("--all-lang, -g")} <lang> ${i18n.t("cli:help.optionDescriptions.setAllLanguageParams")}`,
1914
+ ` ${ansis.green("--config-action, -r")} <action> ${i18n.t("cli:help.optionDescriptions.configHandling")} (${i18n.t("cli:help.defaults.prefix")} backup)`,
1915
+ ` ${ansis.green("--mcp-services, -m")} <list> ${i18n.t("cli:help.optionDescriptions.mcpServices")} (${i18n.t("cli:help.defaults.prefix")} all non-key services)`,
1916
+ ` ${ansis.green("--workflows, -w")} <list> ${i18n.t("cli:help.optionDescriptions.workflows")} (${i18n.t("cli:help.defaults.prefix")} all workflows)`,
1917
+ ` ${ansis.green("--output-styles, -o")} <styles> ${i18n.t("cli:help.optionDescriptions.outputStyles")} (${i18n.t("cli:help.defaults.prefix")} all custom styles)`,
1918
+ ` ${ansis.green("--default-output-style, -d")} <style> ${i18n.t("cli:help.optionDescriptions.defaultOutputStyle")} (${i18n.t("cli:help.defaults.prefix")} engineer-professional)`,
1919
+ ` ${ansis.green("--code-type, -T")} <type> ${i18n.t("cli:help.optionDescriptions.codeToolType")} (claude-code, codex, cc=claude-code, cx=codex)`,
1920
+ ` ${ansis.green("--install-cometix-line, -x")} <value> ${i18n.t("cli:help.optionDescriptions.installStatuslineTool")} (${i18n.t("cli:help.defaults.prefix")} true)`
1921
+ ].join("\n")
1922
+ });
1923
+ sections.push({
1924
+ title: ansis.yellow(i18n.t("cli:help.examples")),
1925
+ body: [
1926
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.showInteractiveMenu")}`),
1927
+ ` ${ansis.cyan("npx @benbenwu/zcf")}`,
1928
+ "",
1929
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.runFullInitialization")}`),
1930
+ ` ${ansis.cyan("npx @benbenwu/zcf init")}`,
1931
+ ` ${ansis.cyan("npx @benbenwu/zcf i")}`,
1932
+ "",
1933
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.updateWorkflowFilesOnly")}`),
1934
+ ` ${ansis.cyan("npx @benbenwu/zcf u")}`,
1935
+ "",
1936
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.configureClaudeCodeRouter")}`),
1937
+ ` ${ansis.cyan("npx @benbenwu/zcf ccr")}`,
1938
+ "",
1939
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.runClaudeCodeUsageAnalysis")}`),
1940
+ ` ${ansis.cyan("npx @benbenwu/zcf ccu")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.dailyUsage")}`)}`,
1941
+ ` ${ansis.cyan("npx @benbenwu/zcf ccu monthly --json")}`,
1942
+ "",
1943
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.uninstallConfigurations")}`),
1944
+ ` ${ansis.cyan("npx @benbenwu/zcf uninstall")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.interactiveUninstall")}`)}`,
1945
+ "",
1946
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkAndUpdateTools")}`),
1947
+ ` ${ansis.cyan("npx @benbenwu/zcf check-updates")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.updateTools")}`)}`,
1948
+ ` ${ansis.cyan("npx @benbenwu/zcf check")}`,
1949
+ "",
1950
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkClaudeCode")}`),
1951
+ ` ${ansis.cyan("npx @benbenwu/zcf check --code-type claude-code")}`,
1952
+ ` ${ansis.cyan("npx @benbenwu/zcf check -T cc")}`,
1953
+ "",
1954
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkCodex")}`),
1955
+ ` ${ansis.cyan("npx @benbenwu/zcf check --code-type codex")}`,
1956
+ ` ${ansis.cyan("npx @benbenwu/zcf check -T cx")}`,
1957
+ "",
1958
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.nonInteractiveModeCicd")}`),
1959
+ ` ${ansis.cyan('npx @benbenwu/zcf i --skip-prompt --api-type api_key --api-key "sk-ant-..."')}`,
1960
+ ` ${ansis.cyan('npx @benbenwu/zcf i --skip-prompt --all-lang zh-CN --api-type api_key --api-key "key"')}`,
1961
+ ` ${ansis.cyan("npx @benbenwu/zcf i --skip-prompt --api-type ccr_proxy")}`,
1962
+ ""
1963
+ ].join("\n")
1964
+ });
1965
+ return sections;
1966
+ }
1967
+ async function setupCommands(cli) {
1968
+ try {
1969
+ const zcfConfig = await readZcfConfigAsync();
1970
+ const defaultLang = zcfConfig?.preferredLang || "en";
1971
+ await initI18n(defaultLang);
1972
+ } catch {
1973
+ }
1974
+ cli.command("", "Show interactive menu (default)").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").action(await withLanguageResolution(async (options) => {
1975
+ await showMainMenu({ codeType: options.codeType });
1976
+ }));
1977
+ cli.command("init", "Initialize Claude Code configuration").alias("i").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--ai-output-lang, -a <lang>", "AI output language").option("--force, -f", "Force overwrite existing configuration").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").option("--config-action, -r <action>", `Config handling (new/backup/merge/docs-only/skip), ${i18n.t("cli:help.defaults.prefix")} backup`).option("--api-type, -t <type>", "API type (auth_token/api_key/ccr_proxy/skip)").option("--api-key, -k <key>", "API key (used for both API key and auth token types)").option("--api-url, -u <url>", "Custom API URL").option("--api-model, -M <model>", "Primary API model (e.g., claude-sonnet-4-5)").option("--api-haiku-model, -H <model>", "Default Haiku model (e.g., claude-haiku-4-5)").option("--api-sonnet-model, -S <model>", "Default Sonnet model (e.g., claude-sonnet-4-5)").option("--api-opus-model, -O <model>", "Default Opus model (e.g., claude-opus-4-5)").option("--provider, -p <provider>", "API provider preset (302ai, glm, minimax, kimi, custom)").option("--mcp-services, -m <services>", `Comma-separated MCP services to install (context7,mcp-deepwiki,Playwright,exa), "skip" to skip all, "all" for all non-key services, ${i18n.t("cli:help.defaults.prefix")} all`).option("--workflows, -w <workflows>", `Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, ${i18n.t("cli:help.defaults.prefix")} all`).option("--output-styles, -o <styles>", `Comma-separated output styles (engineer-professional,nekomata-engineer,laowang-engineer,default,explanatory,learning), "skip" to skip all, "all" for all custom styles, ${i18n.t("cli:help.defaults.prefix")} all`).option("--default-output-style, -d <style>", `Default output style, ${i18n.t("cli:help.defaults.prefix")} engineer-professional`).option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--install-cometix-line, -x <value>", `Install CCometixLine statusline tool (true/false), ${i18n.t("cli:help.defaults.prefix")} true`).option("--api-configs <configs>", "API configurations as JSON string for multiple profiles").option("--api-configs-file <file>", "Path to JSON file containing API configurations").action(await withLanguageResolution(async (options) => {
1978
+ await init(options);
1979
+ }));
1980
+ cli.command("update", "Update Claude Code prompts only").alias("u").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").action(await withLanguageResolution(async (options) => {
1981
+ await update(options);
1982
+ }));
1983
+ cli.command("ccr", "Configure Claude Code Router for model proxy").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").action(await withLanguageResolution(async () => {
1984
+ await ccr();
1985
+ }));
1986
+ cli.command("ccu [...args]", "Run Claude Code usage analysis tool").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").allowUnknownOptions().action(await withLanguageResolution(async (args) => {
1987
+ await executeCcusage(args);
1988
+ }));
1989
+ cli.command("config-switch [target]", "Switch Codex provider or Claude Code configuration, or list available configurations").alias("cs").option("--code-type, -T <type>", "Code tool type (claude-code, codex, cc, cx)").option("--lang <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--list, -l", "List available configurations").action(await withLanguageResolution(async (target, options) => {
1990
+ await configSwitchCommand({
1991
+ target,
1992
+ codeType: options.codeType,
1993
+ list: options.list
1994
+ });
1995
+ }));
1996
+ cli.command("uninstall", "Remove ZCF configurations and tools").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--mode, -m <mode>", "Uninstall mode (complete/custom/interactive), default: interactive").option("--items, -i <items>", "Comma-separated items for custom uninstall mode").action(await withLanguageResolution(async (options) => {
1997
+ await uninstall(options);
1998
+ }));
1999
+ cli.command("check-updates", "Check and update Claude Code and CCR to latest versions").alias("check").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").action(await withLanguageResolution(async (options) => {
2000
+ await checkUpdates(options);
2001
+ }));
2002
+ cli.help((sections) => customizeHelp(sections));
2003
+ cli.version(version);
2004
+ }
2005
+
2006
+ async function main() {
2007
+ const cli = cac("zcf");
2008
+ await setupCommands(cli);
2009
+ cli.parse();
2010
+ }
2011
+ main().catch(console.error);
2012
+
2013
+ export { configSwitch as c };