zcf 2.8.0 → 2.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,8 +24,9 @@ Menu options include:
24
24
 
25
25
  - `1` Full initialization (equivalent to `zcf i`)
26
26
  - `2` Import workflows (equivalent to `zcf u`)
27
- - `3-7` Configuration management (API/CCR, MCP, Model, AI personality, etc.)
28
- - `R` Claude Code Router management (new feature)
27
+ - `3-7` Configuration management (API/CCR, MCP, Model settings, AI personality, etc.)
28
+ - `R` Claude Code Router management (enhanced in v2.8.1)
29
+ - `U` ccusage - Claude Code usage analysis
29
30
  - More features...
30
31
 
31
32
  ### Or, use direct commands:
@@ -54,7 +55,7 @@ npx zcf → select 2 # Execute workflow update via menu
54
55
 
55
56
  #### 🎯 BMad Workflow (v2.7 New Feature)
56
57
 
57
- BMad (Business-Minded Agile Development) is an enterprise-grade workflow system that provides:
58
+ [BMad](https://github.com/bmad-code-org/BMAD-METHOD) (BMad-Method: Universal AI Agent Framework) is an enterprise-grade workflow system that provides:
58
59
 
59
60
  - Complete team of specialized AI agents (PO, PM, Architect, Dev, QA, etc.)
60
61
  - Structured development process with quality gates
@@ -63,19 +64,28 @@ BMad (Business-Minded Agile Development) is an enterprise-grade workflow system
63
64
 
64
65
  After installation, use `/bmad-init` to initialize the BMad workflow in your project.
65
66
 
66
- #### 🚀 CCR (Claude Code Router) Support (v2.8 New Feature)
67
+ #### 🚀 CCR (Claude Code Router) Support (v2.8+ Enhanced)
67
68
 
68
- CCR is a powerful proxy router that enables:
69
+ [CCR](https://github.com/musistudio/claude-code-router/blob/main/README.md) is a powerful proxy router that enables:
69
70
 
70
71
  - **Free Model Access**: Use free AI models (like Gemini, DeepSeek) through Claude Code interface
71
72
  - **Custom Routing**: Route different types of requests to different models based on your rules
72
73
  - **Cost Optimization**: Significantly reduce API costs by using appropriate models for different tasks
73
74
  - **Easy Management**: Interactive menu for CCR configuration and service control
75
+ - **Auto Updates**: Automatic version checking and updates for CCR and Claude Code (v2.8.1+)
74
76
 
75
77
  To access CCR features:
76
78
 
77
79
  ```bash
78
80
  npx zcf ccr # Open CCR management menu
81
+ # or
82
+ npx zcf → select R
83
+ ```
84
+
85
+ Check for updates (v2.8.1+):
86
+
87
+ ```bash
88
+ npx zcf check-updates # Check and update Claude Code and CCR to latest versions
79
89
  ```
80
90
 
81
91
  CCR menu options:
@@ -163,7 +173,7 @@ After configuration:
163
173
  ```bash
164
174
  $ npx zcf
165
175
 
166
- ZCF - Zero-Config Claude-Code Flow v2.3.0
176
+ ZCF - Zero-Config Claude-Code Flow
167
177
 
168
178
  ? Select ZCF display language / 选择ZCF显示语言:
169
179
  ❯ 简体中文
@@ -179,10 +189,14 @@ Select function:
179
189
  6. Configure Claude global memory - Configure AI output language and personality
180
190
  7. Import recommended environment variables and permissions - Import privacy protection environment variables and system permissions
181
191
 
192
+ --------- Other Tools ----------
193
+ R. CCR Management - Claude Code Router management
194
+ U. CCUsage - Claude Code usage analysis tool
195
+
182
196
  ------------ ZCF ------------
183
197
  0. Select display language / 更改显示语言 - Change ZCF interface language
184
198
  -. Clear preference cache - Clear preference language and other caches
185
- q. Exit
199
+ Q. Exit
186
200
 
187
201
  Enter your choice: _
188
202
  ```
@@ -268,13 +282,13 @@ Enter your choice: _
268
282
 
269
283
  #### Commands Quick Reference
270
284
 
271
- | Command | Alias | Description |
272
- | ------------ | ------- | --------------------------------------------- |
273
- | `zcf` | - | Show interactive menu (v2.0 default command) |
274
- | `zcf init` | `zcf i` | Initialize Claude Code configuration |
275
- | `zcf update` | `zcf u` | Update workflow-related md files with backup |
276
- | `zcf ccu` | - | Run Claude Code usage analysis tool |
277
- | `zcf ccr` | - | Open CCR (Claude Code Router) management menu |
285
+ | Command | Alias | Description |
286
+ | ------------ | ------- | ------------------------------------------------------------------------------------- |
287
+ | `zcf` | - | Show interactive menu (v2.0 default command) |
288
+ | `zcf init` | `zcf i` | Initialize Claude Code configuration |
289
+ | `zcf update` | `zcf u` | Update workflow-related md files with backup |
290
+ | `zcf ccu` | - | Run Claude Code usage analysis tool - [ccusage](https://github.com/ryoppippi/ccusage) |
291
+ | `zcf ccr` | - | Open CCR (Claude Code Router) management menu |
278
292
 
279
293
  #### Common Options
280
294
 
@@ -466,14 +480,28 @@ To protect user data security, the following operations require explicit confirm
466
480
 
467
481
  ## 🙏 Acknowledgments
468
482
 
469
- Some prompts in this project are inspired by the following excellent works:
483
+ This project is inspired by and incorporates the following open source projects:
470
484
 
471
- - [Linux.do - Share a universal Prompt for AI to generate only necessary code, welcome to optimize together~](https://linux.do/t/topic/830802)
472
- - [Linux.do - Don't worry about claude code degradation, using agent and command combination to break down tasks in detail may help you](https://linux.do/t/topic/815230)
473
- - [Linux.do - cursor rapid development rules](https://linux.do/t/topic/697566)
485
+ - [LINUX DO - The New Ideal Community](https://linux.do)
486
+ - [CCR](https://github.com/musistudio/claude-code-router)
487
+ - [ccusage](https://github.com/ryoppippi/ccusage)
488
+ - [BMad Method](https://github.com/bmad-code-org/BMAD-METHOD)
474
489
 
475
490
  Thanks to these community contributors for sharing!
476
491
 
492
+ ## ❤️ Support & Sponsorship
493
+
494
+ If you find this project helpful, please consider sponsoring its development. Your support is greatly appreciated!
495
+
496
+ [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/UfoMiao)
497
+
498
+ <table>
499
+ <tr>
500
+ <td><img src="/src/assets/alipay.webp" width="200" alt="Alipay" /></td>
501
+ <td><img src="/src/assets/wechat.webp" width="200" alt="WeChat Pay" /></td>
502
+ </tr>
503
+ </table>
504
+
477
505
  ## 📄 License
478
506
 
479
507
  MIT License
@@ -5,13 +5,21 @@ import { join, dirname } from 'pathe';
5
5
  import dayjs from 'dayjs';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { exec } from 'tinyexec';
8
- import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
9
- import { exec as exec$1 } from 'node:child_process';
10
- import { promisify } from 'node:util';
8
+ import { exec as exec$1 } from 'child_process';
9
+ import { promisify } from 'util';
10
+ import ora from 'ora';
11
+ import prompts$1 from 'prompts';
12
+ import { readFile as readFile$1, writeFile as writeFile$1, mkdir } from 'fs/promises';
13
+ import { join as join$1 } from 'path';
14
+ import { homedir as homedir$1 } from 'os';
15
+ import semver from 'semver';
16
+ import { rm, mkdir as mkdir$1, copyFile as copyFile$1 } from 'node:fs/promises';
17
+ import { exec as exec$2 } from 'node:child_process';
18
+ import { promisify as promisify$1 } from 'node:util';
11
19
  import { homedir, platform } from 'node:os';
12
- import { join as join$1 } from 'node:path';
20
+ import { join as join$2 } from 'node:path';
13
21
 
14
- const version = "2.8.0";
22
+ const version = "2.8.2";
15
23
  const homepage = "https://github.com/UfoMiao/zcf";
16
24
 
17
25
  const common$1 = {
@@ -123,11 +131,21 @@ const configuration$1 = {
123
131
  // Model configuration
124
132
  selectDefaultModel: "\u9009\u62E9\u9ED8\u8BA4\u6A21\u578B",
125
133
  modelConfigSuccess: "\u9ED8\u8BA4\u6A21\u578B\u5DF2\u914D\u7F6E",
134
+ existingModelConfig: "\u68C0\u6D4B\u5230\u5DF2\u6709\u6A21\u578B\u914D\u7F6E",
135
+ currentModel: "\u5F53\u524D\u6A21\u578B",
136
+ modifyModel: "\u662F\u5426\u4FEE\u6539\u6A21\u578B\u914D\u7F6E\uFF1F",
137
+ keepModel: "\u4FDD\u6301\u5F53\u524D\u6A21\u578B\u914D\u7F6E",
138
+ defaultModelOption: "\u9ED8\u8BA4\uFF08\u8BA9 Claude Code \u81EA\u52A8\u9009\u62E9\uFF09",
139
+ modelConfigured: "\u9ED8\u8BA4\u6A21\u578B\u5DF2\u914D\u7F6E",
126
140
  // AI memory configuration
127
141
  selectMemoryOption: "\u9009\u62E9\u914D\u7F6E\u9009\u9879",
128
142
  configureAiLanguage: "\u914D\u7F6E AI \u8F93\u51FA\u8BED\u8A00",
129
143
  configureAiPersonality: "\u914D\u7F6E AI \u4E2A\u6027\u98CE\u683C",
130
144
  aiLanguageConfigured: "AI \u8F93\u51FA\u8BED\u8A00\u5DF2\u914D\u7F6E",
145
+ existingLanguageConfig: "\u68C0\u6D4B\u5230\u5DF2\u6709 AI \u8F93\u51FA\u8BED\u8A00\u914D\u7F6E",
146
+ currentLanguage: "\u5F53\u524D\u8BED\u8A00",
147
+ modifyLanguage: "\u662F\u5426\u4FEE\u6539 AI \u8F93\u51FA\u8BED\u8A00\uFF1F",
148
+ keepLanguage: "\u4FDD\u6301\u5F53\u524D\u8BED\u8A00\u914D\u7F6E",
131
149
  // AI personality
132
150
  selectAiPersonality: "\u9009\u62E9 AI \u4E2A\u6027\u98CE\u683C",
133
151
  customPersonalityHint: "\u5B9A\u4E49\u4F60\u81EA\u5DF1\u7684\u4E2A\u6027",
@@ -430,6 +448,24 @@ const ccrMessages$1 = {
430
448
  ccrUiApiKeyHint: "\u4F7F\u7528\u6B64\u5BC6\u94A5\u767B\u5F55 CCR UI \u754C\u9762"
431
449
  };
432
450
 
451
+ const updater$1 = {
452
+ checkingVersion: "\u6B63\u5728\u68C0\u67E5\u7248\u672C...",
453
+ checkingTools: "\u68C0\u67E5\u5DE5\u5177\u7248\u672C",
454
+ ccrNotInstalled: "CCR \u672A\u5B89\u88C5",
455
+ ccrUpToDate: "CCR \u5DF2\u662F\u6700\u65B0\u7248\u672C (v{version})",
456
+ claudeCodeNotInstalled: "Claude Code \u672A\u5B89\u88C5",
457
+ claudeCodeUpToDate: "Claude Code \u5DF2\u662F\u6700\u65B0\u7248\u672C (v{version})",
458
+ cannotCheckVersion: "\u65E0\u6CD5\u68C0\u67E5\u6700\u65B0\u7248\u672C",
459
+ currentVersion: "\u5F53\u524D\u7248\u672C: v{version}",
460
+ latestVersion: "\u6700\u65B0\u7248\u672C: v{version}",
461
+ confirmUpdate: "\u662F\u5426\u66F4\u65B0 {tool} \u5230\u6700\u65B0\u7248\u672C\uFF1F",
462
+ updateSkipped: "\u5DF2\u8DF3\u8FC7\u66F4\u65B0",
463
+ updating: "\u6B63\u5728\u66F4\u65B0 {tool}...",
464
+ updateSuccess: "{tool} \u66F4\u65B0\u6210\u529F\uFF01",
465
+ updateFailed: "{tool} \u66F4\u65B0\u5931\u8D25",
466
+ checkFailed: "\u7248\u672C\u68C0\u67E5\u5931\u8D25"
467
+ };
468
+
433
469
  const zhCN = {
434
470
  common: common$1,
435
471
  language: language$1,
@@ -443,7 +479,8 @@ const zhCN = {
443
479
  bmad: bmad$1,
444
480
  errors: errors$1,
445
481
  tools: tools$1,
446
- ccr: ccrMessages$1
482
+ ccr: ccrMessages$1,
483
+ updater: updater$1
447
484
  };
448
485
 
449
486
  const common = {
@@ -555,11 +592,21 @@ const configuration = {
555
592
  // Model configuration
556
593
  selectDefaultModel: "Select default model",
557
594
  modelConfigSuccess: "Default model configured",
595
+ existingModelConfig: "Existing model configuration detected",
596
+ currentModel: "Current model",
597
+ modifyModel: "Modify model configuration?",
598
+ keepModel: "Keeping existing model configuration",
599
+ defaultModelOption: "Default (Let Claude Code choose)",
600
+ modelConfigured: "Default model configured",
558
601
  // AI memory configuration
559
602
  selectMemoryOption: "Select configuration option",
560
603
  configureAiLanguage: "Configure AI output language",
561
604
  configureAiPersonality: "Configure AI personality",
562
605
  aiLanguageConfigured: "AI output language configured",
606
+ existingLanguageConfig: "Existing AI output language configuration detected",
607
+ currentLanguage: "Current language",
608
+ modifyLanguage: "Modify AI output language?",
609
+ keepLanguage: "Keeping existing language configuration",
563
610
  // AI personality
564
611
  selectAiPersonality: "Select AI personality",
565
612
  customPersonalityHint: "Define your own personality",
@@ -862,6 +909,24 @@ const ccrMessages = {
862
909
  ccrUiApiKeyHint: "Use this API key to login to CCR UI"
863
910
  };
864
911
 
912
+ const updater = {
913
+ checkingVersion: "Checking version...",
914
+ checkingTools: "Checking tool versions",
915
+ ccrNotInstalled: "CCR is not installed",
916
+ ccrUpToDate: "CCR is up to date (v{version})",
917
+ claudeCodeNotInstalled: "Claude Code is not installed",
918
+ claudeCodeUpToDate: "Claude Code is up to date (v{version})",
919
+ cannotCheckVersion: "Cannot check latest version",
920
+ currentVersion: "Current version: v{version}",
921
+ latestVersion: "Latest version: v{version}",
922
+ confirmUpdate: "Update {tool} to the latest version?",
923
+ updateSkipped: "Update skipped",
924
+ updating: "Updating {tool}...",
925
+ updateSuccess: "{tool} updated successfully!",
926
+ updateFailed: "{tool} update failed",
927
+ checkFailed: "Version check failed"
928
+ };
929
+
865
930
  const en = {
866
931
  common,
867
932
  language,
@@ -875,7 +940,8 @@ const en = {
875
940
  bmad,
876
941
  errors,
877
942
  tools,
878
- ccr: ccrMessages
943
+ ccr: ccrMessages,
944
+ updater
879
945
  };
880
946
 
881
947
  const I18N$1 = {
@@ -1672,7 +1738,11 @@ function updateDefaultModel(model) {
1672
1738
  if (existingSettings) {
1673
1739
  settings = existingSettings;
1674
1740
  }
1675
- settings.model = model;
1741
+ if (model === "default") {
1742
+ delete settings.model;
1743
+ } else {
1744
+ settings.model = model;
1745
+ }
1676
1746
  writeJsonConfig(SETTINGS_FILE, settings);
1677
1747
  }
1678
1748
  function mergeSettingsFile(templatePath, targetPath) {
@@ -1720,6 +1790,16 @@ function mergeSettingsFile(templatePath, targetPath) {
1720
1790
  }
1721
1791
  }
1722
1792
  }
1793
+ function getExistingModelConfig() {
1794
+ const settings = readJsonConfig(SETTINGS_FILE);
1795
+ if (!settings) {
1796
+ return null;
1797
+ }
1798
+ if (!settings.model) {
1799
+ return "default";
1800
+ }
1801
+ return settings.model;
1802
+ }
1723
1803
  function getExistingApiConfig() {
1724
1804
  const settings = readJsonConfig(SETTINGS_FILE);
1725
1805
  if (!settings || !settings.env) {
@@ -1953,11 +2033,223 @@ async function updatePromptOnly(configLang, scriptLang, aiOutputLang) {
1953
2033
  console.log("\n" + ansis.cyan(i18n.common.complete));
1954
2034
  }
1955
2035
 
2036
+ function format(template, replacements) {
2037
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
2038
+ return replacements[key] || match;
2039
+ });
2040
+ }
2041
+
2042
+ const execAsync$3 = promisify(exec$1);
2043
+ const CACHE_DIR = join$1(homedir$1(), ".claude", "cache");
2044
+ const CACHE_FILE = join$1(CACHE_DIR, "version-cache.json");
2045
+ const CACHE_DURATION = 24 * 60 * 60 * 1e3;
2046
+ async function ensureCacheDir() {
2047
+ try {
2048
+ await mkdir(CACHE_DIR, { recursive: true });
2049
+ } catch (error) {
2050
+ }
2051
+ }
2052
+ async function readCache() {
2053
+ try {
2054
+ const content = await readFile$1(CACHE_FILE, "utf-8");
2055
+ return JSON.parse(content);
2056
+ } catch {
2057
+ return {};
2058
+ }
2059
+ }
2060
+ async function writeCache(cache) {
2061
+ await ensureCacheDir();
2062
+ await writeFile$1(CACHE_FILE, JSON.stringify(cache, null, 2));
2063
+ }
2064
+ async function getInstalledVersion(command) {
2065
+ try {
2066
+ let stdout;
2067
+ try {
2068
+ const result = await execAsync$3(`${command} -v`);
2069
+ stdout = result.stdout;
2070
+ } catch {
2071
+ const result = await execAsync$3(`${command} --version`);
2072
+ stdout = result.stdout;
2073
+ }
2074
+ const versionMatch = stdout.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
2075
+ return versionMatch ? versionMatch[1] : null;
2076
+ } catch {
2077
+ return null;
2078
+ }
2079
+ }
2080
+ async function getLatestVersion(packageName, useCache = true) {
2081
+ if (useCache) {
2082
+ const cache = await readCache();
2083
+ const cached = cache[packageName];
2084
+ if (cached && Date.now() - cached.checkedAt < CACHE_DURATION) {
2085
+ return cached.version;
2086
+ }
2087
+ }
2088
+ try {
2089
+ const { stdout } = await execAsync$3(`npm view ${packageName} version`);
2090
+ const version = stdout.trim();
2091
+ const cache = await readCache();
2092
+ cache[packageName] = {
2093
+ version,
2094
+ checkedAt: Date.now()
2095
+ };
2096
+ await writeCache(cache);
2097
+ return version;
2098
+ } catch {
2099
+ return null;
2100
+ }
2101
+ }
2102
+ function compareVersions(current, latest) {
2103
+ if (!semver.valid(current) || !semver.valid(latest)) {
2104
+ return -1;
2105
+ }
2106
+ return semver.compare(current, latest);
2107
+ }
2108
+ function shouldUpdate(current, latest) {
2109
+ return compareVersions(current, latest) < 0;
2110
+ }
2111
+ async function checkCcrVersion() {
2112
+ const currentVersion = await getInstalledVersion("ccr");
2113
+ let latestVersion = await getLatestVersion("@musistudio/claude-code-router");
2114
+ if (!latestVersion) {
2115
+ latestVersion = await getLatestVersion("claude-code-router");
2116
+ }
2117
+ return {
2118
+ installed: currentVersion !== null,
2119
+ currentVersion,
2120
+ latestVersion,
2121
+ needsUpdate: currentVersion && latestVersion ? shouldUpdate(currentVersion, latestVersion) : false
2122
+ };
2123
+ }
2124
+ async function checkClaudeCodeVersion() {
2125
+ const currentVersion = await getInstalledVersion("claude");
2126
+ const latestVersion = await getLatestVersion("@anthropic-ai/claude-code");
2127
+ return {
2128
+ installed: currentVersion !== null,
2129
+ currentVersion,
2130
+ latestVersion,
2131
+ needsUpdate: currentVersion && latestVersion ? shouldUpdate(currentVersion, latestVersion) : false
2132
+ };
2133
+ }
2134
+
2135
+ const execAsync$2 = promisify(exec$1);
2136
+ async function updateCcr(scriptLang, force = false) {
2137
+ const i18n = getTranslation(scriptLang);
2138
+ const spinner = ora(i18n.updater.checkingVersion).start();
2139
+ try {
2140
+ const { installed, currentVersion, latestVersion, needsUpdate } = await checkCcrVersion();
2141
+ spinner.stop();
2142
+ if (!installed) {
2143
+ console.log(ansis.yellow(i18n.updater.ccrNotInstalled));
2144
+ return false;
2145
+ }
2146
+ if (!needsUpdate && !force) {
2147
+ console.log(ansis.green(format(i18n.updater.ccrUpToDate, { version: currentVersion || "" })));
2148
+ return true;
2149
+ }
2150
+ if (!latestVersion) {
2151
+ console.log(ansis.yellow(i18n.updater.cannotCheckVersion));
2152
+ return false;
2153
+ }
2154
+ console.log(ansis.cyan(format(i18n.updater.currentVersion, { version: currentVersion || "" })));
2155
+ console.log(ansis.cyan(format(i18n.updater.latestVersion, { version: latestVersion })));
2156
+ const { confirm } = await prompts$1({
2157
+ type: "confirm",
2158
+ name: "confirm",
2159
+ message: format(i18n.updater.confirmUpdate, { tool: "CCR" }),
2160
+ initial: true
2161
+ });
2162
+ if (!confirm) {
2163
+ console.log(ansis.gray(i18n.updater.updateSkipped));
2164
+ return true;
2165
+ }
2166
+ const updateSpinner = ora(format(i18n.updater.updating, { tool: "CCR" })).start();
2167
+ try {
2168
+ try {
2169
+ await execAsync$2("npm update -g @musistudio/claude-code-router");
2170
+ } catch {
2171
+ await execAsync$2("npm update -g claude-code-router");
2172
+ }
2173
+ updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "CCR" }));
2174
+ return true;
2175
+ } catch (error) {
2176
+ updateSpinner.fail(format(i18n.updater.updateFailed, { tool: "CCR" }));
2177
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
2178
+ return false;
2179
+ }
2180
+ } catch (error) {
2181
+ spinner.fail(i18n.updater.checkFailed);
2182
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
2183
+ return false;
2184
+ }
2185
+ }
2186
+ async function updateClaudeCode(scriptLang, force = false) {
2187
+ const i18n = getTranslation(scriptLang);
2188
+ const spinner = ora(i18n.updater.checkingVersion).start();
2189
+ try {
2190
+ const { installed, currentVersion, latestVersion, needsUpdate } = await checkClaudeCodeVersion();
2191
+ spinner.stop();
2192
+ if (!installed) {
2193
+ console.log(ansis.yellow(i18n.updater.claudeCodeNotInstalled));
2194
+ return false;
2195
+ }
2196
+ if (!needsUpdate && !force) {
2197
+ console.log(ansis.green(format(i18n.updater.claudeCodeUpToDate, { version: currentVersion || "" })));
2198
+ return true;
2199
+ }
2200
+ if (!latestVersion) {
2201
+ console.log(ansis.yellow(i18n.updater.cannotCheckVersion));
2202
+ return false;
2203
+ }
2204
+ console.log(ansis.cyan(format(i18n.updater.currentVersion, { version: currentVersion || "" })));
2205
+ console.log(ansis.cyan(format(i18n.updater.latestVersion, { version: latestVersion })));
2206
+ const { confirm } = await prompts$1({
2207
+ type: "confirm",
2208
+ name: "confirm",
2209
+ message: format(i18n.updater.confirmUpdate, { tool: "Claude Code" }),
2210
+ initial: true
2211
+ });
2212
+ if (!confirm) {
2213
+ console.log(ansis.gray(i18n.updater.updateSkipped));
2214
+ return true;
2215
+ }
2216
+ const updateSpinner = ora(format(i18n.updater.updating, { tool: "Claude Code" })).start();
2217
+ try {
2218
+ await execAsync$2("npm update -g @anthropic-ai/claude-code");
2219
+ updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "Claude Code" }));
2220
+ return true;
2221
+ } catch (error) {
2222
+ updateSpinner.fail(format(i18n.updater.updateFailed, { tool: "Claude Code" }));
2223
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
2224
+ return false;
2225
+ }
2226
+ } catch (error) {
2227
+ spinner.fail(i18n.updater.checkFailed);
2228
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
2229
+ return false;
2230
+ }
2231
+ }
2232
+ async function checkAndUpdateTools(scriptLang) {
2233
+ const i18n = getTranslation(scriptLang);
2234
+ console.log(ansis.bold.cyan(`
2235
+ \u{1F50D} ${i18n.updater.checkingTools}
2236
+ `));
2237
+ await updateCcr(scriptLang);
2238
+ console.log();
2239
+ await updateClaudeCode(scriptLang);
2240
+ }
2241
+
1956
2242
  async function isClaudeCodeInstalled() {
1957
2243
  return await commandExists("claude");
1958
2244
  }
1959
2245
  async function installClaudeCode(lang) {
1960
2246
  const i18n = getTranslation(lang);
2247
+ const installed = await isClaudeCodeInstalled();
2248
+ if (installed) {
2249
+ console.log(ansis.green(`\u2714 ${i18n.installation.alreadyInstalled}`));
2250
+ await updateClaudeCode(lang);
2251
+ return;
2252
+ }
1961
2253
  if (isTermux()) {
1962
2254
  console.log(ansis.yellow(`\u2139 ${i18n.installation.termuxDetected}`));
1963
2255
  const termuxPrefix = getTermuxPrefix();
@@ -2064,6 +2356,13 @@ async function resolveAiOutputLanguage(scriptLang, commandLineOption, savedConfi
2064
2356
  return await selectAiOutputLanguage(scriptLang, scriptLang);
2065
2357
  }
2066
2358
 
2359
+ const prompts = {
2360
+ __proto__: null,
2361
+ resolveAiOutputLanguage: resolveAiOutputLanguage,
2362
+ selectAiOutputLanguage: selectAiOutputLanguage,
2363
+ selectScriptLanguage: selectScriptLanguage
2364
+ };
2365
+
2067
2366
  async function selectMcpServices(scriptLang) {
2068
2367
  const i18n = getTranslation(scriptLang);
2069
2368
  const choices = MCP_SERVICES.map((service) => ({
@@ -2182,7 +2481,7 @@ async function installWorkflowWithDependencies(config, configLang, scriptLang) {
2182
2481
  \u{1F4E6} ${i18n.workflow.installingWorkflow}: ${workflowName}...`));
2183
2482
  const commandsDir = join(CLAUDE_DIR, "commands", "zcf");
2184
2483
  if (!existsSync(commandsDir)) {
2185
- await mkdir(commandsDir, { recursive: true });
2484
+ await mkdir$1(commandsDir, { recursive: true });
2186
2485
  }
2187
2486
  for (const commandFile of config.commands) {
2188
2487
  const commandSource = join(rootDir, "templates", configLang, "workflow", config.category, "commands", commandFile);
@@ -2204,7 +2503,7 @@ async function installWorkflowWithDependencies(config, configLang, scriptLang) {
2204
2503
  if (config.autoInstallAgents && config.agents.length > 0) {
2205
2504
  const agentsCategoryDir = join(CLAUDE_DIR, "agents", "zcf", config.category);
2206
2505
  if (!existsSync(agentsCategoryDir)) {
2207
- await mkdir(agentsCategoryDir, { recursive: true });
2506
+ await mkdir$1(agentsCategoryDir, { recursive: true });
2208
2507
  }
2209
2508
  for (const agent of config.agents) {
2210
2509
  const agentSource = join(rootDir, "templates", configLang, "workflow", config.category, "agents", agent.filename);
@@ -2270,7 +2569,7 @@ async function cleanupOldVersionFiles(scriptLang) {
2270
2569
  }
2271
2570
  }
2272
2571
 
2273
- const execAsync$1 = promisify(exec$1);
2572
+ const execAsync$1 = promisify$1(exec$2);
2274
2573
  async function isCcrInstalled() {
2275
2574
  try {
2276
2575
  await execAsync$1("ccr version");
@@ -2289,6 +2588,7 @@ async function installCcr(scriptLang) {
2289
2588
  const installed = await isCcrInstalled();
2290
2589
  if (installed) {
2291
2590
  console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
2591
+ await updateCcr(scriptLang);
2292
2592
  return;
2293
2593
  }
2294
2594
  console.log(ansis.cyan(`\u{1F4E6} ${i18n.ccr.installingCcr}`));
@@ -2298,6 +2598,7 @@ async function installCcr(scriptLang) {
2298
2598
  } catch (error) {
2299
2599
  if (error.message?.includes("EEXIST")) {
2300
2600
  console.log(ansis.yellow(`\u26A0 ${i18n.ccr.ccrAlreadyInstalled}`));
2601
+ await updateCcr(scriptLang);
2301
2602
  return;
2302
2603
  }
2303
2604
  console.error(ansis.red(`\u2716 ${i18n.ccr.ccrInstallFailed}`));
@@ -2453,9 +2754,9 @@ function getFallbackPresets() {
2453
2754
  ];
2454
2755
  }
2455
2756
 
2456
- const execAsync = promisify(exec$1);
2457
- const CCR_CONFIG_DIR = join$1(homedir(), ".claude-code-router");
2458
- const CCR_CONFIG_FILE = join$1(CCR_CONFIG_DIR, "config.json");
2757
+ const execAsync = promisify$1(exec$2);
2758
+ const CCR_CONFIG_DIR = join$2(homedir(), ".claude-code-router");
2759
+ const CCR_CONFIG_FILE = join$2(CCR_CONFIG_DIR, "config.json");
2459
2760
  const CCR_BACKUP_DIR = CCR_CONFIG_DIR;
2460
2761
  function ensureCcrConfigDir() {
2461
2762
  if (!existsSync(CCR_CONFIG_DIR)) {
@@ -2470,7 +2771,7 @@ function backupCcrConfig(scriptLang) {
2470
2771
  }
2471
2772
  const timestamp = dayjs().format("YYYY-MM-DDTHH-mm-ss-SSS") + "Z";
2472
2773
  const backupFileName = `config.json.${timestamp}.bak`;
2473
- const backupPath = join$1(CCR_BACKUP_DIR, backupFileName);
2774
+ const backupPath = join$2(CCR_BACKUP_DIR, backupFileName);
2474
2775
  console.log(ansis.cyan(`${i18n.ccr.backupCcrConfig}`));
2475
2776
  copyFileSync(CCR_CONFIG_FILE, backupPath);
2476
2777
  console.log(ansis.green(`\u2714 ${i18n.ccr.ccrBackupSuccess.replace("{path}", backupPath)}`));
@@ -3078,4 +3379,4 @@ async function openSettingsJson() {
3078
3379
  }
3079
3380
  }
3080
3381
 
3081
- export { readCcrConfig as $, AI_OUTPUT_LANGUAGES as A, backupMcpConfig as B, CLAUDE_DIR as C, mergeMcpServers as D, buildMcpServerConfig as E, fixWindowsMcpConfig as F, addCompletedOnboarding as G, getTranslation as H, I18N as I, addNumbersToChoices as J, updateZcfConfig as K, LEGACY_ZCF_CONFIG_FILE as L, MCP_SERVICES as M, readZcfConfig as N, resolveAiOutputLanguage as O, configureAiPersonality as P, isWindows as Q, selectMcpServices as R, SETTINGS_FILE as S, formatApiKeyDisplay as T, modifyApiConfigPartially as U, isCcrInstalled as V, installCcr as W, setupCcrConfiguration as X, validateApiKey as Y, ZCF_CONFIG_FILE as Z, readZcfConfigAsync as _, importRecommendedEnv as a, configureCcrFeature as a0, handleExitPromptError as a1, handleGeneralError as a2, displayBanner as a3, selectScriptLanguage as a4, updatePromptOnly as a5, selectAndInstallWorkflows as a6, version as a7, displayBannerWithInfo as a8, importRecommendedPermissions as b, commandExists as c, cleanupPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, SUPPORTED_LANGS as h, init as i, LANG_LABELS as j, isClaudeCodeInstalled as k, installClaudeCode as l, mergeAndCleanPermissions as m, ensureClaudeDir as n, openSettingsJson as o, backupExistingConfig as p, copyConfigFiles as q, configureApi as r, mergeConfigs as s, mergeSettingsFile as t, updateDefaultModel as u, getExistingApiConfig as v, applyAiLanguageDirective as w, getMcpConfigPath as x, readMcpConfig as y, writeMcpConfig as z };
3382
+ export { readCcrConfig as $, AI_OUTPUT_LANGUAGES as A, writeMcpConfig as B, CLAUDE_DIR as C, backupMcpConfig as D, mergeMcpServers as E, buildMcpServerConfig as F, fixWindowsMcpConfig as G, addCompletedOnboarding as H, I18N as I, getTranslation as J, addNumbersToChoices as K, LEGACY_ZCF_CONFIG_FILE as L, MCP_SERVICES as M, updateZcfConfig as N, readZcfConfig as O, configureAiPersonality as P, isWindows as Q, selectMcpServices as R, SETTINGS_FILE as S, formatApiKeyDisplay as T, modifyApiConfigPartially as U, isCcrInstalled as V, installCcr as W, setupCcrConfiguration as X, validateApiKey as Y, ZCF_CONFIG_FILE as Z, readZcfConfigAsync as _, importRecommendedEnv as a, configureCcrFeature as a0, handleExitPromptError as a1, handleGeneralError as a2, displayBanner as a3, selectScriptLanguage as a4, resolveAiOutputLanguage as a5, updatePromptOnly as a6, selectAndInstallWorkflows as a7, version as a8, displayBannerWithInfo as a9, checkAndUpdateTools as aa, prompts as ab, importRecommendedPermissions as b, commandExists as c, cleanupPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, SUPPORTED_LANGS as h, init as i, LANG_LABELS as j, isClaudeCodeInstalled as k, installClaudeCode as l, mergeAndCleanPermissions as m, ensureClaudeDir as n, openSettingsJson as o, backupExistingConfig as p, copyConfigFiles as q, configureApi as r, mergeConfigs as s, mergeSettingsFile as t, updateDefaultModel as u, getExistingModelConfig as v, getExistingApiConfig as w, applyAiLanguageDirective as x, getMcpConfigPath as y, readMcpConfig as z };
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { H as getTranslation, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, J as addNumbersToChoices, j as LANG_LABELS, K as updateZcfConfig, o as openSettingsJson, b as importRecommendedPermissions, a as importRecommendedEnv, N as readZcfConfig, O as resolveAiOutputLanguage, w as applyAiLanguageDirective, P as configureAiPersonality, u as updateDefaultModel, Q as isWindows, y as readMcpConfig, F as fixWindowsMcpConfig, z as writeMcpConfig, R as selectMcpServices, B as backupMcpConfig, M as MCP_SERVICES, E as buildMcpServerConfig, D as mergeMcpServers, v as getExistingApiConfig, T as formatApiKeyDisplay, G as addCompletedOnboarding, U as modifyApiConfigPartially, V as isCcrInstalled, W as installCcr, X as setupCcrConfiguration, Y as validateApiKey, r as configureApi, _ as readZcfConfigAsync, I as I18N, $ as readCcrConfig, a0 as configureCcrFeature, a1 as handleExitPromptError, a2 as handleGeneralError, a3 as displayBanner, a4 as selectScriptLanguage, a5 as updatePromptOnly, a6 as selectAndInstallWorkflows, a7 as version, a8 as displayBannerWithInfo, i as init } from './shared/zcf.CLtDS8Pu.mjs';
4
+ import { J as getTranslation, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, K as addNumbersToChoices, j as LANG_LABELS, N as updateZcfConfig, o as openSettingsJson, b as importRecommendedPermissions, a as importRecommendedEnv, O as readZcfConfig, x as applyAiLanguageDirective, P as configureAiPersonality, v as getExistingModelConfig, u as updateDefaultModel, Q as isWindows, z as readMcpConfig, G as fixWindowsMcpConfig, B as writeMcpConfig, R as selectMcpServices, D as backupMcpConfig, M as MCP_SERVICES, F as buildMcpServerConfig, E as mergeMcpServers, w as getExistingApiConfig, T as formatApiKeyDisplay, H as addCompletedOnboarding, U as modifyApiConfigPartially, V as isCcrInstalled, W as installCcr, X as setupCcrConfiguration, Y as validateApiKey, r as configureApi, _ as readZcfConfigAsync, I as I18N, $ as readCcrConfig, a0 as configureCcrFeature, a1 as handleExitPromptError, a2 as handleGeneralError, a3 as displayBanner, a4 as selectScriptLanguage, a5 as resolveAiOutputLanguage, a6 as updatePromptOnly, a7 as selectAndInstallWorkflows, a8 as version, a9 as displayBannerWithInfo, i as init, aa as checkAndUpdateTools } from './chunks/simple-config.mjs';
5
5
  import inquirer from 'inquirer';
6
6
  import { existsSync, unlinkSync } from 'node:fs';
7
7
  import { x } from 'tinyexec';
@@ -12,6 +12,12 @@ import { promisify } from 'util';
12
12
  import 'pathe';
13
13
  import 'dayjs';
14
14
  import 'node:url';
15
+ import 'ora';
16
+ import 'prompts';
17
+ import 'fs/promises';
18
+ import 'path';
19
+ import 'os';
20
+ import 'semver';
15
21
  import 'node:fs/promises';
16
22
  import 'node:child_process';
17
23
  import 'node:util';
@@ -26,9 +32,15 @@ async function configureApiFeature(scriptLang) {
26
32
  if (existingApiConfig) {
27
33
  console.log("\n" + ansis.blue(`\u2139 ${i18n.api.existingApiConfig}`));
28
34
  console.log(ansis.gray(` ${i18n.api.apiConfigUrl}: ${existingApiConfig.url || i18n.common.notConfigured}`));
29
- console.log(ansis.gray(` ${i18n.api.apiConfigKey}: ${existingApiConfig.key ? formatApiKeyDisplay(existingApiConfig.key) : i18n.common.notConfigured}`));
30
- console.log(ansis.gray(` ${i18n.api.apiConfigAuthType}: ${existingApiConfig.authType || i18n.common.notConfigured}
31
- `));
35
+ console.log(
36
+ ansis.gray(
37
+ ` ${i18n.api.apiConfigKey}: ${existingApiConfig.key ? formatApiKeyDisplay(existingApiConfig.key) : i18n.common.notConfigured}`
38
+ )
39
+ );
40
+ console.log(
41
+ ansis.gray(` ${i18n.api.apiConfigAuthType}: ${existingApiConfig.authType || i18n.common.notConfigured}
42
+ `)
43
+ );
32
44
  const { action } = await inquirer.prompt({
33
45
  type: "list",
34
46
  name: "action",
@@ -209,21 +221,44 @@ async function configureMcpFeature(scriptLang) {
209
221
  }
210
222
  }
211
223
  async function configureDefaultModelFeature(scriptLang) {
224
+ const i18n = getTranslation(scriptLang);
225
+ const existingModel = getExistingModelConfig();
226
+ if (existingModel) {
227
+ console.log("\n" + ansis.blue(`\u2139 ${i18n.configuration.existingModelConfig || "Existing model configuration"}`));
228
+ const modelDisplay = existingModel === "default" ? i18n.configuration.defaultModelOption || "Default (Let Claude Code choose)" : existingModel.charAt(0).toUpperCase() + existingModel.slice(1);
229
+ console.log(ansis.gray(` ${i18n.configuration.currentModel || "Current model"}: ${modelDisplay}
230
+ `));
231
+ const { modify } = await inquirer.prompt({
232
+ type: "confirm",
233
+ name: "modify",
234
+ message: i18n.configuration.modifyModel || "Modify model configuration?",
235
+ default: false
236
+ });
237
+ if (!modify) {
238
+ console.log(ansis.green(`\u2714 ${i18n.configuration.keepModel || "Keeping existing model configuration"}`));
239
+ return;
240
+ }
241
+ }
212
242
  const { model } = await inquirer.prompt({
213
243
  type: "list",
214
244
  name: "model",
215
- message: "Select default model",
245
+ message: i18n.configuration.selectDefaultModel || "Select default model",
216
246
  choices: addNumbersToChoices([
247
+ {
248
+ name: i18n.configuration.defaultModelOption || "Default (Let Claude Code choose)",
249
+ value: "default"
250
+ },
217
251
  { name: "Opus", value: "opus" },
218
252
  { name: "Sonnet", value: "sonnet" }
219
- ])
253
+ ]),
254
+ default: existingModel ? ["opus", "sonnet", "default"].indexOf(existingModel) : 2
220
255
  });
221
256
  if (!model) {
222
257
  handleCancellation(scriptLang);
223
258
  return;
224
259
  }
225
260
  updateDefaultModel(model);
226
- console.log(ansis.green(`\u2714 Default model configured`));
261
+ console.log(ansis.green(`\u2714 ${i18n.configuration.modelConfigured || "Default model configured"}`));
227
262
  }
228
263
  async function configureAiMemoryFeature(scriptLang) {
229
264
  const i18n = getTranslation(scriptLang);
@@ -247,7 +282,26 @@ async function configureAiMemoryFeature(scriptLang) {
247
282
  }
248
283
  if (option === "language") {
249
284
  const zcfConfig = readZcfConfig();
250
- const aiOutputLang = await resolveAiOutputLanguage(scriptLang, void 0, zcfConfig);
285
+ const existingLang = zcfConfig?.aiOutputLang;
286
+ if (existingLang) {
287
+ console.log(
288
+ "\n" + ansis.blue(`\u2139 ${i18n.configuration.existingLanguageConfig || "Existing AI output language configuration"}`)
289
+ );
290
+ console.log(ansis.gray(` ${i18n.configuration.currentLanguage || "Current language"}: ${existingLang}
291
+ `));
292
+ const { modify } = await inquirer.prompt({
293
+ type: "confirm",
294
+ name: "modify",
295
+ message: i18n.configuration.modifyLanguage || "Modify AI output language?",
296
+ default: false
297
+ });
298
+ if (!modify) {
299
+ console.log(ansis.green(`\u2714 ${i18n.configuration.keepLanguage || "Keeping existing language configuration"}`));
300
+ return;
301
+ }
302
+ }
303
+ const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.ab; });
304
+ const aiOutputLang = await selectAiOutputLanguage(scriptLang, scriptLang);
251
305
  applyAiLanguageDirective(aiOutputLang);
252
306
  updateZcfConfig({ aiOutputLang });
253
307
  console.log(ansis.green(`\u2714 ${i18n.configuration.aiLanguageConfigured || "AI output language configured"}`));
@@ -280,10 +334,12 @@ async function changeScriptLanguageFeature(currentLang) {
280
334
  type: "list",
281
335
  name: "lang",
282
336
  message: i18n.language.selectScriptLang,
283
- choices: addNumbersToChoices(SUPPORTED_LANGS.map((l) => ({
284
- name: LANG_LABELS[l],
285
- value: l
286
- }))),
337
+ choices: addNumbersToChoices(
338
+ SUPPORTED_LANGS.map((l) => ({
339
+ name: LANG_LABELS[l],
340
+ value: l
341
+ }))
342
+ ),
287
343
  default: SUPPORTED_LANGS.indexOf(currentLang)
288
344
  });
289
345
  if (!lang) {
@@ -302,15 +358,21 @@ async function configureEnvPermissionFeature(scriptLang) {
302
358
  message: i18n.configuration?.selectEnvPermissionOption || "Select option",
303
359
  choices: addNumbersToChoices([
304
360
  {
305
- name: `${i18n.configuration?.importRecommendedEnv || "Import environment"} ${ansis.gray("- " + (i18n.configuration?.importRecommendedEnvDesc || "Import env settings"))}`,
361
+ name: `${i18n.configuration?.importRecommendedEnv || "Import environment"} ${ansis.gray(
362
+ "- " + (i18n.configuration?.importRecommendedEnvDesc || "Import env settings")
363
+ )}`,
306
364
  value: "env"
307
365
  },
308
366
  {
309
- name: `${i18n.configuration?.importRecommendedPermissions || "Import permissions"} ${ansis.gray("- " + (i18n.configuration?.importRecommendedPermissionsDesc || "Import permission settings"))}`,
367
+ name: `${i18n.configuration?.importRecommendedPermissions || "Import permissions"} ${ansis.gray(
368
+ "- " + (i18n.configuration?.importRecommendedPermissionsDesc || "Import permission settings")
369
+ )}`,
310
370
  value: "permissions"
311
371
  },
312
372
  {
313
- name: `${i18n.configuration?.openSettingsJson || "Open settings"} ${ansis.gray("- " + (i18n.configuration?.openSettingsJsonDesc || "View settings file"))}`,
373
+ name: `${i18n.configuration?.openSettingsJson || "Open settings"} ${ansis.gray(
374
+ "- " + (i18n.configuration?.openSettingsJsonDesc || "View settings file")
375
+ )}`,
314
376
  value: "open"
315
377
  }
316
378
  ])
@@ -443,8 +505,14 @@ async function runCcrStart(scriptLang) {
443
505
  if (stderr) console.error(ansis.yellow(stderr));
444
506
  console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStarted}`));
445
507
  } catch (error) {
446
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
447
- throw error;
508
+ if (error.stdout && error.stdout.includes("Loaded JSON config from:")) {
509
+ console.log(error.stdout);
510
+ if (error.stderr) console.error(ansis.yellow(error.stderr));
511
+ console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStarted}`));
512
+ } else {
513
+ console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
514
+ throw error;
515
+ }
448
516
  }
449
517
  }
450
518
  async function runCcrStop(scriptLang) {
@@ -859,6 +927,16 @@ async function ccr(options = {}) {
859
927
  }
860
928
  }
861
929
 
930
+ async function checkUpdates(options = {}) {
931
+ const scriptLang = options.lang || await selectScriptLanguage();
932
+ try {
933
+ await checkAndUpdateTools(scriptLang);
934
+ } catch (error) {
935
+ console.error(ansis.red("Error checking updates:"), error);
936
+ process.exit(1);
937
+ }
938
+ }
939
+
862
940
  function setupCommands(cli) {
863
941
  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) => {
864
942
  await handleDefaultCommand(lang, options);
@@ -875,6 +953,9 @@ function setupCommands(cli) {
875
953
  cli.command("ccu [...args]", "Run Claude Code usage analysis tool").allowUnknownOptions().action(async (args) => {
876
954
  await executeCcusage(args);
877
955
  });
956
+ 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) => {
957
+ await checkUpdates({ lang: options.lang });
958
+ });
878
959
  cli.help((sections) => customizeHelp(sections));
879
960
  cli.version(version);
880
961
  }
package/dist/index.d.mts CHANGED
@@ -13,6 +13,7 @@ interface TranslationStructure {
13
13
  errors: any;
14
14
  tools: any;
15
15
  ccr: any;
16
+ updater: any;
16
17
  }
17
18
 
18
19
  interface McpService {
@@ -105,12 +106,16 @@ declare function backupExistingConfig(): string | null;
105
106
  declare function copyConfigFiles(lang: SupportedLang, onlyMd?: boolean): void;
106
107
  declare function configureApi(apiConfig: ApiConfig | null): ApiConfig | null;
107
108
  declare function mergeConfigs(sourceFile: string, targetFile: string): void;
108
- declare function updateDefaultModel(model: 'opus' | 'sonnet'): void;
109
+ declare function updateDefaultModel(model: 'opus' | 'sonnet' | 'default'): void;
109
110
  /**
110
111
  * Merge settings.json intelligently
111
112
  * Preserves user's environment variables and custom configurations
112
113
  */
113
114
  declare function mergeSettingsFile(templatePath: string, targetPath: string): void;
115
+ /**
116
+ * Get existing model configuration from settings.json
117
+ */
118
+ declare function getExistingModelConfig(): 'opus' | 'sonnet' | 'default' | null;
114
119
  /**
115
120
  * Get existing API configuration from settings.json
116
121
  */
@@ -150,5 +155,5 @@ declare function cleanupPermissions(templatePermissions: string[], userPermissio
150
155
  */
151
156
  declare function mergeAndCleanPermissions(templatePermissions: string[] | undefined, userPermissions: string[] | undefined): string[];
152
157
 
153
- export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, I18N, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, MCP_SERVICES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getExistingApiConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateDefaultModel, writeMcpConfig };
158
+ export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, I18N, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, MCP_SERVICES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateDefaultModel, writeMcpConfig };
154
159
  export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, McpServerConfig, McpService, SupportedLang };
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ interface TranslationStructure {
13
13
  errors: any;
14
14
  tools: any;
15
15
  ccr: any;
16
+ updater: any;
16
17
  }
17
18
 
18
19
  interface McpService {
@@ -105,12 +106,16 @@ declare function backupExistingConfig(): string | null;
105
106
  declare function copyConfigFiles(lang: SupportedLang, onlyMd?: boolean): void;
106
107
  declare function configureApi(apiConfig: ApiConfig | null): ApiConfig | null;
107
108
  declare function mergeConfigs(sourceFile: string, targetFile: string): void;
108
- declare function updateDefaultModel(model: 'opus' | 'sonnet'): void;
109
+ declare function updateDefaultModel(model: 'opus' | 'sonnet' | 'default'): void;
109
110
  /**
110
111
  * Merge settings.json intelligently
111
112
  * Preserves user's environment variables and custom configurations
112
113
  */
113
114
  declare function mergeSettingsFile(templatePath: string, targetPath: string): void;
115
+ /**
116
+ * Get existing model configuration from settings.json
117
+ */
118
+ declare function getExistingModelConfig(): 'opus' | 'sonnet' | 'default' | null;
114
119
  /**
115
120
  * Get existing API configuration from settings.json
116
121
  */
@@ -150,5 +155,5 @@ declare function cleanupPermissions(templatePermissions: string[], userPermissio
150
155
  */
151
156
  declare function mergeAndCleanPermissions(templatePermissions: string[] | undefined, userPermissions: string[] | undefined): string[];
152
157
 
153
- export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, I18N, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, MCP_SERVICES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getExistingApiConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateDefaultModel, writeMcpConfig };
158
+ export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, I18N, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, MCP_SERVICES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateDefaultModel, writeMcpConfig };
154
159
  export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, McpServerConfig, McpService, SupportedLang };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, I as I18N, j as LANG_LABELS, L as LEGACY_ZCF_CONFIG_FILE, M as MCP_SERVICES, S as SETTINGS_FILE, h as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE, G as addCompletedOnboarding, w as applyAiLanguageDirective, p as backupExistingConfig, B as backupMcpConfig, E as buildMcpServerConfig, d as cleanupPermissions, c as commandExists, r as configureApi, q as copyConfigFiles, n as ensureClaudeDir, F as fixWindowsMcpConfig, v as getExistingApiConfig, x as getMcpConfigPath, g as getPlatform, a as importRecommendedEnv, b as importRecommendedPermissions, i as init, l as installClaudeCode, k as isClaudeCodeInstalled, m as mergeAndCleanPermissions, s as mergeConfigs, D as mergeMcpServers, t as mergeSettingsFile, o as openSettingsJson, y as readMcpConfig, u as updateDefaultModel, z as writeMcpConfig } from './shared/zcf.CLtDS8Pu.mjs';
1
+ export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, I as I18N, j as LANG_LABELS, L as LEGACY_ZCF_CONFIG_FILE, M as MCP_SERVICES, S as SETTINGS_FILE, h as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE, H as addCompletedOnboarding, x as applyAiLanguageDirective, p as backupExistingConfig, D as backupMcpConfig, F as buildMcpServerConfig, d as cleanupPermissions, c as commandExists, r as configureApi, q as copyConfigFiles, n as ensureClaudeDir, G as fixWindowsMcpConfig, w as getExistingApiConfig, v as getExistingModelConfig, y as getMcpConfigPath, g as getPlatform, a as importRecommendedEnv, b as importRecommendedPermissions, i as init, l as installClaudeCode, k as isClaudeCodeInstalled, m as mergeAndCleanPermissions, s as mergeConfigs, E as mergeMcpServers, t as mergeSettingsFile, o as openSettingsJson, z as readMcpConfig, u as updateDefaultModel, B as writeMcpConfig } from './chunks/simple-config.mjs';
2
2
  import 'inquirer';
3
3
  import 'ansis';
4
4
  import 'node:fs';
@@ -6,6 +6,14 @@ import 'pathe';
6
6
  import 'dayjs';
7
7
  import 'node:url';
8
8
  import 'tinyexec';
9
+ import 'child_process';
10
+ import 'util';
11
+ import 'ora';
12
+ import 'prompts';
13
+ import 'fs/promises';
14
+ import 'path';
15
+ import 'os';
16
+ import 'semver';
9
17
  import 'node:fs/promises';
10
18
  import 'node:child_process';
11
19
  import 'node:util';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "zcf",
3
3
  "type": "module",
4
- "version": "2.8.0",
4
+ "version": "2.8.2",
5
5
  "description": "Zero-Config Claude-Code Flow - One-click configuration tool for Claude Code",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/UfoMiao/zcf",
@@ -21,12 +21,17 @@
21
21
  "templates"
22
22
  ],
23
23
  "dependencies": {
24
+ "@types/prompts": "^2.4.9",
25
+ "@types/semver": "^7.7.0",
24
26
  "ansis": "^3.17.0",
25
27
  "cac": "^6.7.14",
26
28
  "dayjs": "^1.11.13",
27
29
  "find-up-simple": "^1.0.1",
28
30
  "inquirer": "^12.9.0",
31
+ "ora": "^8.2.0",
29
32
  "pathe": "^2.0.3",
33
+ "prompts": "^2.4.2",
34
+ "semver": "^7.7.2",
30
35
  "tinyexec": "^1.0.1"
31
36
  },
32
37
  "devDependencies": {
@@ -1,6 +1,22 @@
1
- ### Prioritize using MCP service
1
+ ## MCP Services Usage Guide
2
2
 
3
- - `Context7`: Query latest library documentation/examples
4
- - `DeepWiki`: Query related GitHub repository documentation/examples
5
- - `Exa`: Use Exa AI for web search - real-time web search, can capture specific URL content. Supports configurable result count and returns most relevant website content
6
- - `Playwright`: Direct browser control for browser-related operations
3
+ ### Documentation & Code Queries
4
+ - **Context7**: Query latest library docs and code examples
5
+ - Use case: When learning new framework or library usage
6
+ - Examples: React Hooks, Vue Composition API queries
7
+
8
+ - **DeepWiki**: Query GitHub repository documentation
9
+ - Use case: When deep-diving into open source implementations
10
+ - Examples: Project architecture, contribution guides
11
+
12
+ ### Information Search
13
+ - **Exa**: AI-powered web search
14
+ - Real-time search for latest tech news
15
+ - Extract complete content from specific URLs
16
+ - Return most relevant search results
17
+
18
+ ### Browser Automation
19
+ - **Playwright**: Browser control
20
+ - Automate web operations and testing
21
+ - Screenshots and page analysis
22
+ - Form filling and interaction testing
@@ -7,6 +7,7 @@ This document provides best practices for Claude Code when executing technical t
7
7
  **Important**: The following operations require explicit user confirmation before execution:
8
8
 
9
9
  ### Operations Requiring Confirmation
10
+
10
11
  - **File System**: Delete files/directories, bulk modifications, move system files
11
12
  - **Code Commits**: `git commit`, `git push`, `git reset --hard`
12
13
  - **System Config**: Modify environment variables, system settings, permissions
@@ -15,7 +16,9 @@ This document provides best practices for Claude Code when executing technical t
15
16
  - **Package Management**: Global install/uninstall, update core dependencies
16
17
 
17
18
  ### Confirmation Process
19
+
18
20
  Before executing dangerous operations:
21
+
19
22
  1. Clearly explain the operation and its impacts
20
23
  2. Wait for explicit user confirmation (e.g., "yes", "confirm", "proceed")
21
24
  3. If user hesitates or declines, provide more information or alternatives
@@ -36,12 +39,14 @@ cd C:\Users\name\My Documents
36
39
  ```
37
40
 
38
41
  ### Cross-Platform Compatibility
42
+
39
43
  - Prefer forward slashes `/` as path separators
40
44
  - When using backslashes, ensure paths are double-quoted
41
45
 
42
46
  ## Search Tool Usage
43
47
 
44
48
  ### Content Search
49
+
45
50
  **Always prioritize `rg` (ripgrep)** - faster and won't timeout.
46
51
 
47
52
  ```bash
@@ -56,6 +61,7 @@ grep -r "pattern" .
56
61
  > Note: If `rg` unavailable, remind user to install: `brew/scoop/apt install ripgrep`
57
62
 
58
63
  ### File Finding
64
+
59
65
  - Use Glob tool for pattern matching
60
66
  - Use LS tool for directory listings
61
67
  - Avoid using `find` command
@@ -77,12 +83,14 @@ grep -r "pattern" .
77
83
  Automatically check documentation update needs after task completion:
78
84
 
79
85
  ### Criteria
86
+
80
87
  - **New Features**: Update README, CHANGELOG, usage docs
81
88
  - **API Changes**: Update API docs, type definitions, interface specs
82
89
  - **Config Changes**: Update config guides, CLAUDE.md, env var docs
83
90
  - **Bug Fixes**: Usually no doc updates needed (unless usage affected)
84
91
 
85
92
  ### Process
93
+
86
94
  1. Analyze code change type and impact scope
87
95
  2. Auto-identify documentation files in project
88
96
  3. List documents needing updates
@@ -90,8 +98,29 @@ Automatically check documentation update needs after task completion:
90
98
  5. Update relevant docs after confirmation
91
99
 
92
100
  ### Common Document Types
101
+
93
102
  - **README.md**: Features, usage, configuration
94
103
  - **CHANGELOG.md**: Version history
95
104
  - **CLAUDE.md**: AI assistant config and instructions
96
105
  - **API Docs**: Interface definitions, parameters
97
- - **Config Docs**: Environment variables, settings
106
+ - **Config Docs**: Environment variables, settings
107
+
108
+ ## AI Assistant Behavior Guidelines
109
+
110
+ The following guidelines define core behavioral standards that AI assistants should follow when executing tasks:
111
+
112
+ ### 1. Persist Until Complete Resolution
113
+
114
+ Remember, you are an agent - please keep going until the user's query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved.
115
+
116
+ ### 2. Base Responses on Facts, Not Guesses
117
+
118
+ If you are not sure about information pertaining to the user's request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer.
119
+
120
+ ### 3. Plan Extensively and Reflect Thoroughly
121
+
122
+ You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls, ensuring user's query is completely resolved. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully. In addition, ensure function calls have the correct arguments.
123
+
124
+ ### 4. Read Before Write Principle
125
+
126
+ Before updating or modifying files, first use the Read tool to read the file contents.
@@ -1,6 +1,22 @@
1
- # 优先使用 MCP 服务:
1
+ ## MCP 服务使用指南
2
2
 
3
- - `Context7`: 查询最新库文档/示例。
4
- - `DeepWiki`: 查询相关 GitHub 仓库的文档/示例。
5
- - `exa`: 使用 Exa AI 进行网页搜索 - 实时网页搜索,能够抓取特定 URL 的内容。支持可配置的结果数量,并返回最相关网站的内容。
6
- - `Playwright`: 直接操控浏览器,进行浏览器相关操作。
3
+ ### 文档与代码查询
4
+ - **Context7**: 查询最新库文档和代码示例
5
+ - 使用场景:需要了解新框架或库的用法时
6
+ - 示例:查询 React Hooks、Vue Composition API 等
7
+
8
+ - **DeepWiki**: 查询 GitHub 仓库文档
9
+ - 使用场景:需要深入了解开源项目实现时
10
+ - 示例:查看项目架构、贡献指南等
11
+
12
+ ### 信息搜索
13
+ - **Exa**: AI 驱动的网页搜索
14
+ - 实时搜索最新技术资讯
15
+ - 抓取特定 URL 的完整内容
16
+ - 返回最相关的搜索结果
17
+
18
+ ### 浏览器自动化
19
+ - **Playwright**: 浏览器操控
20
+ - 自动化网页操作和测试
21
+ - 截图和页面分析
22
+ - 表单填写和交互测试
@@ -7,15 +7,18 @@
7
7
  **重要**:以下操作需要明确的用户确认后才能执行:
8
8
 
9
9
  ### 需确认的操作类型
10
+
10
11
  - **文件系统**:删除文件/目录、批量修改、移动系统文件
11
12
  - **代码提交**:`git commit`、`git push`、`git reset --hard`
12
13
  - **系统配置**:修改环境变量、系统设置、权限变更
13
14
  - **数据操作**:数据库删除、结构变更、批量更新
14
- - **网络请求**:发送敏感数据、调用生产环境API
15
+ - **网络请求**:发送敏感数据、调用生产环境 API
15
16
  - **包管理**:全局安装/卸载、更新核心依赖
16
17
 
17
18
  ### 确认方式
19
+
18
20
  执行危险操作前,必须:
21
+
19
22
  1. 明确说明即将执行的操作及其影响
20
23
  2. 等待用户明确确认(如"是"、"确认"、"继续")
21
24
  3. 用户未确认或表示犹豫时,提供更多信息或替代方案
@@ -36,12 +39,14 @@ cd C:\Users\name\My Documents
36
39
  ```
37
40
 
38
41
  ### 跨平台兼容性
42
+
39
43
  - 优先使用正斜杠 `/` 作为路径分隔符
40
44
  - 使用反斜杠时确保路径被双引号包裹
41
45
 
42
46
  ## 搜索工具使用
43
47
 
44
48
  ### 内容搜索
49
+
45
50
  **始终优先使用 `rg` (ripgrep)**,速度更快且不会超时。
46
51
 
47
52
  ```bash
@@ -56,6 +61,7 @@ grep -r "pattern" .
56
61
  > 提示:如 `rg` 不可用,提醒用户安装:`brew/scoop/apt install ripgrep`
57
62
 
58
63
  ### 文件查找
64
+
59
65
  - 使用 Glob 工具进行模式匹配
60
66
  - 使用 LS 工具列出目录
61
67
  - 避免使用 `find` 命令
@@ -77,12 +83,14 @@ grep -r "pattern" .
77
83
  任务完成后自动检查文档更新需求:
78
84
 
79
85
  ### 判断标准
86
+
80
87
  - **新功能**:需更新 README、CHANGELOG、使用文档
81
- - **API变更**:需更新 API文档、类型定义、接口说明
88
+ - **API 变更**:需更新 API 文档、类型定义、接口说明
82
89
  - **配置变更**:需更新配置说明、CLAUDE.md、环境变量文档
83
- - **Bug修复**:通常无需更新文档(除非影响使用方式)
90
+ - **Bug 修复**:通常无需更新文档(除非影响使用方式)
84
91
 
85
92
  ### 执行流程
93
+
86
94
  1. 分析代码变更类型和影响范围
87
95
  2. 自动识别项目中的文档文件
88
96
  3. 列出需更新的文档清单
@@ -90,8 +98,29 @@ grep -r "pattern" .
90
98
  5. 获得确认后逐一更新相关文档
91
99
 
92
100
  ### 常见文档类型
101
+
93
102
  - **README.md**:功能说明、使用方法、配置说明
94
103
  - **CHANGELOG.md**:版本更新记录
95
- - **CLAUDE.md**:AI助手配置和指令
96
- - **API文档**:接口定义、参数说明
97
- - **配置文档**:环境变量、配置项说明
104
+ - **CLAUDE.md**:AI 助手配置和指令
105
+ - **API 文档**:接口定义、参数说明
106
+ - **配置文档**:环境变量、配置项说明
107
+
108
+ ## AI 助手行为准则
109
+
110
+ 以下准则定义了 AI 助手在执行任务时应遵循的核心行为规范:
111
+
112
+ ### 1. 持续解决问题直至完成
113
+
114
+ 记住,你是一个 AI 助手 - 请持续工作直到用户的问题完全解决,再结束你的回合并交还给用户。只有在确信问题已解决时才终止你的回合。
115
+
116
+ ### 2. 基于事实而非猜测
117
+
118
+ 如果你对用户请求相关的信息不确定,使用你的工具读取文件并收集相关信息:不要猜测或编造答案。
119
+
120
+ ### 3. 充分规划与反思
121
+
122
+ 你必须在每次函数调用前进行充分的规划,并对之前函数调用的结果进行充分的反思,确保用户的问题完全解决。不要仅通过函数调用来完成整个过程,因为这可能会损害你解决问题和深入思考的能力。此外,确保函数调用具有正确的参数。
123
+
124
+ ### 4. 先读后写原则
125
+
126
+ 在更新或修改文件前,先使用 Read 工具读取文件内容。