zcf 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 UfoMiao
3
+ Copyright (c) 2025 UfoMiao & WitMiao
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -6,22 +6,23 @@
6
6
 
7
7
  **中文** | [English](README_EN.md)
8
8
 
9
- > 零配置,一键搞定 Claude Code 环境设置 - 支持中英文双语配置、智能代理系统和个性化AI助手
9
+ > 零配置,一键搞定 Claude Code 环境设置 - 支持中英文双语配置、智能代理系统和个性化 AI 助手
10
10
 
11
11
  ![效果图](./src/assets/screenshot.webp)
12
12
 
13
13
  ## 🚀 快速开始
14
14
 
15
- ### 🎯 推荐:使用交互式菜单(v2.0新增)
15
+ ### 🎯 推荐:使用交互式菜单(v2.0 新增)
16
16
 
17
17
  ```bash
18
18
  npx zcf # 打开交互式菜单,根据你的需求选择操作
19
19
  ```
20
20
 
21
21
  菜单选项包括:
22
+
22
23
  - `1` 完整初始化(等同于 `zcf i`)
23
24
  - `2` 导入工作流(等同于 `zcf u`)
24
- - `3-6` 配置管理(API、MCP、模型、AI个性等)
25
+ - `3-6` 配置管理(API、MCP、模型、AI 个性等)
25
26
  - 更多功能选项...
26
27
 
27
28
  ### 或者,直接使用命令:
@@ -43,6 +44,7 @@ npx zcf → 选择 2 # 通过菜单执行工作流更新
43
44
  ```
44
45
 
45
46
  > **提示**:
47
+ >
46
48
  > - v2.0 起,`zcf` 默认打开交互式菜单,提供可视化操作界面
47
49
  > - 你可以通过菜单选择操作,也可以直接使用命令快捷执行
48
50
  > - `zcf i` = 完整初始化,`zcf u` = 仅更新工作流
@@ -86,7 +88,7 @@ npx zcf → 选择 2 # 通过菜单执行工作流更新
86
88
  - 使用 npm 进行自动安装(确保兼容性)
87
89
  - 跨平台支持(Windows/macOS/Linux)
88
90
  - 自动配置 MCP 服务
89
- - 智能配置合并和部分修改支持(v2.0新增)
91
+ - 智能配置合并和部分修改支持(v2.0 新增)
90
92
 
91
93
  ### 📦 完整配置
92
94
 
@@ -102,17 +104,17 @@ npx zcf → 选择 2 # 通过菜单执行工作流更新
102
104
  - **API Key**:适用于从 Anthropic Console 获取的 API 密钥
103
105
  - 自定义 API URL 支持
104
106
  - 支持稍后在 claude 命令中配置
105
- - 部分修改功能:仅更新需要的配置项(v2.0新增)
107
+ - 部分修改功能:仅更新需要的配置项(v2.0 新增)
106
108
 
107
109
  ### 💾 配置管理
108
110
 
109
111
  - 智能备份现有配置(所有备份保存在 ~/.claude/backup/)
110
- - 配置合并选项(v2.0增强:支持深度合并)
112
+ - 配置合并选项(v2.0 增强:支持深度合并)
111
113
  - 安全的覆盖机制
112
114
  - MCP 配置修改前自动备份
113
- - 默认模型配置(v2.0新增)
114
- - AI 记忆管理(v2.0新增)
115
- - ZCF 缓存清理(v2.0新增)
115
+ - 默认模型配置(v2.0 新增)
116
+ - AI 记忆管理(v2.0 新增)
117
+ - ZCF 缓存清理(v2.0 新增)
116
118
 
117
119
  ## 📖 使用说明
118
120
 
@@ -135,7 +137,7 @@ $ npx zcf
135
137
  4. 配置 MCP 服务 - 管理 MCP 集成
136
138
  5. 配置默认模型 - 设置默认 AI 模型
137
139
  6. 配置 AI 个性 - 设置 AI 助手人格
138
-
140
+
139
141
  ------------ ZCF ------------
140
142
  0. 更改语言 - 切换界面语言
141
143
  -. 清理缓存 - 清理 ZCF 缓存文件
@@ -144,7 +146,7 @@ $ npx zcf
144
146
  请输入选择: _
145
147
  ```
