zcf 2.12.4 → 2.12.5

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 (36) hide show
  1. package/README.md +30 -5
  2. package/dist/chunks/simple-config.mjs +676 -1684
  3. package/dist/cli.mjs +371 -406
  4. package/dist/i18n/locales/en/api.json +35 -0
  5. package/dist/i18n/locales/en/ccr.json +63 -0
  6. package/dist/i18n/locales/en/cli.json +42 -0
  7. package/dist/i18n/locales/en/cometix.json +29 -0
  8. package/dist/i18n/locales/en/common.json +14 -0
  9. package/dist/i18n/locales/en/configuration.json +60 -0
  10. package/dist/i18n/locales/en/errors.json +20 -0
  11. package/dist/i18n/locales/en/installation.json +12 -0
  12. package/dist/i18n/locales/en/language.json +13 -0
  13. package/dist/i18n/locales/en/mcp.json +17 -0
  14. package/dist/i18n/locales/en/menu.json +31 -0
  15. package/dist/i18n/locales/en/tools.json +15 -0
  16. package/dist/i18n/locales/en/updater.json +20 -0
  17. package/dist/i18n/locales/en/workflow.json +23 -0
  18. package/dist/i18n/locales/zh-CN/api.json +35 -0
  19. package/dist/i18n/locales/zh-CN/ccr.json +63 -0
  20. package/dist/i18n/locales/zh-CN/cli.json +42 -0
  21. package/dist/i18n/locales/zh-CN/cometix.json +29 -0
  22. package/dist/i18n/locales/zh-CN/common.json +14 -0
  23. package/dist/i18n/locales/zh-CN/configuration.json +60 -0
  24. package/dist/i18n/locales/zh-CN/errors.json +20 -0
  25. package/dist/i18n/locales/zh-CN/installation.json +12 -0
  26. package/dist/i18n/locales/zh-CN/language.json +13 -0
  27. package/dist/i18n/locales/zh-CN/mcp.json +17 -0
  28. package/dist/i18n/locales/zh-CN/menu.json +31 -0
  29. package/dist/i18n/locales/zh-CN/tools.json +15 -0
  30. package/dist/i18n/locales/zh-CN/updater.json +20 -0
  31. package/dist/i18n/locales/zh-CN/workflow.json +23 -0
  32. package/dist/index.d.mts +3 -26
  33. package/dist/index.d.ts +3 -26
  34. package/dist/index.mjs +5 -4
  35. package/package.json +6 -2
  36. package/templates/common/settings.json +2 -1
package/dist/cli.mjs CHANGED
@@ -1,31 +1,32 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { I as I18N, J as readCcrConfig, K as isCcrInstalled, M as installCcr, N as configureCcrFeature, O as handleExitPromptError, P as handleGeneralError, Q as getTranslation, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, R as addNumbersToChoices, j as LANG_LABELS, T as updateZcfConfig, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, U as readZcfConfig, v as applyAiLanguageDirective, V as configureOutputStyle, s as getExistingModelConfig, u as updateDefaultModel, W as isWindows, z as readMcpConfig, G as fixWindowsMcpConfig, B as writeMcpConfig, X as selectMcpServices, D as backupMcpConfig, Y as getMcpServices, F as buildMcpServerConfig, E as mergeMcpServers, t as getExistingApiConfig, _ as formatApiKeyDisplay, H as addCompletedOnboarding, $ as modifyApiConfigPartially, a0 as setupCcrConfiguration, a1 as validateApiKey, p as configureApi, a2 as readZcfConfigAsync, a3 as COMETIX_COMMAND_NAME, a4 as COMETIX_COMMANDS, a5 as installCometixLine, a6 as selectScriptLanguage, a7 as checkAndUpdateTools, a8 as displayBanner, a9 as resolveAiOutputLanguage, aa as updatePromptOnly, ab as selectAndInstallWorkflows, ac as checkClaudeCodeVersionAndPrompt, ad as version, ae as displayBannerWithInfo, i as init } from './chunks/simple-config.mjs';
4
+ import { J as ensureI18nInitialized, K as i18n, M as readCcrConfig, N as isCcrInstalled, O as installCcr, P as configureCcrFeature, Q as handleExitPromptError, R as handleGeneralError, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, T as addNumbersToChoices, j as LANG_LABELS, U as updateZcfConfig, V as changeLanguage, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, W as readZcfConfig, w as applyAiLanguageDirective, X as configureOutputStyle, t as getExistingModelConfig, u as updateDefaultModel, Y as isWindows, B as readMcpConfig, H as fixWindowsMcpConfig, D as writeMcpConfig, _ as selectMcpServices, E as backupMcpConfig, $ as getMcpServices, G as buildMcpServerConfig, F as mergeMcpServers, v as getExistingApiConfig, a0 as formatApiKeyDisplay, I as addCompletedOnboarding, a1 as modifyApiConfigPartially, a2 as setupCcrConfiguration, a3 as validateApiKey, q as configureApi, a4 as COMETIX_COMMAND_NAME, a5 as COMETIX_COMMANDS, a6 as installCometixLine, a7 as checkAndUpdateTools, a8 as displayBanner, a9 as resolveAiOutputLanguage, aa as updatePromptOnly, ab as selectAndInstallWorkflows, ac as checkClaudeCodeVersionAndPrompt, ad as version, ae as displayBannerWithInfo, i as init, af as readZcfConfigAsync, ag as initI18n, ah as selectScriptLanguage } from './chunks/simple-config.mjs';
5
5
  import { existsSync, unlinkSync } from 'node:fs';
6
6
  import { homedir } from 'node:os';
7
- import { join } from 'node:path';
8
7
  import inquirer from 'inquirer';
8
+ import { join } from 'pathe';
9
9
  import { exec, spawn } from 'node:child_process';
10
10
  import { promisify } from 'node:util';
11
11
  import process from 'node:process';
12
12
  import { x } from 'tinyexec';
13
- import 'dayjs';
14
13
  import 'node:url';
15
- import 'pathe';
14
+ import 'i18next';
15
+ import 'i18next-fs-backend';
16
+ import 'dayjs';
16
17
  import 'ora';
17
18
  import 'semver';
18
19
  import 'node:fs/promises';
19
20
 
20
21
  const execAsync$1 = promisify(exec);
21
- async function runCcrUi(scriptLang, apiKey) {
22
- const i18n = I18N[scriptLang];
22
+ async function runCcrUi(apiKey) {
23
+ ensureI18nInitialized();
23
24
  console.log(ansis.cyan(`
24
- \u{1F5A5}\uFE0F ${i18n.ccr.startingCcrUi}`));
25
+ \u{1F5A5}\uFE0F ${i18n.t("ccr:startingCcrUi")}`));
25
26
  if (apiKey) {
26
27
  console.log(ansis.bold.green(`
27
- \u{1F511} ${i18n.ccr.ccrUiApiKey || "CCR UI API Key"}: ${apiKey}`));
28
- console.log(ansis.gray(` ${i18n.ccr.ccrUiApiKeyHint || "Use this API key to login to CCR UI"}
28
+ \u{1F511} ${i18n.t("ccr:ccrUiApiKey") || "CCR UI API Key"}: ${apiKey}`));
29
+ console.log(ansis.gray(` ${i18n.t("ccr:ccrUiApiKeyHint") || "Use this API key to login to CCR UI"}
29
30
  `));
30
31
  }
31
32
  try {
@@ -34,82 +35,82 @@ async function runCcrUi(scriptLang, apiKey) {
34
35
  console.log(stdout);
35
36
  if (stderr)
36
37
  console.error(ansis.yellow(stderr));
37
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrUiStarted}`));
38
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrUiStarted")}`));
38
39
  } catch (error) {
39
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
40
+ console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
40
41
  throw error;
41
42
  }
42
43
  }
43
- async function runCcrStatus(scriptLang) {
44
- const i18n = I18N[scriptLang];
44
+ async function runCcrStatus() {
45
+ ensureI18nInitialized();
45
46
  console.log(ansis.cyan(`
46
- \u{1F4CA} ${i18n.ccr.checkingCcrStatus}`));
47
+ \u{1F4CA} ${i18n.t("ccr:checkingCcrStatus")}`));
47
48
  try {
48
49
  const { stdout, stderr } = await execAsync$1("ccr status");
49
50
  if (stdout) {
50
51
  console.log(`
51
- ${ansis.bold(i18n.ccr.ccrStatusTitle)}`);
52
+ ${ansis.bold(i18n.t("ccr:ccrStatusTitle"))}`);
52
53
  console.log(stdout);
53
54
  }
54
55
  if (stderr)
55
56
  console.error(ansis.yellow(stderr));
56
57
  } catch (error) {
57
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
58
+ console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
58
59
  throw error;
59
60
  }
60
61
  }
61
- async function runCcrRestart(scriptLang) {
62
- const i18n = I18N[scriptLang];
62
+ async function runCcrRestart() {
63
+ ensureI18nInitialized();
63
64
  console.log(ansis.cyan(`
64
- \u{1F504} ${i18n.ccr.restartingCcr}`));
65
+ \u{1F504} ${i18n.t("ccr:restartingCcr")}`));
65
66
  try {
66
67
  const { stdout, stderr } = await execAsync$1("ccr restart");
67
68
  if (stdout)
68
69
  console.log(stdout);
69
70
  if (stderr)
70
71
  console.error(ansis.yellow(stderr));
71
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrRestarted}`));
72
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrRestarted")}`));
72
73
  } catch (error) {
73
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
74
+ console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
74
75
  throw error;
75
76
  }
76
77
  }
77
- async function runCcrStart(scriptLang) {
78
- const i18n = I18N[scriptLang];
78
+ async function runCcrStart() {
79
+ ensureI18nInitialized();
79
80
  console.log(ansis.cyan(`
80
- \u25B6\uFE0F ${i18n.ccr.startingCcr}`));
81
+ \u25B6\uFE0F ${i18n.t("ccr:startingCcr")}`));
81
82
  try {
82
83
  const { stdout, stderr } = await execAsync$1("ccr start");
83
84
  if (stdout)
84
85
  console.log(stdout);
85
86
  if (stderr)
86
87
  console.error(ansis.yellow(stderr));
87
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStarted}`));
88
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrStarted")}`));
88
89
  } catch (error) {
89
90
  if (error.stdout && error.stdout.includes("Loaded JSON config from:")) {
90
91
  console.log(error.stdout);
91
92
  if (error.stderr)
92
93
  console.error(ansis.yellow(error.stderr));
93
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStarted}`));
94
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrStarted")}`));
94
95
  } else {
95
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
96
+ console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
96
97
  throw error;
97
98
  }
98
99
  }
99
100
  }
100
- async function runCcrStop(scriptLang) {
101
- const i18n = I18N[scriptLang];
101
+ async function runCcrStop() {
102
+ ensureI18nInitialized();
102
103
  console.log(ansis.cyan(`
103
- \u23F9\uFE0F ${i18n.ccr.stoppingCcr}`));
104
+ \u23F9\uFE0F ${i18n.t("ccr:stoppingCcr")}`));
104
105
  try {
105
106
  const { stdout, stderr } = await execAsync$1("ccr stop");
106
107
  if (stdout)
107
108
  console.log(stdout);
108
109
  if (stderr)
109
110
  console.error(ansis.yellow(stderr));
110
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStopped}`));
111
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrStopped")}`));
111
112
  } catch (error) {
112
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
113
+ console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
113
114
  throw error;
114
115
  }