146
148
 
147
- ### 完整初始化流程(选择1或使用 `zcf i`)
149
+ ### 完整初始化流程(选择 1 或使用 `zcf i`)
148
150
 
149
151
  ```bash
150
152
  ? 选择 Claude Code 配置语言:
@@ -209,11 +211,11 @@ $ npx zcf
209
211
 
210
212
  #### 命令速查表
211
213
 
212
- | 命令 | 缩写 | 说明 |
213
- | ------------ | --------- | --------------------------------------- |
214
- | `zcf` | - | 显示交互式菜单(v2.0默认命令) |
215
- | `zcf init` | `zcf i` | 初始化 Claude Code 配置 |
216
- | `zcf update` | `zcf u` | 更新 Prompt 文档并备份旧配置 |
214
+ | 命令 | 缩写 | 说明 |
215
+ | ------------ | ------- | ------------------------------- |
216
+ | `zcf` | - | 显示交互式菜单(v2.0 默认命令) |
217
+ | `zcf init` | `zcf i` | 初始化 Claude Code 配置 |
218
+ | `zcf update` | `zcf u` | 更新 Prompt 文档并备份旧配置 |
217
219
 
218
220
  #### 常用选项
219
221
 
@@ -289,13 +291,13 @@ claude-code-config/
289
291
  └── dist/ # 构建输出
290
292
  ```
291
293
 
292
- ## ✨ 核心特性(v2.0增强)
294
+ ## ✨ 核心特性(v2.0 增强)
293
295
 
294
296
  ### 🤖 专业代理
295
297
 
296
298
  - **任务规划师**:将复杂任务拆解为可执行步骤
297
299
  - **UI/UX 设计师**:提供专业界面设计指导
298
- - **AI 个性化**:支持多种预设人格和自定义(v2.0新增)
300
+ - **AI 个性化**:支持多种预设人格和自定义(v2.0 新增)
299
301
 
300
302
  ### ⚡ 命令系统
301
303
 
@@ -307,19 +309,19 @@ claude-code-config/
307
309
  - API 密钥管理(支持部分修改)
308
310
  - 细粒度权限控制
309
311
  - 多种 Claude 模型支持(可配置默认模型)
310
- - 交互式菜单系统(v2.0新增)
311
- - AI 记忆管理(v2.0新增)
312
+ - 交互式菜单系统(v2.0 新增)
313
+ - AI 记忆管理(v2.0 新增)
312
314
 
313
315
  ## 🎯 开发工作流
314
316
 
315
317
  ### 六阶段工作流
316
318
 
317
- 1. **[模式:研究]** - 理解需求
318
- 2. **[模式:构思]** - 设计方案
319
- 3. **[模式:计划]** - 制定详细计划
320
- 4. **[模式:执行]** - 实施开发
321
- 5. **[模式:优化]** - 提升质量
322
- 6. **[模式:评审]** - 最终评估
319
+ 1. [模式:研究] - 理解需求
320
+ 2. [模式:构思] - 设计方案
321
+ 3. [模式:计划] - 制定详细计划
322
+ 4. [模式:执行] - 实施开发
323
+ 5. [模式:优化] - 提升质量
324
+ 6. [模式:评审] - 最终评估
323
325
 
324
326
  ## 🛠️ 开发
325
327
 
package/dist/cli.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import cac from 'cac';
3
2
  import ansis from 'ansis';
4
- import { z as displayBanner, B as selectScriptLanguage, D as readZcfConfig, I as I18N, S as SETTINGS_FILE, d as SUPPORTED_LANGS, L as LANG_LABELS, E as resolveAiOutputLanguage, F as updatePromptOnly, G as updateZcfConfig, H as version, Z as ZCF_CONFIG_FILE, p as applyAiLanguageDirective, J as configureAiPersonality, u as updateDefaultModel, K as isWindows, r as readMcpConfig, x as fixWindowsMcpConfig, w as writeMcpConfig, M as MCP_SERVICES, s as backupMcpConfig, v as buildMcpServerConfig, t as mergeMcpServers, o as getExistingApiConfig, N as formatApiKeyDisplay, O as modifyApiConfigPartially, P as validateApiKey, l as configureApi, Q as displayBannerWithInfo, i as init } from './shared/zcf.DGNSM22u.mjs';
5
- import prompts from '@posva/prompts';
3
+ import cac from 'cac';
4
+ import { d as SUPPORTED_LANGS, I as I18N, L as LANG_LABELS, z as updateZcfConfig, Z as ZCF_CONFIG_FILE, B as readZcfConfig, D as resolveAiOutputLanguage, p as applyAiLanguageDirective, E as configureAiPersonality, u as updateDefaultModel, F as isWindows, r as readMcpConfig, x as fixWindowsMcpConfig, w as writeMcpConfig, M as MCP_SERVICES, s as backupMcpConfig, v as buildMcpServerConfig, t as mergeMcpServers, o as getExistingApiConfig, G as formatApiKeyDisplay, H as modifyApiConfigPartially, J as validateApiKey, l as configureApi, K as displayBanner, N as selectScriptLanguage, S as SETTINGS_FILE, O as updatePromptOnly, P as version, Q as handleExitPromptError, R as handleGeneralError, T as displayBannerWithInfo, i as init } from './shared/zcf.ccfEwLWL.mjs';
5
+ import inquirer from 'inquirer';
6
6
  import { existsSync, unlinkSync } from 'node:fs';
7
7
  import 'node:os';
8
8
  import 'pathe';
@@ -10,57 +10,6 @@ import 'dayjs';
10
10
  import 'node:url';
11
11
  import 'tinyexec';
12
12
 
13
- async function update(options = {}) {
14
- try {
15
- if (!options.skipBanner) {
16
- displayBanner("Update configuration for Claude Code");
17
- }
18
- const scriptLang = await selectScriptLanguage();
19
- const zcfConfig = readZcfConfig();
20
- const i18n = I18N[scriptLang];
21
- if (!existsSync(SETTINGS_FILE)) {
22
- console.log(ansis.yellow(i18n.noExistingConfig));
23
- process.exit(1);
24
- }
25
- let configLang = options.configLang;
26
- if (!configLang) {
27
- console.log(ansis.dim(` ${i18n.configLangHint["zh-CN"]}`));
28
- console.log(ansis.dim(` ${i18n.configLangHint["en"]}
29
- `));
30
- const configResponse = await prompts({
31
- type: "select",
32
- name: "lang",
33
- message: i18n.updateConfigLangPrompt,
34
- choices: SUPPORTED_LANGS.map((l) => ({
35
- title: `${LANG_LABELS[l]} - ${i18n.configLangHint[l]}`,
36
- value: l
37
- }))
38
- });
39
- if (!configResponse.lang) {
40
- console.log(ansis.yellow(i18n.cancelled));
41
- process.exit(0);
42
- }
43
- configLang = configResponse.lang;
44
- }
45
- const aiOutputLang = await resolveAiOutputLanguage(scriptLang, options.aiOutputLang, zcfConfig);
46
- console.log(ansis.cyan(`
47
- ${i18n.updatingPrompts}
48
- `));
49
- await updatePromptOnly(configLang, scriptLang, aiOutputLang);
50
- updateZcfConfig({
51
- version,
52
- preferredLang: scriptLang,
53
- aiOutputLang
54
- });
55
- } catch (error) {
56
- const zcfConfig = readZcfConfig();
57
- const defaultLang = zcfConfig?.preferredLang || "en";
58
- const errorMsg = I18N[defaultLang].error;
59
- console.error(ansis.red(`${errorMsg}:`), error);
60
- process.exit(1);
61
- }
62
- }
63
-
64
13
  function handleCancellation(scriptLang) {
65
14
  console.log(ansis.yellow(I18N[scriptLang].cancelled));
66
15
  }