115
116
  }
@@ -120,95 +121,95 @@ function isCcrConfigured() {
120
121
  return false;
121
122
  }
122
123
  const config = readCcrConfig();
123
- return config !== null && config.Providers && config.Providers.length > 0;
124
+ return config !== null;
124
125
  }
125
- async function showCcrMenu(scriptLang) {
126
+ async function showCcrMenu() {
126
127
  try {
127
- const i18n = I18N[scriptLang];
128
+ ensureI18nInitialized();
128
129
  console.log(`
129
130
  ${ansis.cyan("\u2550".repeat(50))}`);
130
- console.log(ansis.bold.cyan(` ${i18n.ccr.ccrMenuTitle}`));
131
+ console.log(ansis.bold.cyan(` ${i18n.t("ccr:ccrMenuTitle")}`));
131
132
  console.log(`${ansis.cyan("\u2550".repeat(50))}
132
133
  `);
133
- console.log(` ${ansis.cyan("1.")} ${i18n.ccr.ccrMenuOptions.initCcr} ${ansis.gray(`- ${i18n.ccr.ccrMenuDescriptions.initCcr}`)}`);
134
- console.log(` ${ansis.cyan("2.")} ${i18n.ccr.ccrMenuOptions.startUi} ${ansis.gray(`- ${i18n.ccr.ccrMenuDescriptions.startUi}`)}`);
135
- console.log(` ${ansis.cyan("3.")} ${i18n.ccr.ccrMenuOptions.checkStatus} ${ansis.gray(`- ${i18n.ccr.ccrMenuDescriptions.checkStatus}`)}`);
136
- console.log(` ${ansis.cyan("4.")} ${i18n.ccr.ccrMenuOptions.restart} ${ansis.gray(`- ${i18n.ccr.ccrMenuDescriptions.restart}`)}`);
137
- console.log(` ${ansis.cyan("5.")} ${i18n.ccr.ccrMenuOptions.start} ${ansis.gray(`- ${i18n.ccr.ccrMenuDescriptions.start}`)}`);
138
- console.log(` ${ansis.cyan("6.")} ${i18n.ccr.ccrMenuOptions.stop} ${ansis.gray(`- ${i18n.ccr.ccrMenuDescriptions.stop}`)}`);
139
- console.log(` ${ansis.yellow("0.")} ${i18n.ccr.ccrMenuOptions.back}`);
134
+ console.log(` ${ansis.cyan("1.")} ${i18n.t("ccr:ccrMenuOptions.initCcr")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.initCcr")}`)}`);
135
+ console.log(` ${ansis.cyan("2.")} ${i18n.t("ccr:ccrMenuOptions.startUi")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.startUi")}`)}`);
136
+ console.log(` ${ansis.cyan("3.")} ${i18n.t("ccr:ccrMenuOptions.checkStatus")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.checkStatus")}`)}`);
137
+ console.log(` ${ansis.cyan("4.")} ${i18n.t("ccr:ccrMenuOptions.restart")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.restart")}`)}`);
138
+ console.log(` ${ansis.cyan("5.")} ${i18n.t("ccr:ccrMenuOptions.start")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.start")}`)}`);
139
+ console.log(` ${ansis.cyan("6.")} ${i18n.t("ccr:ccrMenuOptions.stop")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.stop")}`)}`);
140
+ console.log(` ${ansis.yellow("0.")} ${i18n.t("ccr:ccrMenuOptions.back")}`);
140
141
  console.log("");
141
142
  const { choice } = await inquirer.prompt({
142
143
  type: "input",
143
144
  name: "choice",
144
- message: i18n.common.enterChoice,
145
+ message: i18n.t("common:enterChoice"),
145
146
  validate: (value) => {
146
147
  const valid = ["1", "2", "3", "4", "5", "6", "0"];
147
- return valid.includes(value) || i18n.common.invalidChoice;
148
+ return valid.includes(value) || i18n.t("common:invalidChoice");
148
149
  }
149
150
  });
150
151
  switch (choice) {
151
152
  case "1": {
152
153
  const ccrStatus = await isCcrInstalled();
153
154
  if (!ccrStatus.hasCorrectPackage) {
154
- await installCcr(scriptLang);
155
+ await installCcr();
155
156
  } else {
156
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
157
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrAlreadyInstalled")}`));
157
158
  }
158
- await configureCcrFeature(scriptLang);
159
+ await configureCcrFeature();
159
160
  console.log(ansis.green(`
160
- \u2714 ${i18n.ccr.ccrSetupComplete}`));
161
+ \u2714 ${i18n.t("ccr:ccrSetupComplete")}`));
161
162
  break;
162
163
  }
163
164
  case "2":
164
165
  if (!isCcrConfigured()) {
165
166
  console.log(ansis.yellow(`
166
- \u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
167
- console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
167
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
168
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
168
169
  `));
169
170
  } else {
170
171
  const config = readCcrConfig();
171
- await runCcrUi(scriptLang, config?.APIKEY);
172
+ await runCcrUi(config?.APIKEY);
172
173
  }
173
174
  break;
174
175
  case "3":
175
176
  if (!isCcrConfigured()) {
176
177
  console.log(ansis.yellow(`
177
- \u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
178
- console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
178
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
179
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
179
180
  `));
180
181
  } else {
181
- await runCcrStatus(scriptLang);
182
+ await runCcrStatus();
182
183
  }
183
184
  break;
184
185
  case "4":
185
186
  if (!isCcrConfigured()) {
186
187
  console.log(ansis.yellow(`
187
- \u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
188
- console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
188
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
189
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
189
190
  `));
190
191
  } else {
191
- await runCcrRestart(scriptLang);
192
+ await runCcrRestart();
192
193
  }
193
194
  break;
194
195
  case "5":
195
196
  if (!isCcrConfigured()) {
196
197
  console.log(ansis.yellow(`
197
- \u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
198
- console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
198
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
199
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
199
200
  `));
200
201
  } else {
201
- await runCcrStart(scriptLang);
202
+ await runCcrStart();
202
203
  }
203
204
  break;
204
205
  case "6":
205
206
  if (!isCcrConfigured()) {
206
207
  console.log(ansis.yellow(`
207
- \u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
208
- console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
208
+ \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
209
+ console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
209
210
  `));
210
211
  } else {
211
- await runCcrStop(scriptLang);
212
+ await runCcrStop();
212
213
  }
213
214
  break;
214
215
  case "0":
@@ -221,78 +222,78 @@ ${ansis.dim("\u2500".repeat(50))}
221
222
  const { continueInCcr } = await inquirer.prompt({
222
223
  type: "confirm",
223
224
  name: "continueInCcr",
224
- message: i18n.common.returnToMenu || "Return to CCR menu?",
225
+ message: i18n.t("common:returnToMenu"),
225
226
  default: true
226
227
  });
227
228
  if (continueInCcr) {
228
- return await showCcrMenu(scriptLang);
229
+ return await showCcrMenu();
229
230
  }
230
231
  }
231
232
  return false;
232
233
  } catch (error) {
233
234
  if (!handleExitPromptError(error)) {
234
- handleGeneralError(error, scriptLang);
235
+ handleGeneralError(error);
235
236
  }
236
237
  return false;
237
238
  }
238
239
  }
239
240
 
240
- function handleCancellation(scriptLang) {
241
- const i18n = getTranslation(scriptLang);
242
- console.log(ansis.yellow(i18n.common.cancelled));
241
+ async function handleCancellation() {
242
+ ensureI18nInitialized();
243
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
243
244
  }
244
- async function configureApiFeature(scriptLang) {
245
- const i18n = getTranslation(scriptLang);
245
+ async function configureApiFeature() {
246
+ ensureI18nInitialized();
246
247
  const existingApiConfig = getExistingApiConfig();
247
248
  if (existingApiConfig) {
248
249
  console.log(`
249
- ${ansis.blue(`\u2139 ${i18n.api.existingApiConfig}`)}`);
250
- console.log(ansis.gray(` ${i18n.api.apiConfigUrl}: ${existingApiConfig.url || i18n.common.notConfigured}`));
250
+ ${ansis.blue(`\u2139 ${i18n.t("api:existingApiConfig")}`)}`);
251
+ console.log(ansis.gray(` ${i18n.t("api:apiConfigUrl")}: ${existingApiConfig.url || i18n.t("common:notConfigured")}`));
251
252
  console.log(
252
253
  ansis.gray(
253
- ` ${i18n.api.apiConfigKey}: ${existingApiConfig.key ? formatApiKeyDisplay(existingApiConfig.key) : i18n.common.notConfigured}`
254
+ ` ${i18n.t("api:apiConfigKey")}: ${existingApiConfig.key ? formatApiKeyDisplay(existingApiConfig.key) : i18n.t("common:notConfigured")}`
254
255
  )
255
256
  );
256
257
  console.log(
257
- ansis.gray(` ${i18n.api.apiConfigAuthType}: ${existingApiConfig.authType || i18n.common.notConfigured}
258
+ ansis.gray(` ${i18n.t("api:apiConfigAuthType")}: ${existingApiConfig.authType || i18n.t("common:notConfigured")}
258
259
  `)
259
260
  );
260
261
  const { action } = await inquirer.prompt({
261
262
  type: "list",
262
263
  name: "action",
263
- message: i18n.api.selectApiAction,
264
+ message: i18n.t("api:selectApiAction"),
264
265
  choices: addNumbersToChoices([
265
- { name: i18n.api.keepExistingConfig, value: "keep" },
266
- { name: i18n.api.modifyAllConfig, value: "modify-all" },
267
- { name: i18n.api.modifyPartialConfig, value: "modify-partial" },
268
- { name: i18n.api.useCcrProxy, value: "use-ccr" }
266
+ { name: i18n.t("api:keepExistingConfig"), value: "keep" },
267
+ { name: i18n.t("api:modifyAllConfig"), value: "modify-all" },
268
+ { name: i18n.t("api:modifyPartialConfig"), value: "modify-partial" },
269
+ { name: i18n.t("api:useCcrProxy"), value: "use-ccr" }
269
270
  ])
270
271
  });
271
272
  if (!action) {
272
- handleCancellation(scriptLang);
273
+ await handleCancellation();
273
274
  return;
274
275
  }
275
276
  if (action === "keep") {
276
- console.log(ansis.green(`\u2714 ${i18n.api.keepExistingConfig}`));
277
+ console.log(ansis.green(`\u2714 ${i18n.t("api:keepExistingConfig")}`));
277
278
  try {
278
279
  addCompletedOnboarding();
279
280
  } catch (error) {
280
- console.error(ansis.red(i18n.configuration.failedToSetOnboarding), error);
281
+ console.error(ansis.red(i18n.t("errors:failedToSetOnboarding")), error);
281
282
  }
282
283
  return;
283
284
  } else if (action === "modify-partial") {
284
- await modifyApiConfigPartially(existingApiConfig, i18n, scriptLang);
285
+ await modifyApiConfigPartially(existingApiConfig);
285
286
  return;
286
287
  } else if (action === "use-ccr") {
287
288
  const ccrStatus = await isCcrInstalled();
288
289
  if (!ccrStatus.hasCorrectPackage) {
289
- await installCcr(scriptLang);
290
+ await installCcr();
290
291
  } else {
291
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
292
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrAlreadyInstalled")}`));
292
293
  }
293
- const ccrConfigured = await setupCcrConfiguration(scriptLang);
294
+ const ccrConfigured = await setupCcrConfiguration();
294
295
  if (ccrConfigured) {
295
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrSetupComplete}`));
296
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrSetupComplete")}`));
296
297
  }