@@ -73,55 +22,51 @@ async function configureApiFeature(scriptLang) {
73
22
  console.log(ansis.gray(` ${i18n.apiConfigKey}: ${existingApiConfig.key ? formatApiKeyDisplay(existingApiConfig.key) : i18n.notConfigured}`));
74
23
  console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${existingApiConfig.authType || i18n.notConfigured}
75
24
  `));
76
- const actionResponse = await prompts({
77
- type: "select",
25
+ const { action } = await inquirer.prompt({
26
+ type: "list",
78
27
  name: "action",
79
28
  message: i18n.selectApiAction,
80
29
  choices: [
81
- { title: i18n.keepExistingConfig, value: "keep" },
82
- { title: i18n.modifyAllConfig, value: "modify-all" },
83
- { title: i18n.modifyPartialConfig, value: "modify-partial" }
30
+ { name: i18n.keepExistingConfig, value: "keep" },
31
+ { name: i18n.modifyAllConfig, value: "modify-all" },
32
+ { name: i18n.modifyPartialConfig, value: "modify-partial" }
84
33
  ]
85
34
  });
86
- if (!actionResponse.action) {
35
+ if (!action) {
87
36
  handleCancellation(scriptLang);
88
37
  return;
89
38
  }
90
- if (actionResponse.action === "keep") {
39
+ if (action === "keep") {
91
40
  console.log(ansis.green(`\u2714 ${i18n.keepExistingConfig}`));
92
41
  return;
93
- } else if (actionResponse.action === "modify-partial") {
42
+ } else if (action === "modify-partial") {
94
43
  await modifyApiConfigPartially(existingApiConfig, i18n, scriptLang);
95
44
  return;
96
45
  }
97
46
  }
98
- const apiResponse = await prompts({
99
- type: "select",
47
+ const { apiChoice } = await inquirer.prompt({
48
+ type: "list",
100
49
  name: "apiChoice",
101
50
  message: i18n.configureApi,
102
51
  choices: [
103
52
  {
104
- title: i18n.useAuthToken,
53
+ name: `${i18n.useAuthToken} - ${ansis.gray(i18n.authTokenDesc)}`,
105
54
  value: "auth_token",
106
- description: ansis.gray(i18n.authTokenDesc)
55
+ short: i18n.useAuthToken
107
56
  },
108
57
  {
109
- title: i18n.useApiKey,
58
+ name: `${i18n.useApiKey} - ${ansis.gray(i18n.apiKeyDesc)}`,
110
59
  value: "api_key",
111
- description: ansis.gray(i18n.apiKeyDesc)
60
+ short: i18n.useApiKey
112
61
  },
113
- {
114
- title: i18n.skipApi,
115
- value: "skip"
116
- }
62
+ { name: i18n.skipApi, value: "skip" }
117
63
  ]
118
64
  });
119
- if (!apiResponse.apiChoice || apiResponse.apiChoice === "skip") {
65
+ if (!apiChoice || apiChoice === "skip") {
120
66
  return;
121
67
  }
122
- const apiChoice = apiResponse.apiChoice;
123
- const urlResponse = await prompts({
124
- type: "text",
68
+ const { url } = await inquirer.prompt({
69
+ type: "input",
125
70
  name: "url",
126
71
  message: i18n.enterApiUrl,
127
72
  validate: (value) => {
@@ -134,13 +79,13 @@ async function configureApiFeature(scriptLang) {
134
79
  }
135
80
  }
136
81
  });
137
- if (!urlResponse.url) {
82
+ if (!url) {
138
83
  handleCancellation(scriptLang);
139
84
  return;
140
85
  }
141
86
  const keyMessage = apiChoice === "auth_token" ? i18n.enterAuthToken : i18n.enterApiKey;
142
- const keyResponse = await prompts({
143
- type: "text",
87
+ const { key } = await inquirer.prompt({
88
+ type: "input",
144
89
  name: "key",
145
90
  message: keyMessage,
146
91
  validate: (value) => {
@@ -154,11 +99,11 @@ async function configureApiFeature(scriptLang) {
154
99
  return true;
155
100
  }
156
101
  });
157
- if (!keyResponse.key) {
102
+ if (!key) {
158
103
  handleCancellation(scriptLang);
159
104
  return;
160
105
  }
161
- const apiConfig = { url: urlResponse.url, key: keyResponse.key, authType: apiChoice };
106
+ const apiConfig = { url, key, authType: apiChoice };
162
107
  const configuredApi = configureApi(apiConfig);
163
108
  if (configuredApi) {
164
109
  console.log(ansis.green(`\u2714 ${i18n.apiConfigSuccess}`));
@@ -169,13 +114,13 @@ async function configureApiFeature(scriptLang) {
169
114
  async function configureMcpFeature(scriptLang) {
170
115
  const i18n = I18N[scriptLang];
171
116
  if (isWindows()) {
172
- const fixResponse = await prompts({
117
+ const { fixWindows } = await inquirer.prompt({
173
118
  type: "confirm",
174
119
  name: "fixWindows",
175
120
  message: i18n.fixWindowsMcp || "Fix Windows MCP configuration?",
176
- initial: true
121
+ default: true
177
122
  });
178
- if (fixResponse.fixWindows) {
123
+ if (fixWindows) {
179
124
  const existingConfig = readMcpConfig() || { mcpServers: {} };
180
125
  const fixedConfig = fixWindowsMcpConfig(existingConfig);
181
126
  writeMcpConfig(fixedConfig);
@@ -194,18 +139,16 @@ async function configureMcpFeature(scriptLang) {
194
139
  selected: false
195
140
  }))
196
141
  ];
197
- const selectedResponse = await prompts({
198
- type: "multiselect",
142
+ const { services } = await inquirer.prompt({
143
+ type: "checkbox",
199
144
  name: "services",
200
- message: i18n.selectMcpServices,
201
- choices,
202
- instructions: false,
203
- hint: i18n.spaceToSelectReturn
145
+ message: i18n.selectMcpServices + " " + ansis.gray(i18n.spaceToSelectReturn),
146
+ choices
204
147
  });
205
- if (!selectedResponse.services) {
148
+ if (!services) {
206
149
  return;
207
150
  }
208
- let selectedServices = selectedResponse.services || [];
151
+ let selectedServices = services || [];
209
152
  if (selectedServices.includes("ALL")) {
210
153
  selectedServices = MCP_SERVICES.map((s) => s.id);
211
154
  }
@@ -220,14 +163,14 @@ async function configureMcpFeature(scriptLang) {
220
163
  if (!service) continue;
221
164
  let config = service.config;
222
165
  if (service.requiresApiKey) {
223
- const apiKeyResponse = await prompts({
224
- type: "text",
166
+ const { apiKey } = await inquirer.prompt({
167
+ type: "input",
225
168
  name: "apiKey",
226
169
  message: service.apiKeyPrompt[scriptLang],
227
170
  validate: (value) => !!value || i18n.keyRequired
228
171
  });
229
- if (apiKeyResponse.apiKey) {
230
- config = buildMcpServerConfig(service.config, apiKeyResponse.apiKey, service.apiKeyPlaceholder);
172
+ if (apiKey) {
173
+ config = buildMcpServerConfig(service.config, apiKey, service.apiKeyPlaceholder);
231
174
  } else {
232
175
  continue;
233
176
  }
@@ -243,43 +186,43 @@ async function configureMcpFeature(scriptLang) {
243
186
  }
244
187
  async function configureDefaultModelFeature(scriptLang) {
245
188
  const i18n = I18N[scriptLang];
246
- const modelResponse = await prompts({
247
- type: "select",
189
+ const { model } = await inquirer.prompt({
190
+ type: "list",
248
191
  name: "model",
249
192
  message: i18n.selectDefaultModel || "Select default model",
250
193
  choices: [
251
- { title: "Opus", value: "opus" },
252
- { title: "Sonnet", value: "sonnet" }
194
+ { name: "Opus", value: "opus" },
195
+ { name: "Sonnet", value: "sonnet" }
253
196
  ]
254
197
  });
255
- if (!modelResponse.model) {
198
+ if (!model) {
256
199
  handleCancellation(scriptLang);
257
200
  return;
258
201
  }
259
- updateDefaultModel(modelResponse.model);
202
+ updateDefaultModel(model);
260
203
  console.log(ansis.green(`\u2714 ${i18n.modelConfigSuccess || "Default model configured"}`));
261
204
  }
262
205
  async function configureAiMemoryFeature(scriptLang) {
263
206
  const i18n = I18N[scriptLang];
264
- const memoryResponse = await prompts({
265
- type: "select",
207
+ const { option } = await inquirer.prompt({
208
+ type: "list",
266
209
  name: "option",
267
210
  message: i18n.selectMemoryOption || "Select configuration option",
268
211
  choices: [
269
212
  {
270
- title: i18n.configureAiLanguage || "Configure AI output language",
213
+ name: i18n.configureAiLanguage || "Configure AI output language",
271
214
  value: "language"
272
215
  },
273
216
  {
274
- title: i18n.configureAiPersonality || "Configure AI personality",
217
+ name: i18n.configureAiPersonality || "Configure AI personality",
275
218
  value: "personality"
276
219
  }
277
220
  ]
278
221
  });
279
- if (!memoryResponse.option) {
222
+ if (!option) {
280
223
  return;
281
224
  }
282
- if (memoryResponse.option === "language") {
225
+ if (option === "language") {
283
226
  const zcfConfig = readZcfConfig();
284
227
  const aiOutputLang = await resolveAiOutputLanguage(scriptLang, void 0, zcfConfig);
285
228
  applyAiLanguageDirective(aiOutputLang);
@@ -291,13 +234,13 @@ async function configureAiMemoryFeature(scriptLang) {
291
234
  }
292
235
  async function clearZcfCacheFeature(scriptLang) {
293
236
  const i18n = I18N[scriptLang];
294
- const confirmResponse = await prompts({
237
+ const { confirm } = await inquirer.prompt({
295
238
  type: "confirm",
296
239
  name: "confirm",
297
240
  message: i18n.confirmClearCache || "Clear all ZCF preferences cache?",
298
- initial: false
241
+ default: false
299
242
  });
300
- if (!confirmResponse.confirm) {
243
+ if (!confirm) {
301
244
  handleCancellation(scriptLang);
302
245
  return;
303
246
  }
@@ -310,22 +253,71 @@ async function clearZcfCacheFeature(scriptLang) {
310
253
  }
311
254
  async function changeScriptLanguageFeature(currentLang) {
312
255
  const i18n = I18N[currentLang];
313
- const langResponse = await prompts({
314
- type: "select",
256
+ const { lang } = await inquirer.prompt({
257
+ type: "list",
315
258
  name: "lang",
316
259
  message: i18n.selectScriptLang,
317
260
  choices: SUPPORTED_LANGS.map((l) => ({
318
- title: LANG_LABELS[l],
261
+ name: LANG_LABELS[l],
319
262
  value: l
320
263
  })),
321
- initial: SUPPORTED_LANGS.indexOf(currentLang)
264
+ default: SUPPORTED_LANGS.indexOf(currentLang)
322
265
  });
323
- if (!langResponse.lang) {
266
+ if (!lang) {
324
267
  return currentLang;
325
268
  }
326
- updateZcfConfig({ preferredLang: langResponse.lang });
327
- console.log(ansis.green(`\u2714 ${I18N[langResponse.lang].languageChanged || "Language changed"}`));
328
- return langResponse.lang;
269
+ updateZcfConfig({ preferredLang: lang });
270
+ console.log(ansis.green(`\u2714 ${I18N[lang].languageChanged || "Language changed"}`));
271
+ return lang;
272
+ }
273
+
274
+ async function update(options = {}) {
275
+ try {
276
+ if (!options.skipBanner) {
277
+ displayBanner("Update configuration for Claude Code");
278
+ }
279
+ const scriptLang = await selectScriptLanguage();
280
+ const zcfConfig = readZcfConfig();
281
+ const i18n = I18N[scriptLang];
282
+ if (!existsSync(SETTINGS_FILE)) {
283
+ console.log(ansis.yellow(i18n.noExistingConfig));
284
+ process.exit(1);
285
+ }
286
+ let configLang = options.configLang;
287
+ if (!configLang) {
288
+ console.log(ansis.dim(` ${i18n.configLangHint["zh-CN"]}`));
289
+ console.log(ansis.dim(` ${i18n.configLangHint["en"]}
290
+ `));
291
+ const { lang } = await inquirer.prompt({
292
+ type: "list",
293
+ name: "lang",
294
+ message: i18n.updateConfigLangPrompt,
295
+ choices: SUPPORTED_LANGS.map((l) => ({
296
+ name: `${LANG_LABELS[l]} - ${i18n.configLangHint[l]}`,
297
+ value: l
298
+ }))
299
+ });
300
+ if (!lang) {
301
+ console.log(ansis.yellow(i18n.cancelled));
302
+ process.exit(0);
303
+ }
304
+ configLang = lang;
305
+ }
306
+ const aiOutputLang = await resolveAiOutputLanguage(scriptLang, options.aiOutputLang, zcfConfig);
307
+ console.log(ansis.cyan(`
308
+ ${i18n.updatingPrompts}
309
+ `));
310
+ await updatePromptOnly(configLang, scriptLang, aiOutputLang);
311
+ updateZcfConfig({
312
+ version,
313
+ preferredLang: scriptLang,
314
+ aiOutputLang
315
+ });
316
+ } catch (error) {
317
+ if (!handleExitPromptError(error)) {
318
+ handleGeneralError(error);
319
+ }
320
+ }
329
321
  }
330
322
 
331
323
  async function showMainMenu() {
@@ -378,8 +370,8 @@ async function showMainMenu() {
378
370
  );
379
371
  console.log(` ${ansis.red("q.")} ${ansis.red(i18n.menuOptions.exit)}`);
380
372
  console.log("");
381
- const response = await prompts({
382
- type: "text",
373
+ const { choice } = await inquirer.prompt({
374
+ type: "input",
383
375
  name: "choice",
384
376
  message: i18n.enterChoice || "Enter your choice",
385
377
  validate: (value) => {
@@ -387,12 +379,12 @@ async function showMainMenu() {
387
379
  return valid.includes(value) || i18n.invalidChoice;
388
380
  }
389
381
  });
390
- if (!response.choice) {
382
+ if (!choice) {
391
383
  console.log(ansis.yellow(i18n.cancelled));
392
384
  exitMenu = true;
393
385
  break;
394
386
  }
395
- switch (response.choice.toLowerCase()) {
387
+ switch (choice.toLowerCase()) {
396
388
  case "1":
397
389
  await init({ lang: scriptLang, skipBanner: true });
398
390
  break;
@@ -418,19 +410,6 @@ async function showMainMenu() {
418
410
  const newLang = await changeScriptLanguageFeature(scriptLang);
419
411
  if (newLang !== scriptLang) {
420
412
  scriptLang = newLang;
421
- console.log("\n" + ansis.dim("\u2500".repeat(50)) + "\n");
422
- const newI18n = I18N[scriptLang];
423
- const continueResponse = await prompts({
424
- type: "confirm",
425
- name: "continue",
426
- message: newI18n.returnToMenu,
427
- initial: true
428
- });
429
- if (!continueResponse.continue) {
430
- exitMenu = true;
431
- console.log(ansis.cyan(newI18n.goodbye));
432
- }
433
- continue;
434
413
  }
435
414
  break;
436
415
  case "q":
@@ -438,29 +417,28 @@ async function showMainMenu() {
438
417
  console.log(ansis.cyan(i18n.goodbye));
439
418
  break;
440
419
  }
441
- if (!exitMenu && response.choice.toLowerCase() !== "q") {
420
+ if (!exitMenu && choice.toLowerCase() !== "q") {
421
+ if (choice === "0" || choice === "-") {
422
+ console.log("\n" + ansis.dim("\u2500".repeat(50)) + "\n");
423
+ continue;
424
+ }
442
425
  console.log("\n" + ansis.dim("\u2500".repeat(50)) + "\n");
443
- const continueResponse = await prompts({
426
+ const { continue: shouldContinue } = await inquirer.prompt({
444
427
  type: "confirm",
445
428
  name: "continue",
446
429
  message: i18n.returnToMenu,
447
- initial: true
430
+ default: true
448
431
  });
449
- if (!continueResponse.continue) {
432
+ if (!shouldContinue) {
450
433
  exitMenu = true;
451
434
  console.log(ansis.cyan(i18n.goodbye));
452
435
  }
453
436
  }
454
437
  }
455
438
  } catch (error) {
456
- const zcfConfig = readZcfConfig();
457
- const defaultLang = zcfConfig?.preferredLang || "en";
458
- const errorMsg = I18N[defaultLang].error;
459
- console.error(ansis.red(`${errorMsg}:`), error);
460
- if (error instanceof Error) {
461
- console.error(ansis.gray(`Stack: ${error.stack}`));
439
+ if (!handleExitPromptError(error)) {
440
+ handleGeneralError(error);
462
441
  }
463
- process.exit(1);
464
442
  }
465
443
  }
466
444
 
@@ -496,7 +474,9 @@ cli.help((sections) => {
496
474
  title: ansis.yellow("Commands / \u547D\u4EE4:"),
497
475
  body: [
498
476
  ` ${ansis.cyan("zcf")} Show interactive menu (default) / \u663E\u793A\u4EA4\u4E92\u5F0F\u83DC\u5355\uFF08\u9ED8\u8BA4\uFF09`,
499
- ` ${ansis.cyan("zcf init")} | ${ansis.cyan("i")} Initialize Claude Code configuration / \u521D\u59CB\u5316 Claude Code \u914D\u7F6E`,
477
+ ` ${ansis.cyan("zcf init")} | ${ansis.cyan(
478
+ "i"
479
+ )} Initialize Claude Code configuration / \u521D\u59CB\u5316 Claude Code \u914D\u7F6E`,
500
480
  ` ${ansis.cyan("zcf update")} | ${ansis.cyan("u")} Update workflow-related md files / \u4EC5\u66F4\u65B0\u5DE5\u4F5C\u6D41\u76F8\u5173md`,
501
481
  "",
502
482
  ansis.gray(" Shortcuts / \u5FEB\u6377\u65B9\u5F0F:"),
package/dist/index.d.mts CHANGED
@@ -70,6 +70,10 @@ declare const I18N: {
70
70
  installSuccess: string;
71
71
  installFailed: string;
72
72
  npmNotFound: string;
73
+ termuxDetected: string;
74
+ termuxInstallHint: string;
75
+ termuxPathInfo: string;
76
+ termuxEnvironmentInfo: string;
73
77
  configureApi: string;
74
78
  useAuthToken: string;
75
79
  authTokenDesc: string;
@@ -224,6 +228,10 @@ declare const I18N: {
224
228
  installSuccess: string;
225
229
  installFailed: string;
226
230
  npmNotFound: string;
231
+ termuxDetected: string;
232
+ termuxInstallHint: string;
233
+ termuxPathInfo: string;
234
+ termuxEnvironmentInfo: string;
227
235
  configureApi: string;
228
236
  useAuthToken: string;
229
237
  authTokenDesc: string;
package/dist/index.d.ts CHANGED
@@ -70,6 +70,10 @@ declare const I18N: {
70
70
  installSuccess: string;
71
71
  installFailed: string;
72
72
  npmNotFound: string;
73
+ termuxDetected: string;
74
+ termuxInstallHint: string;
75
+ termuxPathInfo: string;
76
+ termuxEnvironmentInfo: string;
73
77
  configureApi: string;
74
78
  useAuthToken: string;
75
79
  authTokenDesc: string;
@@ -224,6 +228,10 @@ declare const I18N: {
224
228
  installSuccess: string;
225
229
  installFailed: string;
226
230
  npmNotFound: string;
231
+ termuxDetected: string;
232
+ termuxInstallHint: string;
233
+ termuxPathInfo: string;
234
+ termuxEnvironmentInfo: string;
227
235
  configureApi: string;
228
236
  useAuthToken: string;
229
237
  authTokenDesc: string;