297
298
  return;
298
299
  }
@@ -300,24 +301,24 @@ ${ansis.blue(`\u2139 ${i18n.api.existingApiConfig}`)}`);
300
301
  const { apiChoice } = await inquirer.prompt({
301
302
  type: "list",
302
303
  name: "apiChoice",
303
- message: i18n.api.configureApi,
304
+ message: i18n.t("api:configureApi"),
304
305
  choices: addNumbersToChoices([
305
306
  {
306
- name: `${i18n.api.useAuthToken} - ${ansis.gray(i18n.api.authTokenDesc)}`,
307
+ name: `${i18n.t("api:useAuthToken")} - ${ansis.gray(i18n.t("api:authTokenDesc"))}`,
307
308
  value: "auth_token",
308
- short: i18n.api.useAuthToken
309
+ short: i18n.t("api:useAuthToken")
309
310
  },
310
311
  {
311
- name: `${i18n.api.useApiKey} - ${ansis.gray(i18n.api.apiKeyDesc)}`,
312
+ name: `${i18n.t("api:useApiKey")} - ${ansis.gray(i18n.t("api:apiKeyDesc"))}`,
312
313
  value: "api_key",
313
- short: i18n.api.useApiKey
314
+ short: i18n.t("api:useApiKey")
314
315
  },
315
316
  {
316
- name: `${i18n.api.useCcrProxy} - ${ansis.gray(i18n.api.ccrProxyDesc)}`,
317
+ name: `${i18n.t("api:useCcrProxy")} - ${ansis.gray(i18n.t("api:ccrProxyDesc"))}`,
317
318
  value: "ccr_proxy",
318
- short: i18n.api.useCcrProxy
319
+ short: i18n.t("api:useCcrProxy")
319
320
  },
320
- { name: i18n.api.skipApi, value: "skip" }
321
+ { name: i18n.t("api:skipApi"), value: "skip" }
321
322
  ])
322
323
  });
323
324
  if (!apiChoice || apiChoice === "skip") {
@@ -326,70 +327,70 @@ ${ansis.blue(`\u2139 ${i18n.api.existingApiConfig}`)}`);
326
327
  if (apiChoice === "ccr_proxy") {
327
328
  const ccrStatus = await isCcrInstalled();
328
329
  if (!ccrStatus.hasCorrectPackage) {
329
- await installCcr(scriptLang);
330
+ await installCcr();
330
331
  } else {
331
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
332
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrAlreadyInstalled")}`));
332
333
  }
333
- const ccrConfigured = await setupCcrConfiguration(scriptLang);
334
+ const ccrConfigured = await setupCcrConfiguration();
334
335
  if (ccrConfigured) {
335
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrSetupComplete}`));
336
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrSetupComplete")}`));
336
337
  }
337
338
  return;
338
339
  }
339
340
  const { url } = await inquirer.prompt({
340
341
  type: "input",
341
342
  name: "url",
342
- message: i18n.api.enterApiUrl,
343
- validate: (value) => {
343
+ message: i18n.t("api:enterApiUrl"),
344
+ validate: async (value) => {
344
345
  if (!value)
345
- return i18n.api.urlRequired;
346
+ return i18n.t("api:urlRequired");
346
347
  try {
347
348
  void new URL(value);
348
349
  return true;
349
350
  } catch {
350
- return i18n.api.invalidUrl;
351
+ return i18n.t("api:invalidUrl");
351
352
  }
352
353
  }
353
354
  });
354
355
  if (!url) {
355
- handleCancellation(scriptLang);
356
+ await handleCancellation();
356
357
  return;
357
358
  }
358
- const keyMessage = apiChoice === "auth_token" ? i18n.api.enterAuthToken : i18n.api.enterApiKey;
359
+ const keyMessage = apiChoice === "auth_token" ? i18n.t("api:enterAuthToken") : i18n.t("api:enterApiKey");
359
360
  const { key } = await inquirer.prompt({
360
361
  type: "input",
361
362
  name: "key",
362
363
  message: keyMessage,
363
- validate: (value) => {
364
+ validate: async (value) => {
364
365
  if (!value) {
365
- return i18n.api.keyRequired;
366
+ return i18n.t("api:keyRequired");
366
367
  }
367
- const validation = validateApiKey(value, scriptLang);
368
+ const validation = await validateApiKey(value);
368
369
  if (!validation.isValid) {
369
- return validation.error || i18n.api.invalidKeyFormat;
370
+ return validation.error || i18n.t("api:invalidKeyFormat");
370
371
  }
371
372
  return true;
372
373
  }
373
374
  });
374
375
  if (!key) {
375
- handleCancellation(scriptLang);
376
+ await handleCancellation();
376
377
  return;
377
378
  }
378
379
  const apiConfig = { url, key, authType: apiChoice };
379
380
  const configuredApi = configureApi(apiConfig);
380
381
  if (configuredApi) {
381
- console.log(ansis.green(`\u2714 ${i18n.api.apiConfigSuccess}`));
382
+ console.log(ansis.green(`\u2714 ${i18n.t("api:apiConfigSuccess")}`));
382
383
  console.log(ansis.gray(` URL: ${configuredApi.url}`));
383
384
  console.log(ansis.gray(` Key: ${formatApiKeyDisplay(configuredApi.key)}`));
384
385
  }
385
386
  }
386
- async function configureMcpFeature(scriptLang) {
387
- const i18n = getTranslation(scriptLang);
387
+ async function configureMcpFeature() {
388
+ ensureI18nInitialized();
388
389
  if (isWindows()) {
389
390
  const { fixWindows } = await inquirer.prompt({
390
391
  type: "confirm",
391
392
  name: "fixWindows",
392
- message: i18n.configuration.fixWindowsMcp || "Fix Windows MCP configuration?",
393
+ message: i18n.t("configuration:fixWindowsMcp") || "Fix Windows MCP configuration?",
393
394
  default: true
394
395
  });
395
396
  if (fixWindows) {
@@ -399,18 +400,18 @@ async function configureMcpFeature(scriptLang) {
399
400
  console.log(ansis.green(`\u2714 Windows MCP configuration fixed`));
400
401
  }
401
402
  }
402
- const selectedServices = await selectMcpServices(scriptLang);
403
+ const selectedServices = await selectMcpServices();
403
404
  if (!selectedServices) {
404
405
  return;
405
406
  }
406
407
  if (selectedServices.length > 0) {
407
408
  const mcpBackupPath = backupMcpConfig();
408
409
  if (mcpBackupPath) {
409
- console.log(ansis.gray(`\u2714 ${i18n.mcp.mcpBackupSuccess}: ${mcpBackupPath}`));
410
+ console.log(ansis.gray(`\u2714 ${i18n.t("mcp:mcpBackupSuccess")}: ${mcpBackupPath}`));
410
411
  }
411
412
  const newServers = {};
412
413
  for (const serviceId of selectedServices) {
413
- const service = getMcpServices(scriptLang).find((s) => s.id === serviceId);
414
+ const service = (await getMcpServices()).find((s) => s.id === serviceId);
414
415
  if (!service)
415
416
  continue;
416
417
  let config = service.config;
@@ -419,7 +420,7 @@ async function configureMcpFeature(scriptLang) {
419
420
  type: "input",
420
421
  name: "apiKey",
421
422
  message: service.apiKeyPrompt,
422
- validate: (value) => !!value || i18n.api.keyRequired
423
+ validate: async (value) => !!value || i18n.t("api:keyRequired")
423
424
  });
424
425
  if (apiKey) {
425
426
  config = buildMcpServerConfig(service.config, apiKey, service.apiKeyPlaceholder, service.apiKeyEnvVar);
@@ -433,69 +434,69 @@ async function configureMcpFeature(scriptLang) {
433
434
  let mergedConfig = mergeMcpServers(existingConfig, newServers);
434
435
  mergedConfig = fixWindowsMcpConfig(mergedConfig);
435
436
  writeMcpConfig(mergedConfig);
436
- console.log(ansis.green(`\u2714 ${i18n.mcp.mcpConfigSuccess}`));
437
+ console.log(ansis.green(`\u2714 ${i18n.t("mcp:mcpConfigSuccess")}`));
437
438
  }
438
439
  }
439
- async function configureDefaultModelFeature(scriptLang) {
440
- const i18n = getTranslation(scriptLang);
440
+ async function configureDefaultModelFeature() {
441
+ ensureI18nInitialized();
441
442
  const existingModel = getExistingModelConfig();
442
443
  if (existingModel) {
443
444
  console.log(`
444
- ${ansis.blue(`\u2139 ${i18n.configuration.existingModelConfig || "Existing model configuration"}`)}`);
445
- const modelDisplay = existingModel === "default" ? i18n.configuration.defaultModelOption || "Default (Let Claude Code choose)" : existingModel.charAt(0).toUpperCase() + existingModel.slice(1);
446
- console.log(ansis.gray(` ${i18n.configuration.currentModel || "Current model"}: ${modelDisplay}
445
+ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingModelConfig") || "Existing model configuration"}`)}`);
446
+ const modelDisplay = existingModel === "default" ? i18n.t("configuration:defaultModelOption") || "Default (Let Claude Code choose)" : existingModel.charAt(0).toUpperCase() + existingModel.slice(1);
447
+ console.log(ansis.gray(` ${i18n.t("configuration:currentModel") || "Current model"}: ${modelDisplay}
447
448
  `));
448
449
  const { modify } = await inquirer.prompt({
449
450
  type: "confirm",
450
451
  name: "modify",
451
- message: i18n.configuration.modifyModel || "Modify model configuration?",
452
+ message: i18n.t("configuration:modifyModel") || "Modify model configuration?",
452
453
  default: false
453
454
  });
454
455
  if (!modify) {
455
- console.log(ansis.green(`\u2714 ${i18n.configuration.keepModel || "Keeping existing model configuration"}`));
456
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepModel") || "Keeping existing model configuration"}`));
456
457
  return;
457
458
  }
458
459
  }
459
460
  const { model } = await inquirer.prompt({
460
461
  type: "list",
461
462
  name: "model",
462
- message: i18n.configuration.selectDefaultModel || "Select default model",
463
+ message: i18n.t("configuration:selectDefaultModel") || "Select default model",
463
464
  choices: addNumbersToChoices([
464
465
  {
465
- name: i18n.configuration.defaultModelOption || "Default - Let Claude Code choose",
466
+ name: i18n.t("configuration:defaultModelOption") || "Default - Let Claude Code choose",
466
467
  value: "default"
467
468
  },
468
469
  {
469
- name: i18n.configuration.opusModelOption || "Opus - Only use opus, high token consumption, use with caution",
470
+ name: i18n.t("configuration:opusModelOption") || "Opus - Only use opus, high token consumption, use with caution",
470
471
  value: "opus"
471
472
  },
472
473
  {
473
- name: i18n.configuration.opusPlanModelOption || "OpusPlan - Use Opus for planning, write code with sonnet, recommended",
474
+ name: i18n.t("configuration:opusPlanModelOption") || "OpusPlan - Use Opus for planning, write code with sonnet, recommended",
474
475
  value: "opusplan"
475
476
  }
476
477
  ]),
477
478
  default: existingModel ? ["default", "opus", "opusplan"].indexOf(existingModel) : 0
478
479
  });
479
480
  if (!model) {
480
- handleCancellation(scriptLang);
481
+ await handleCancellation();
481
482
  return;
482
483
  }
483
484
  updateDefaultModel(model);
484
- console.log(ansis.green(`\u2714 ${i18n.configuration.modelConfigured || "Default model configured"}`));
485
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:modelConfigured") || "Default model configured"}`));
485
486
  }
486
- async function configureAiMemoryFeature(scriptLang) {
487
- const i18n = getTranslation(scriptLang);
487
+ async function configureAiMemoryFeature() {
488
+ ensureI18nInitialized();
488
489
  const { option } = await inquirer.prompt({
489
490
  type: "list",
490
491
  name: "option",
491
- message: i18n.configuration.selectMemoryOption || "Select configuration option",
492
+ message: i18n.t("configuration:selectMemoryOption") || "Select configuration option",
492
493
  choices: addNumbersToChoices([
493
494
  {
494
- name: i18n.configuration.configureAiLanguage || "Configure AI output language",
495
+ name: i18n.t("configuration:configureAiLanguage") || "Configure AI output language",
495
496
  value: "language"
496
497
  },
497
498
  {
498
- name: i18n.configuration.configureOutputStyle || "Configure global AI output style",
499
+ name: i18n.t("configuration:configureOutputStyle") || "Configure global AI output style",
499
500
  value: "outputStyle"
500
501
  }
501
502
  ])
@@ -509,55 +510,55 @@ async function configureAiMemoryFeature(scriptLang) {
509
510
  if (existingLang) {
510
511
  console.log(
511
512
  `
512
- ${ansis.blue(`\u2139 ${i18n.configuration.existingLanguageConfig || "Existing AI output language configuration"}`)}`
513
+ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existing AI output language configuration"}`)}`
513
514
  );
514
- console.log(ansis.gray(` ${i18n.configuration.currentLanguage || "Current language"}: ${existingLang}
515
+ console.log(ansis.gray(` ${i18n.t("configuration:currentLanguage") || "Current language"}: ${existingLang}
515
516
  `));
516
517
  const { modify } = await inquirer.prompt({
517
518
  type: "confirm",
518
519
  name: "modify",
519
- message: i18n.configuration.modifyLanguage || "Modify AI output language?",
520
+ message: i18n.t("configuration:modifyLanguage") || "Modify AI output language?",
520
521
  default: false
521
522
  });
522
523
  if (!modify) {
523
- console.log(ansis.green(`\u2714 ${i18n.configuration.keepLanguage || "Keeping existing language configuration"}`));
524
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepLanguage") || "Keeping existing language configuration"}`));
524
525
  return;
525
526
  }
526
527
  }
527
- const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.af; });
528
- const aiOutputLang = await selectAiOutputLanguage(scriptLang, scriptLang);
528
+ const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.ai; });
529
+ const aiOutputLang = await selectAiOutputLanguage();
529
530
  applyAiLanguageDirective(aiOutputLang);
530
531
  updateZcfConfig({ aiOutputLang });
531
- console.log(ansis.green(`\u2714 ${i18n.configuration.aiLanguageConfigured || "AI output language configured"}`));
532
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:aiLanguageConfigured") || "AI output language configured"}`));
532
533
  } else if (option === "outputStyle") {
533
- await configureOutputStyle(scriptLang, scriptLang);
534
+ await configureOutputStyle();
534
535
  }
535
536
  }
536
- async function clearZcfCacheFeature(scriptLang) {
537
- const i18n = getTranslation(scriptLang);
537
+ async function clearZcfCacheFeature() {
538
+ ensureI18nInitialized();
538
539
  const { confirm } = await inquirer.prompt({
539
540
  type: "confirm",
540
541
  name: "confirm",
541
- message: i18n.configuration.confirmClearCache || "Clear all ZCF preferences cache?",
542
+ message: i18n.t("configuration:confirmClearCache") || "Clear all ZCF preferences cache?",
542
543
  default: false
543
544
  });
544
545
  if (!confirm) {
545
- handleCancellation(scriptLang);
546
+ await handleCancellation();
546
547
  return;
547
548
  }
548
549
  if (existsSync(ZCF_CONFIG_FILE)) {
549
550
  unlinkSync(ZCF_CONFIG_FILE);
550
- console.log(ansis.green(`\u2714 ${i18n.configuration.cacheCleared || "ZCF cache cleared"}`));
551
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:cacheCleared") || "ZCF cache cleared"}`));
551
552
  } else {
552
553
  console.log(ansis.yellow("No cache found"));
553
554
  }
554
555
  }
555
556
  async function changeScriptLanguageFeature(currentLang) {
556
- const i18n = getTranslation(currentLang);
557
+ ensureI18nInitialized();
557
558
  const { lang } = await inquirer.prompt({
558
559
  type: "list",
559
560
  name: "lang",
560
- message: i18n.language.selectScriptLang,
561
+ message: i18n.t("language:selectScriptLang"),
561
562
  choices: addNumbersToChoices(
562
563
  SUPPORTED_LANGS.map((l) => ({
563
564
  name: LANG_LABELS[l],
@@ -570,75 +571,66 @@ async function changeScriptLanguageFeature(currentLang) {
570
571
  return currentLang;
571
572
  }
572
573
  updateZcfConfig({ preferredLang: lang });
573
- const newI18n = getTranslation(lang);
574
- console.log(ansis.green(`\u2714 ${newI18n.language.languageChanged || "Language changed"}`));
574
+ await changeLanguage(lang);
575
+ console.log(ansis.green(`\u2714 ${i18n.t("language:languageChanged") || "Language changed"}`));
575
576
  return lang;
576
577
  }
577
- async function configureEnvPermissionFeature(scriptLang) {
578
- const i18n = getTranslation(scriptLang);
578
+ async function configureEnvPermissionFeature() {
579
+ ensureI18nInitialized();
579
580
  const { choice } = await inquirer.prompt({
580
581
  type: "list",
581
582
  name: "choice",
582
- message: i18n.configuration?.selectEnvPermissionOption || "Select option",
583
+ message: i18n.t("configuration:selectEnvPermissionOption") || "Select option",
583
584
  choices: addNumbersToChoices([
584
585
  {
585
- name: `${i18n.configuration?.importRecommendedEnv || "Import environment"} ${ansis.gray(
586
- `- ${i18n.configuration?.importRecommendedEnvDesc || "Import env settings"}`
586
+ name: `${i18n.t("configuration:importRecommendedEnv") || "Import environment"} ${ansis.gray(
587
+ `- ${i18n.t("configuration:importRecommendedEnvDesc") || "Import env settings"}`
587
588
  )}`,
588
589
  value: "env"
589
590
  },
590
591
  {
591
- name: `${i18n.configuration?.importRecommendedPermissions || "Import permissions"} ${ansis.gray(
592
- `- ${i18n.configuration?.importRecommendedPermissionsDesc || "Import permission settings"}`
592
+ name: `${i18n.t("configuration:importRecommendedPermissions") || "Import permissions"} ${ansis.gray(
593
+ `- ${i18n.t("configuration:importRecommendedPermissionsDesc") || "Import permission settings"}`
593
594
  )}`,
594
595
  value: "permissions"
595
596
  },
596
597
  {
597
- name: `${i18n.configuration?.openSettingsJson || "Open settings"} ${ansis.gray(
598
- `- ${i18n.configuration?.openSettingsJsonDesc || "View settings file"}`
598
+ name: `${i18n.t("configuration:openSettingsJson") || "Open settings"} ${ansis.gray(
599
+ `- ${i18n.t("configuration:openSettingsJsonDesc") || "View settings file"}`
599
600
  )}`,
600
601
  value: "open"
601
602
  }
602
603
  ])
603
604
  });
604
605
  if (!choice) {
605
- handleCancellation(scriptLang);
606
+ await handleCancellation();
606
607
  return;
607
608
  }
608
609
  try {
609
610
  switch (choice) {
610
611
  case "env":
611
612
  await importRecommendedEnv();
612
- console.log(ansis.green(`\u2705 ${i18n.configuration.envImportSuccess}`));
613
+ console.log(ansis.green(`\u2705 ${i18n.t("configuration:envImportSuccess")}`));
613
614
  break;
614
615
  case "permissions":
615
616
  await importRecommendedPermissions();
616
- console.log(ansis.green(`\u2705 ${i18n.configuration?.permissionsImportSuccess || "Permissions imported"}`));
617
+ console.log(ansis.green(`\u2705 ${i18n.t("configuration:permissionsImportSuccess") || "Permissions imported"}`));
617
618
  break;
618
619
  case "open":
619
- console.log(ansis.cyan(i18n.configuration?.openingSettingsJson || "Opening settings.json..."));
620
+ console.log(ansis.cyan(i18n.t("configuration:openingSettingsJson") || "Opening settings.json..."));
620
621
  await openSettingsJson();
621
622
  break;
622
623
  }
623
624
  } catch (error) {
624
- console.error(ansis.red(`${i18n.common.error}: ${error.message}`));
625
+ console.error(ansis.red(`${i18n.t("common:error")}: ${error.message}`));
625
626
  }
626
627
  }
627
628
 
628
629
  async function executeCcusage(args = []) {
629
630
  try {
630
- let lang = "en";
631
- try {
632
- const zcfConfig = await readZcfConfigAsync();
633
- const rawLang = zcfConfig?.preferredLang || "en";
634
- lang = getValidLanguage(rawLang);
635
- } catch {
636
- lang = "en";
637
- }
638
- const i18n = I18N[lang];
639
631
  const command = "npx";
640
632
  const commandArgs = ["ccusage@latest", ...args || []];
641
- console.log(ansis.cyan(i18n.tools.runningCcusage));
633
+ console.log(ansis.cyan(i18n.t("tools:runningCcusage")));
642
634
  console.log(ansis.gray(`$ npx ccusage@latest ${(args || []).join(" ")}`));
643
635
  console.log("");
644
636
  await x(command, commandArgs, {
@@ -647,19 +639,10 @@ async function executeCcusage(args = []) {
647
639
  }
648
640
  });
649
641
  } catch (error) {
650
- let lang = "en";
651
- try {
652
- const zcfConfig = await readZcfConfigAsync();
653
- const rawLang = zcfConfig?.preferredLang || "en";
654
- lang = getValidLanguage(rawLang);
655
- } catch {
656
- lang = "en";
657
- }
658
- const i18n = I18N[lang];
659
- console.error(ansis.red(i18n.tools.ccusageFailed));
660
- console.error(ansis.yellow(i18n.tools.checkNetworkConnection));
642
+ console.error(ansis.red(i18n.t("tools:ccusageFailed")));
643
+ console.error(ansis.yellow(i18n.t("tools:checkNetworkConnection")));
661
644
  if (process.env.DEBUG) {
662
- console.error(ansis.gray(i18n.tools.errorDetails), error);
645
+ console.error(ansis.gray(i18n.t("tools:errorDetails")), error);
663
646
  }
664
647
  if (process.env.NODE_ENV !== "test") {
665
648
  process.exit(1);
@@ -669,25 +652,25 @@ async function executeCcusage(args = []) {
669
652
  }
670
653
 
671
654
  const execAsync = promisify(exec);
672
- async function runCometixPrintConfig(scriptLang) {
673
- const i18n = getTranslation(scriptLang);
655
+ async function runCometixPrintConfig() {
656
+ ensureI18nInitialized();
674
657
  try {
675
- console.log(ansis.blue(`${i18n.cometix.printingConfig}`));
658
+ console.log(ansis.blue(`${i18n.t("cometix:printingConfig")}`));
676
659
  const { stdout } = await execAsync(COMETIX_COMMANDS.PRINT_CONFIG);
677
660
  console.log(stdout);
678
661
  } catch (error) {
679
662
  if (error.message.includes(`command not found: ${COMETIX_COMMAND_NAME}`)) {
680
- console.error(ansis.red(`\u2717 ${i18n.cometix.commandNotFound}`));
663
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`));
681
664
  } else {
682
- console.error(ansis.red(`\u2717 ${i18n.cometix.printConfigFailed}: ${error}`));
665
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:printConfigFailed")}: ${error}`));
683
666
  }
684
667
  throw error;
685
668
  }
686
669
  }
687
- async function runCometixTuiConfig(scriptLang) {
688
- const i18n = getTranslation(scriptLang);
670
+ async function runCometixTuiConfig() {
671
+ ensureI18nInitialized();
689
672
  return new Promise((resolve, reject) => {
690
- console.log(ansis.blue(`${i18n.cometix.enteringTuiConfig}`));
673
+ console.log(ansis.blue(`${i18n.t("cometix:enteringTuiConfig")}`));
691
674
  const child = spawn(COMETIX_COMMAND_NAME, ["-c"], {
692
675
  stdio: "inherit",
693
676
  // This allows the TUI to interact directly with the terminal
@@ -695,56 +678,56 @@ async function runCometixTuiConfig(scriptLang) {
695
678
  });
696
679
  child.on("close", (code) => {
697
680
  if (code === 0) {
698
- console.log(ansis.green(`\u2713 ${i18n.cometix.tuiConfigSuccess}`));
681
+ console.log(ansis.green(`\u2713 ${i18n.t("cometix:tuiConfigSuccess")}`));
699
682
  resolve();
700
683
  } else {
701
684
  const error = new Error(`${COMETIX_COMMAND_NAME} -c exited with code ${code}`);
702
- console.error(ansis.red(`\u2717 ${i18n.cometix.tuiConfigFailed}: ${error.message}`));
685
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`));
703
686
  reject(error);
704
687
  }
705
688
  });
706
689
  child.on("error", (error) => {
707
690
  if (error.message.includes(`command not found`) || error.message.includes("ENOENT")) {
708
- console.error(ansis.red(`\u2717 ${i18n.cometix.commandNotFound}`));
691
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`));
709
692
  } else {
710
- console.error(ansis.red(`\u2717 ${i18n.cometix.tuiConfigFailed}: ${error.message}`));
693
+ console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`));
711
694
  }
712
695
  reject(error);
713
696
  });
714
697
  });
715
698
  }
716
699
 
717
- async function showCometixMenu(scriptLang) {
700
+ async function showCometixMenu() {
718
701
  try {
719
- const i18n = getTranslation(scriptLang);
702
+ ensureI18nInitialized();
720
703
  console.log(`
721
704
  ${ansis.cyan("\u2550".repeat(50))}`);
722
- console.log(ansis.bold.cyan(` ${i18n.cometix.cometixMenuTitle}`));
705
+ console.log(ansis.bold.cyan(` ${i18n.t("cometix:cometixMenuTitle")}`));
723
706
  console.log(`${ansis.cyan("\u2550".repeat(50))}
724
707
  `);
725
- console.log(` ${ansis.cyan("1.")} ${i18n.cometix.cometixMenuOptions.installOrUpdate} ${ansis.gray(`- ${i18n.cometix.cometixMenuDescriptions.installOrUpdate}`)}`);
726
- console.log(` ${ansis.cyan("2.")} ${i18n.cometix.cometixMenuOptions.printConfig} ${ansis.gray(`- ${i18n.cometix.cometixMenuDescriptions.printConfig}`)}`);
727
- console.log(` ${ansis.cyan("3.")} ${i18n.cometix.cometixMenuOptions.customConfig} ${ansis.gray(`- ${i18n.cometix.cometixMenuDescriptions.customConfig}`)}`);
728
- console.log(` ${ansis.yellow("0.")} ${i18n.cometix.cometixMenuOptions.back}`);
708
+ console.log(` ${ansis.cyan("1.")} ${i18n.t("cometix:cometixMenuOptions.installOrUpdate")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.installOrUpdate")}`)}`);
709
+ console.log(` ${ansis.cyan("2.")} ${i18n.t("cometix:cometixMenuOptions.printConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.printConfig")}`)}`);
710
+ console.log(` ${ansis.cyan("3.")} ${i18n.t("cometix:cometixMenuOptions.customConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.customConfig")}`)}`);
711
+ console.log(` ${ansis.yellow("0.")} ${i18n.t("cometix:cometixMenuOptions.back")}`);
729
712
  console.log("");
730
713
  const { choice } = await inquirer.prompt({
731
714
  type: "input",
732
715
  name: "choice",
733
- message: i18n.common.enterChoice,
734
- validate: (value) => {
716
+ message: i18n.t("common:enterChoice"),
717
+ validate: async (value) => {
735
718
  const valid = ["1", "2", "3", "0"];
736
- return valid.includes(value) || i18n.common.invalidChoice;
719
+ return valid.includes(value) || i18n.t("common:invalidChoice");
737
720
  }
738
721
  });
739
722
  switch (choice) {
740
723
  case "1":
741
- await installCometixLine(scriptLang);
724
+ await installCometixLine();
742
725
  break;
743
726
  case "2":
744
- await runCometixPrintConfig(scriptLang);
727
+ await runCometixPrintConfig();
745
728
  break;
746
729
  case "3":
747
- await runCometixTuiConfig(scriptLang);
730
+ await runCometixTuiConfig();
748
731
  break;
749
732
  case "0":
750
733
  return false;
@@ -756,44 +739,40 @@ ${ansis.dim("\u2500".repeat(50))}
756
739
  const { continueInCometix } = await inquirer.prompt({
757
740
  type: "confirm",
758
741
  name: "continueInCometix",
759
- message: i18n.common.returnToMenu,
742
+ message: i18n.t("common:returnToMenu"),
760
743
  default: true
761
744
  });
762
745
  if (continueInCometix) {
763
- return await showCometixMenu(scriptLang);
746
+ return await showCometixMenu();
764
747
  }
765
748
  }
766
749
  return false;
767
750
  } catch (error) {
768
751
  if (!handleExitPromptError(error)) {
769
- handleGeneralError(error, scriptLang);
752
+ handleGeneralError(error);
770
753
  }
771
754
  return false;
772
755
  }
773
756
  }
774
757
 
775
- function getValidLanguage(lang) {
776
- return lang && lang in I18N ? lang : "en";
777
- }
778
- async function runCcusageFeature(scriptLang) {
779
- const validLang = getValidLanguage(scriptLang);
780
- const i18n = getTranslation(validLang);
758
+ async function runCcusageFeature() {
759
+ ensureI18nInitialized();
781
760
  console.log("");
782
- console.log(ansis.cyan(i18n.menu.menuOptions.ccusage));
783
- console.log(ansis.gray(`${i18n.tools.ccusageDescription}`));
761
+ console.log(ansis.cyan(i18n.t("menu:menuOptions.ccusage")));
762
+ console.log(ansis.gray(`${i18n.t("tools:ccusageDescription")}`));
784
763
  console.log("");
785
764
  const choices = [
786
- { name: i18n.tools.ccusageModes.daily, value: "daily" },
787
- { name: i18n.tools.ccusageModes.monthly, value: "monthly" },
788
- { name: i18n.tools.ccusageModes.session, value: "session" },
789
- { name: i18n.tools.ccusageModes.blocks, value: "blocks" },
790
- { name: i18n.tools.ccusageModes.custom, value: "custom" },
791
- { name: i18n.common.back, value: "back" }
765
+ { name: i18n.t("tools:ccusageModes.daily"), value: "daily" },
766
+ { name: i18n.t("tools:ccusageModes.monthly"), value: "monthly" },
767
+ { name: i18n.t("tools:ccusageModes.session"), value: "session" },
768
+ { name: i18n.t("tools:ccusageModes.blocks"), value: "blocks" },
769
+ { name: i18n.t("tools:ccusageModes.custom"), value: "custom" },
770
+ { name: i18n.t("common:back"), value: "back" }
792
771
  ];
793
772
  const { mode } = await inquirer.prompt({
794
773
  type: "list",
795
774
  name: "mode",
796
- message: i18n.tools.selectAnalysisMode,
775
+ message: i18n.t("tools:selectAnalysisMode"),
797
776
  choices: addNumbersToChoices(choices)
798
777
  });
799
778
  if (mode === "back") {
@@ -804,7 +783,7 @@ async function runCcusageFeature(scriptLang) {
804
783
  const { customArgs } = await inquirer.prompt({
805
784
  type: "input",
806
785
  name: "customArgs",
807
- message: i18n.tools.enterCustomArgs,
786
+ message: i18n.t("tools:enterCustomArgs"),
808
787
  default: ""
809
788
  });
810
789
  if (customArgs === null || customArgs === void 0 || customArgs === "") {
@@ -836,24 +815,21 @@ async function runCcusageFeature(scriptLang) {
836
815
  await inquirer.prompt({
837
816
  type: "input",
838
817
  name: "continue",
839
- message: ansis.gray(i18n.tools.pressEnterToContinue)
818
+ message: ansis.gray(i18n.t("tools:pressEnterToContinue"))
840
819
  });
841
820
  }
842
- async function runCcrMenuFeature(scriptLang) {
843
- const validLang = getValidLanguage(scriptLang);
844
- await showCcrMenu(validLang);
821
+ async function runCcrMenuFeature() {
822
+ await showCcrMenu();
845
823
  }
846
- async function runCometixMenuFeature(scriptLang) {
847
- const validLang = getValidLanguage(scriptLang);
848
- await showCometixMenu(validLang);
824
+ async function runCometixMenuFeature() {
825
+ await showCometixMenu();
849
826
  }
850
827
 
851
- async function checkUpdates(options = {}) {
852
- const scriptLang = options.lang || await selectScriptLanguage();
828
+ async function checkUpdates() {
853
829
  try {
854
- await checkAndUpdateTools(scriptLang);
830
+ await checkAndUpdateTools();
855
831
  } catch (error) {
856
- console.error(ansis.red("Error checking updates:"), error);
832
+ console.error(ansis.red(i18n.t("updater:errorCheckingUpdates")), error);
857
833
  process.exit(1);
858
834
  }
859
835
  }
@@ -861,38 +837,39 @@ async function checkUpdates(options = {}) {
861
837
  async function update(options = {}) {
862
838
  try {
863
839
  if (!options.skipBanner) {
864
- displayBanner("Update configuration for Claude Code");
840
+ displayBanner(i18n.t("cli:banner.updateSubtitle"));
865
841
  }
866
- const scriptLang = await selectScriptLanguage();
867
842
  const zcfConfig = readZcfConfig();
868
- const i18n = I18N[scriptLang];
869
843
  let configLang = options.configLang;
870
844
  if (!configLang) {
845
+ const LANG_HINT_KEYS = {
846
+ "zh-CN": i18n.t("language:configLangHint.zh-CN"),
847
+ "en": i18n.t("language:configLangHint.en")
848
+ };
871
849
  const { lang } = await inquirer.prompt({
872
850
  type: "list",
873
851
  name: "lang",
874
- message: i18n.language.updateConfigLangPrompt,
852
+ message: i18n.t("language:updateConfigLangPrompt"),
875
853
  choices: addNumbersToChoices(SUPPORTED_LANGS.map((l) => ({
876
- name: `${LANG_LABELS[l]} - ${i18n.language.configLangHint[l]}`,
854
+ name: `${LANG_LABELS[l]} - ${LANG_HINT_KEYS[l]}`,
877
855
  value: l
878
856
  })))
879
857
  });
880
858
  if (!lang) {
881
- console.log(ansis.yellow(i18n.common.cancelled));
859
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
882
860
  process.exit(0);
883
861
  }
884
862
  configLang = lang;
885
863
  }
886
- const aiOutputLang = await resolveAiOutputLanguage(scriptLang, options.aiOutputLang, zcfConfig);
864
+ const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig);
887
865
  console.log(ansis.cyan(`
888
- ${i18n.configuration.updatingPrompts}
866
+ ${i18n.t("configuration:updatingPrompts")}
889
867
  `));
890
- await updatePromptOnly(configLang, scriptLang, aiOutputLang);
891
- await selectAndInstallWorkflows(configLang, scriptLang);
892
- await checkClaudeCodeVersionAndPrompt(scriptLang, false);
868
+ await updatePromptOnly(aiOutputLang);
869
+ await selectAndInstallWorkflows(configLang);
870
+ await checkClaudeCodeVersionAndPrompt(false);
893
871
  updateZcfConfig({
894
872
  version,
895
- preferredLang: scriptLang,
896
873
  aiOutputLang
897
874
  });
898
875
  } catch (error) {
@@ -905,136 +882,131 @@ ${i18n.configuration.updatingPrompts}
905
882
  async function showMainMenu() {
906
883
  try {
907
884
  displayBannerWithInfo();
908
- const zcfConfig = await readZcfConfigAsync();
909
- let scriptLang = zcfConfig?.preferredLang || await selectScriptLanguage();
910
885
  let exitMenu = false;
911
886
  while (!exitMenu) {
912
- const i18n = I18N[scriptLang];
913
- console.log(ansis.cyan(i18n.menu.selectFunction));
887
+ console.log(ansis.cyan(i18n.t("menu:selectFunction")));
914
888
  console.log(" -------- Claude Code --------");
915
889
  console.log(
916
- ` ${ansis.cyan("1.")} ${i18n.menu.menuOptions.fullInit} ${ansis.gray(`- ${i18n.menu.menuDescriptions.fullInit}`)}`
890
+ ` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.fullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.fullInit")}`)}`
917
891
  );
918
892
  console.log(
919
- ` ${ansis.cyan("2.")} ${i18n.menu.menuOptions.importWorkflow} ${ansis.gray(
920
- `- ${i18n.menu.menuDescriptions.importWorkflow}`
893
+ ` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.importWorkflow")} ${ansis.gray(
894
+ `- ${i18n.t("menu:menuDescriptions.importWorkflow")}`
921
895
  )}`
922
896
  );
923
897
  console.log(
924
- ` ${ansis.cyan("3.")} ${i18n.menu.menuOptions.configureApiOrCcr} ${ansis.gray(
925
- `- ${i18n.menu.menuDescriptions.configureApiOrCcr}`
898
+ ` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.configureApiOrCcr")} ${ansis.gray(
899
+ `- ${i18n.t("menu:menuDescriptions.configureApiOrCcr")}`
926
900
  )}`
927
901
  );
928
902
  console.log(
929
- ` ${ansis.cyan("4.")} ${i18n.menu.menuOptions.configureMcp} ${ansis.gray(
930
- `- ${i18n.menu.menuDescriptions.configureMcp}`
903
+ ` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.configureMcp")} ${ansis.gray(
904
+ `- ${i18n.t("menu:menuDescriptions.configureMcp")}`
931
905
  )}`
932
906
  );
933
907
  console.log(
934
- ` ${ansis.cyan("5.")} ${i18n.menu.menuOptions.configureModel} ${ansis.gray(
935
- `- ${i18n.menu.menuDescriptions.configureModel}`
908
+ ` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.configureModel")} ${ansis.gray(
909
+ `- ${i18n.t("menu:menuDescriptions.configureModel")}`
936
910
  )}`
937
911
  );
938
912
  console.log(
939
- ` ${ansis.cyan("6.")} ${i18n.menu.menuOptions.configureAiMemory} ${ansis.gray(
940
- `- ${i18n.menu.menuDescriptions.configureAiMemory}`
913
+ ` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.configureAiMemory")} ${ansis.gray(
914
+ `- ${i18n.t("menu:menuDescriptions.configureAiMemory")}`
941
915
  )}`
942
916
  );
943
917
  console.log(
944
- ` ${ansis.cyan("7.")} ${i18n.menu.menuOptions.configureEnvPermission} ${ansis.gray(
945
- `- ${i18n.menu.menuDescriptions.configureEnvPermission}`
918
+ ` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(
919
+ `- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`
946
920
  )}`
947
921
  );
948
922
  console.log("");
949
- console.log(` --------- ${i18n.menu.menuSections.otherTools} ----------`);
923
+ console.log(` --------- ${i18n.t("menu:menuSections.otherTools")} ----------`);
950
924
  console.log(
951
- ` ${ansis.cyan("R.")} ${i18n.menu.menuOptions.ccrManagement} ${ansis.gray(`- ${i18n.menu.menuDescriptions.ccrManagement}`)}`
925
+ ` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}`
952
926
  );
953
927
  console.log(
954
- ` ${ansis.cyan("U.")} ${i18n.menu.menuOptions.ccusage} ${ansis.gray(`- ${i18n.menu.menuDescriptions.ccusage}`)}`
928
+ ` ${ansis.cyan("U.")} ${i18n.t("menu:menuOptions.ccusage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccusage")}`)}`
955
929
  );
956
930
  console.log(
957
- ` ${ansis.cyan("L.")} ${i18n.menu.menuOptions.cometixLine} ${ansis.gray(`- ${i18n.menu.menuDescriptions.cometixLine}`)}`
931
+ ` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}`
958
932
  );
959
933
  console.log("");
960
934
  console.log(" ------------ ZCF ------------");
961
935
  console.log(
962
- ` ${ansis.cyan("0.")} ${i18n.menu.menuOptions.changeLanguage} ${ansis.gray(
963
- `- ${i18n.menu.menuDescriptions.changeLanguage}`
936
+ ` ${ansis.cyan("0.")} ${i18n.t("menu:menuOptions.changeLanguage")} ${ansis.gray(
937
+ `- ${i18n.t("menu:menuDescriptions.changeLanguage")}`
964
938
  )}`
965
939
  );
966
940
  console.log(
967
- ` ${ansis.cyan("-.")} ${i18n.menu.menuOptions.clearCache} ${ansis.gray(`- ${i18n.menu.menuDescriptions.clearCache}`)}`
941
+ ` ${ansis.cyan("-.")} ${i18n.t("menu:menuOptions.clearCache")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.clearCache")}`)}`
968
942
  );
969
943
  console.log(
970
- ` ${ansis.cyan("+.")} ${i18n.menu.menuOptions.checkUpdates} ${ansis.gray(`- ${i18n.menu.menuDescriptions.checkUpdates}`)}`
944
+ ` ${ansis.cyan("+.")} ${i18n.t("menu:menuOptions.checkUpdates")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.checkUpdates")}`)}`
971
945
  );
972
- console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.menu.menuOptions.exit)}`);
946
+ console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.t("menu:menuOptions.exit"))}`);
973
947
  console.log("");
974
948
  const { choice } = await inquirer.prompt({
975
949
  type: "input",
976
950
  name: "choice",
977
- message: i18n.common.enterChoice,
951
+ message: i18n.t("common:enterChoice"),
978
952
  validate: (value) => {
979
953
  const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "q", "Q"];
980
- return valid.includes(value) || i18n.common.invalidChoice;
954
+ return valid.includes(value) || i18n.t("common:invalidChoice");
981
955
  }
982
956
  });
983
957
  if (!choice) {
984
- console.log(ansis.yellow(i18n.common.cancelled));
958
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
985
959
  exitMenu = true;
986
960
  break;
987
961
  }
988
962
  switch (choice.toLowerCase()) {
989
963
  case "1":
990
- await init({ lang: scriptLang, skipBanner: true });
964
+ await init({ skipBanner: true });
991
965
  break;
992
966
  case "2":
993
967
  await update({ skipBanner: true });
994
968
  break;
995
969
  case "3":
996
- await configureApiFeature(scriptLang);
970
+ await configureApiFeature();
997
971
  break;
998
972
  case "4":
999
- await configureMcpFeature(scriptLang);
973
+ await configureMcpFeature();
1000
974
  break;
1001
975
  case "5":
1002
- await configureDefaultModelFeature(scriptLang);
976
+ await configureDefaultModelFeature();
1003
977
  break;
1004
978
  case "6":
1005
- await configureAiMemoryFeature(scriptLang);
979
+ await configureAiMemoryFeature();
1006
980
  break;
1007
981
  case "7":
1008
- await configureEnvPermissionFeature(scriptLang);
982
+ await configureEnvPermissionFeature();
1009
983
  break;
1010
984
  case "r":
1011
985
  case "R":
1012
- await runCcrMenuFeature(scriptLang);
986
+ await runCcrMenuFeature();
1013
987
  break;
1014
988
  case "u":
1015
989
  case "U":
1016
- await runCcusageFeature(scriptLang);
990
+ await runCcusageFeature();
1017
991
  break;
1018
992
  case "l":
1019
993
  case "L":
1020
- await runCometixMenuFeature(scriptLang);
994
+ await runCometixMenuFeature();
1021
995
  break;
1022
996
  case "0": {
1023
- const newLang = await changeScriptLanguageFeature(scriptLang);
1024
- if (newLang !== scriptLang) {
1025
- scriptLang = newLang;
1026
- }
997
+ const currentLang = i18n.language;
998
+ await changeScriptLanguageFeature(currentLang);
1027
999
  break;
1028
1000
  }
1029
1001
  case "-":
1030
- await clearZcfCacheFeature(scriptLang);
1002
+ await clearZcfCacheFeature();
1031
1003
  break;
1032
1004
  case "+":
1033
- await checkUpdates({ lang: scriptLang });
1005
+ await checkUpdates();
1034
1006
  break;
1035
1007
  case "q":
1036
1008
  exitMenu = true;
1037
- console.log(ansis.cyan(i18n.common.goodbye));
1009
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
1038
1010
  break;
1039
1011
  }
1040
1012
  if (!exitMenu && choice.toLowerCase() !== "q") {
@@ -1050,12 +1022,12 @@ ${ansis.dim("\u2500".repeat(50))}
1050
1022
  const { continue: shouldContinue } = await inquirer.prompt({
1051
1023
  type: "confirm",
1052
1024
  name: "continue",
1053
- message: i18n.common.returnToMenu,
1025
+ message: i18n.t("common:returnToMenu"),
1054
1026
  default: true
1055
1027
  });
1056
1028
  if (!shouldContinue) {
1057
1029
  exitMenu = true;
1058
- console.log(ansis.cyan(i18n.common.goodbye));
1030
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
1059
1031
  }
1060
1032
  }
1061
1033
  }
@@ -1071,73 +1043,43 @@ async function ccr(options = {}) {
1071
1043
  if (!options.skipBanner) {
1072
1044
  displayBannerWithInfo();
1073
1045
  }
1074
- const zcfConfig = await readZcfConfigAsync();
1075
- const scriptLang = options.lang || zcfConfig?.preferredLang || await selectScriptLanguage();
1076
- const continueInCcr = await showCcrMenu(scriptLang);
1046
+ const continueInCcr = await showCcrMenu();
1077
1047
  if (!continueInCcr && !options.skipBanner) {
1078
1048
  await showMainMenu();
1079
1049
  }
1080
1050
  } catch (error) {
1081
1051
  if (!handleExitPromptError(error)) {
1082
- handleGeneralError(error, options.lang);
1052
+ handleGeneralError(error);
1083
1053
  }
1084
1054
  }
1085
1055
  }
1086
1056
 
1087
- function setupCommands(cli) {
1088
- cli.command("[lang]", "Show interactive menu (default)").option("--init", "Run full initialization directly").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").action(async (lang, options) => {
1089
- await handleDefaultCommand(lang, options);
1090
- });
1091
- 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), default: 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("--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, default: all').option("--workflows, -w <workflows>", 'Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, default: 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, default: all').option("--default-output-style, -d <style>", "Default output style, default: engineer-professional").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--install-cometix-line, -x <value>", "Install CCometixLine statusline tool (true/false), default: true").action(async (options) => {
1092
- await handleInitCommand(options);
1093
- });
1094
- cli.command("update", "Update Claude Code prompts only").alias("u").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").action(async (options) => {
1095
- await handleUpdateCommand(options);
1096
- });
1097
- cli.command("ccr", "Configure Claude Code Router for model proxy").option("--lang, -l <lang>", "Display language (zh-CN, en)").action(async (options) => {
1098
- await ccr({ lang: options.lang });
1099
- });
1100
- cli.command("ccu [...args]", "Run Claude Code usage analysis tool").allowUnknownOptions().action(async (args) => {
1101
- await executeCcusage(args);
1102
- });
1103
- cli.command("check-updates", "Check and update Claude Code and CCR to latest versions").alias("check").option("--lang, -l <lang>", "Display language (zh-CN, en)").action(async (options) => {
1104
- await checkUpdates({ lang: options.lang });
1105
- });
1106
- cli.help((sections) => customizeHelp(sections));
1107
- cli.version(version);
1108
- }
1109
- async function handleDefaultCommand(lang, options) {
1110
- if (options.init) {
1111
- await init({
1112
- lang: lang || options.lang,
1113
- configLang: options.configLang,
1114
- force: options.force
1115
- });
1116
- } else {
1117
- await showMainMenu();
1057
+ async function resolveAndSwitchLanguage(lang, options, skipPrompt = false) {
1058
+ const zcfConfig = await readZcfConfigAsync();
1059
+ const targetLang = options?.allLang || lang || options?.lang || zcfConfig?.preferredLang || (skipPrompt ? "en" : await selectScriptLanguage());
1060
+ if (i18n.isInitialized && i18n.language !== targetLang) {
1061
+ await changeLanguage(targetLang);
1118
1062
  }
1063
+ return targetLang;
1119
1064
  }
1120
- async function handleInitCommand(options) {
1121
- await init({
1122
- lang: options.lang,
1123
- configLang: options.configLang,
1124
- aiOutputLang: options.aiOutputLang,
1125
- force: options.force,
1126
- skipPrompt: options.skipPrompt,
1127
- configAction: options.configAction,
1128
- apiType: options.apiType,
1129
- apiKey: options.apiKey,
1130
- apiUrl: options.apiUrl,
1131
- mcpServices: options.mcpServices,
1132
- workflows: options.workflows,
1133
- outputStyles: options.outputStyles,
1134
- defaultOutputStyle: options.defaultOutputStyle,
1135
- allLang: options.allLang,
1136
- installCometixLine: options.installCometixLine
1137
- });
1065
+ async function withLanguageResolution(action, skipPrompt = false) {
1066
+ return async (...args) => {
1067
+ const options = args[0];
1068
+ const languageOptions = extractLanguageOptions(options);
1069
+ await resolveAndSwitchLanguage(void 0, languageOptions, skipPrompt || languageOptions.skipPrompt);
1070
+ return await action(...args);
1071
+ };
1138
1072
  }
1139
- async function handleUpdateCommand(options) {
1140
- await update({ configLang: options.configLang });
1073
+ function extractLanguageOptions(options) {
1074
+ if (!options || typeof options !== "object" || options === null) {
1075
+ return {};
1076
+ }
1077
+ const obj = options;
1078
+ return {
1079
+ lang: typeof obj.lang === "string" ? obj.lang : void 0,
1080
+ allLang: typeof obj.allLang === "string" ? obj.allLang : void 0,
1081
+ skipPrompt: typeof obj.skipPrompt === "boolean" ? obj.skipPrompt : void 0
1082
+ };
1141
1083
  }
1142
1084
  function customizeHelp(sections) {
1143
1085
  sections.unshift({
@@ -1145,89 +1087,112 @@ function customizeHelp(sections) {
1145
1087
  body: ansis.cyan.bold(`ZCF - Zero-Config Claude-Code Flow v${version}`)
1146
1088
  });
1147
1089
  sections.push({
1148
- title: ansis.yellow("Commands / \u547D\u4EE4:"),
1090
+ title: ansis.yellow(i18n.t("cli:help.commands")),
1149
1091
  body: [
1150
- ` ${ansis.cyan("zcf")} Show interactive menu (default) / \u663E\u793A\u4EA4\u4E92\u5F0F\u83DC\u5355\uFF08\u9ED8\u8BA4\uFF09`,
1092
+ ` ${ansis.cyan("zcf")} ${i18n.t("cli:help.commandDescriptions.showInteractiveMenuDefault")}`,
1151
1093
  ` ${ansis.cyan("zcf init")} | ${ansis.cyan(
1152
1094
  "i"
1153
- )} Initialize Claude Code configuration / \u521D\u59CB\u5316 Claude Code \u914D\u7F6E`,
1154
- ` ${ansis.cyan("zcf update")} | ${ansis.cyan("u")} Update workflow-related md files / \u4EC5\u66F4\u65B0\u5DE5\u4F5C\u6D41\u76F8\u5173md`,
1155
- ` ${ansis.cyan("zcf ccr")} Configure Claude Code Router for model proxy / \u914D\u7F6E\u6A21\u578B\u8DEF\u7531\u4EE3\u7406`,
1156
- ` ${ansis.cyan("zcf ccu")} [args] Claude Code usage statistics analysis / Claude Code \u7528\u91CF\u7EDF\u8BA1\u5206\u6790`,
1157
- ` ${ansis.cyan("zcf check-updates")} Check and update to latest versions / \u68C0\u67E5\u5E76\u66F4\u65B0\u5230\u6700\u65B0\u7248\u672C`,
1095
+ )} ${i18n.t("cli:help.commandDescriptions.initClaudeCodeConfig")}`,
1096
+ ` ${ansis.cyan("zcf update")} | ${ansis.cyan("u")} ${i18n.t("cli:help.commandDescriptions.updateWorkflowFiles")}`,
1097
+ ` ${ansis.cyan("zcf ccr")} ${i18n.t("cli:help.commandDescriptions.configureCcrProxy")}`,
1098
+ ` ${ansis.cyan("zcf ccu")} [args] ${i18n.t("cli:help.commandDescriptions.claudeCodeUsageAnalysis")}`,
1099
+ ` ${ansis.cyan("zcf check-updates")} ${i18n.t("cli:help.commandDescriptions.checkUpdateVersions")}`,
1158
1100
  "",
1159
- ansis.gray(" Shortcuts / \u5FEB\u6377\u65B9\u5F0F:"),
1160
- ` ${ansis.cyan("zcf i")} Quick init / \u5FEB\u901F\u521D\u59CB\u5316`,
1161
- ` ${ansis.cyan("zcf u")} Quick update / \u5FEB\u901F\u66F4\u65B0`,
1162
- ` ${ansis.cyan("zcf check")} Quick check updates / \u5FEB\u901F\u68C0\u67E5\u66F4\u65B0`
1101
+ ansis.gray(` ${i18n.t("cli:help.shortcuts")}`),
1102
+ ` ${ansis.cyan("zcf i")} ${i18n.t("cli:help.shortcutDescriptions.quickInit")}`,
1103
+ ` ${ansis.cyan("zcf u")} ${i18n.t("cli:help.shortcutDescriptions.quickUpdate")}`,
1104
+ ` ${ansis.cyan("zcf check")} ${i18n.t("cli:help.shortcutDescriptions.quickCheckUpdates")}`
1163
1105
  ].join("\n")
1164
1106
  });
1165
1107
  sections.push({
1166
- title: ansis.yellow("Options / \u9009\u9879:"),
1108
+ title: ansis.yellow(i18n.t("cli:help.options")),
1167
1109
  body: [
1168
- ` ${ansis.green("--init")} Run full initialization directly / \u76F4\u63A5\u8FD0\u884C\u5B8C\u6574\u521D\u59CB\u5316`,
1169
- ` ${ansis.green("--lang, -l")} <lang> Display language / \u663E\u793A\u8BED\u8A00 (zh-CN, en)`,
1170
- ` ${ansis.green("--config-lang, -c")} <lang> Configuration language / \u914D\u7F6E\u8BED\u8A00 (zh-CN, en)`,
1171
- ` ${ansis.green("--force, -f")} Force overwrite / \u5F3A\u5236\u8986\u76D6\u73B0\u6709\u914D\u7F6E`,
1172
- ` ${ansis.green("--help, -h")} Display help / \u663E\u793A\u5E2E\u52A9`,
1173
- ` ${ansis.green("--version, -v")} Display version / \u663E\u793A\u7248\u672C`,
1110
+ ` ${ansis.green("--lang, -l")} <lang> ${i18n.t("cli:help.optionDescriptions.displayLanguage")} (zh-CN, en)`,
1111
+ ` ${ansis.green("--config-lang, -c")} <lang> ${i18n.t("cli:help.optionDescriptions.configurationLanguage")} (zh-CN, en)`,
1112
+ ` ${ansis.green("--force, -f")} ${i18n.t("cli:help.optionDescriptions.forceOverwrite")}`,
1113
+ ` ${ansis.green("--help, -h")} ${i18n.t("cli:help.optionDescriptions.displayHelp")}`,
1114
+ ` ${ansis.green("--version, -v")} ${i18n.t("cli:help.optionDescriptions.displayVersion")}`,
1174
1115
  "",
1175
- ansis.gray(" Non-interactive mode (for CI/CD) / \u975E\u4EA4\u4E92\u6A21\u5F0F\uFF08\u9002\u7528\u4E8ECI/CD\uFF09:"),
1176
- ` ${ansis.green("--skip-prompt, -s")} Skip all prompts / \u8DF3\u8FC7\u6240\u6709\u4EA4\u4E92\u63D0\u793A`,
1177
- ` ${ansis.green("--api-type, -t")} <type> API type / API\u7C7B\u578B (auth_token, api_key, ccr_proxy, skip)`,
1178
- ` ${ansis.green("--api-key, -k")} <key> API key (for both types) / API\u5BC6\u94A5\uFF08\u9002\u7528\u4E8E\u6240\u6709\u7C7B\u578B\uFF09`,
1179
- ` ${ansis.green("--api-url, -u")} <url> Custom API URL / \u81EA\u5B9A\u4E49API\u5730\u5740`,
1180
- ` ${ansis.green("--ai-output-lang, -a")} <lang> AI output language / AI\u8F93\u51FA\u8BED\u8A00`,
1181
- ` ${ansis.green("--all-lang, -g")} <lang> Set all language params / \u7EDF\u4E00\u8BBE\u7F6E\u6240\u6709\u8BED\u8A00\u53C2\u6570`,
1182
- ` ${ansis.green("--config-action, -r")} <action> Config handling / \u914D\u7F6E\u5904\u7406 (default: backup)`,
1183
- ` ${ansis.green("--mcp-services, -m")} <list> MCP services / MCP\u670D\u52A1 (default: all non-key services)`,
1184
- ` ${ansis.green("--workflows, -w")} <list> Workflows / \u5DE5\u4F5C\u6D41 (default: all workflows)`,
1185
- ` ${ansis.green("--output-styles, -o")} <styles> Output styles / \u8F93\u51FA\u6837\u5F0F (default: all custom styles)`,
1186
- ` ${ansis.green("--default-output-style, -d")} <style> Default output style / \u9ED8\u8BA4\u8F93\u51FA\u6837\u5F0F (default: engineer-professional)`,
1187
- ` ${ansis.green("--install-cometix-line, -x")} <value> Install statusline tool / \u5B89\u88C5\u72B6\u6001\u680F\u5DE5\u5177 (default: true)`
1116
+ ansis.gray(` ${i18n.t("cli:help.nonInteractiveMode")}`),
1117
+ ` ${ansis.green("--skip-prompt, -s")} ${i18n.t("cli:help.optionDescriptions.skipAllPrompts")}`,
1118
+ ` ${ansis.green("--api-type, -t")} <type> ${i18n.t("cli:help.optionDescriptions.apiType")} (auth_token, api_key, ccr_proxy, skip)`,
1119
+ ` ${ansis.green("--api-key, -k")} <key> ${i18n.t("cli:help.optionDescriptions.apiKey")}`,
1120
+ ` ${ansis.green("--api-url, -u")} <url> ${i18n.t("cli:help.optionDescriptions.customApiUrl")}`,
1121
+ ` ${ansis.green("--ai-output-lang, -a")} <lang> ${i18n.t("cli:help.optionDescriptions.aiOutputLanguage")}`,
1122
+ ` ${ansis.green("--all-lang, -g")} <lang> ${i18n.t("cli:help.optionDescriptions.setAllLanguageParams")}`,
1123
+ ` ${ansis.green("--config-action, -r")} <action> ${i18n.t("cli:help.optionDescriptions.configHandling")} (default: backup)`,
1124
+ ` ${ansis.green("--mcp-services, -m")} <list> ${i18n.t("cli:help.optionDescriptions.mcpServices")} (default: all non-key services)`,
1125
+ ` ${ansis.green("--workflows, -w")} <list> ${i18n.t("cli:help.optionDescriptions.workflows")} (default: all workflows)`,
1126
+ ` ${ansis.green("--output-styles, -o")} <styles> ${i18n.t("cli:help.optionDescriptions.outputStyles")} (default: all custom styles)`,
1127
+ ` ${ansis.green("--default-output-style, -d")} <style> ${i18n.t("cli:help.optionDescriptions.defaultOutputStyle")} (default: engineer-professional)`,
1128
+ ` ${ansis.green("--install-cometix-line, -x")} <value> ${i18n.t("cli:help.optionDescriptions.installStatuslineTool")} (default: true)`
1188
1129
  ].join("\n")
1189
1130
  });
1190
1131
  sections.push({
1191
- title: ansis.yellow("Examples / \u793A\u4F8B:"),
1132
+ title: ansis.yellow(i18n.t("cli:help.examples")),
1192
1133
  body: [
1193
- ansis.gray(" # Show interactive menu / \u663E\u793A\u4EA4\u4E92\u5F0F\u83DC\u5355"),
1134
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.showInteractiveMenu")}`),
1194
1135
  ` ${ansis.cyan("npx zcf")}`,
1195
1136
  "",
1196
- ansis.gray(" # Run full initialization / \u8FD0\u884C\u5B8C\u6574\u521D\u59CB\u5316"),
1137
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.runFullInitialization")}`),
1197
1138
  ` ${ansis.cyan("npx zcf init")}`,
1198
1139
  ` ${ansis.cyan("npx zcf i")}`,
1199
- ` ${ansis.cyan("npx zcf --init")}`,
1200
1140
  "",
1201
- ansis.gray(" # Update workflow-related md files only / \u4EC5\u66F4\u65B0\u5DE5\u4F5C\u6D41\u76F8\u5173md\u6587\u4EF6"),
1141
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.updateWorkflowFilesOnly")}`),
1202
1142
  ` ${ansis.cyan("npx zcf u")}`,
1203
1143
  "",
1204
- ansis.gray(" # Configure Claude Code Router / \u914D\u7F6E Claude Code Router"),
1144
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.configureClaudeCodeRouter")}`),
1205
1145
  ` ${ansis.cyan("npx zcf ccr")}`,
1206
1146
  "",
1207
- ansis.gray(" # Run Claude Code usage analysis / \u8FD0\u884C Claude Code \u7528\u91CF\u5206\u6790"),
1147
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.runClaudeCodeUsageAnalysis")}`),
1208
1148
  ` ${ansis.cyan("npx zcf ccu")} ${ansis.gray("# Daily usage (default)")}`,
1209
1149
  ` ${ansis.cyan("npx zcf ccu monthly --json")}`,
1210
1150
  "",
1211
- ansis.gray(" # Check and update tools / \u68C0\u67E5\u5E76\u66F4\u65B0\u5DE5\u5177"),
1151
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkAndUpdateTools")}`),
1212
1152
  ` ${ansis.cyan("npx zcf check-updates")} ${ansis.gray("# Update Claude Code, CCR and CCometixLine")}`,
1213
1153
  ` ${ansis.cyan("npx zcf check")}`,
1214
1154
  "",
1215
- ansis.gray(" # Non-interactive mode (CI/CD) / \u975E\u4EA4\u4E92\u6A21\u5F0F\uFF08CI/CD\uFF09"),
1155
+ ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.nonInteractiveModeCicd")}`),
1216
1156
  ` ${ansis.cyan('npx zcf i --skip-prompt --api-type api_key --api-key "sk-ant-..."')}`,
1217
1157
  ` ${ansis.cyan('npx zcf i --skip-prompt --all-lang zh-CN --api-type api_key --api-key "key"')}`,
1218
1158
  ` ${ansis.cyan("npx zcf i --skip-prompt --api-type ccr_proxy")}`,
1219
- "",
1220
- ansis.gray(" # Force overwrite with Chinese config / \u5F3A\u5236\u4F7F\u7528\u4E2D\u6587\u914D\u7F6E\u8986\u76D6"),
1221
- ` ${ansis.cyan("npx zcf --init -c zh-CN -f")}`,
1222
- ` ${ansis.cyan("npx zcf --init --config-lang zh-CN --force")}`
1159
+ ""
1223
1160
  ].join("\n")
1224
1161
  });
1225
1162
  return sections;
1226
1163
  }
1164
+ async function setupCommands(cli) {
1165
+ try {
1166
+ const zcfConfig = await readZcfConfigAsync();
1167
+ const defaultLang = zcfConfig?.preferredLang || "en";
1168
+ await initI18n(defaultLang);
1169
+ } catch {
1170
+ }
1171
+ 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").action(await withLanguageResolution(async () => {
1172
+ await showMainMenu();
1173
+ }));
1174
+ 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), default: 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("--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, default: all').option("--workflows, -w <workflows>", 'Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, default: 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, default: all').option("--default-output-style, -d <style>", "Default output style, default: engineer-professional").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--install-cometix-line, -x <value>", "Install CCometixLine statusline tool (true/false), default: true").action(await withLanguageResolution(async (options) => {
1175
+ await init(options);
1176
+ }));
1177
+ 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) => {
1178
+ await update(options);
1179
+ }));
1180
+ 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 () => {
1181
+ await ccr();
1182
+ }));
1183
+ 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) => {
1184
+ await executeCcusage(args);
1185
+ }));
1186
+ 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").action(await withLanguageResolution(async () => {
1187
+ await checkUpdates();
1188
+ }));
1189
+ cli.help((sections) => customizeHelp(sections));
1190
+ cli.version(version);
1191
+ }
1227
1192
 
1228
1193
  async function main() {
1229
1194
  const cli = cac("zcf");
1230
- setupCommands(cli);
1195
+ await setupCommands(cli);
1231
1196
  cli.parse();
1232
1197
  }
1233
1198
  main().catch(console.error);