zcf 2.12.7 → 2.12.9

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 & WitMiao
3
+ Copyright (c) 2025-PRESENT UfoMiao <https://github.com/UfoMiao> & Miao Da <https://github.com/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
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
package/README.md CHANGED
@@ -24,13 +24,29 @@ 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 settings, AI output style, environment permissions, etc.)
27
+ - `3` Configure API or CCR - API configuration or CCR proxy setup
28
+ - `4` Configure MCP - MCP service configuration and management
29
+ - `5` Configure default model - Set default model (opus/sonnet/opusplan/custom)
30
+ - `6` Configure AI memory - Configure AI output language and global output style
31
+ - `7` Configure environment permissions - Import environment variables and permissions
28
32
  - `R` Claude Code Router management (enhanced in v2.8.1)
29
33
  - `U` ccusage - Claude Code usage analysis
30
34
  - `L` CCometixLine - High-performance statusline tool with Git integration and real-time usage tracking (v2.9.9+ new)
31
35
  - `+` Check updates - Check and update Claude Code, CCR and CCometixLine versions (v2.9.9+ enhanced)
32
36
  - More features...
33
37
 
38
+ #### 🎯 Key Configuration Features
39
+
40
+ **Model Configuration (Option 5)**: Configure your default Claude model with flexible options:
41
+ - **Default**: Let Claude Code automatically choose the best model for each task
42
+ - **Opus**: Use Claude-3.5-Opus exclusively (high token consumption, use with caution)
43
+ - **OpusPlan**: Use Opus for planning, Sonnet for implementation (recommended balance)
44
+ - **Custom**: Specify your own model names for both primary and fast tasks (supports any custom model)
45
+
46
+ **AI Memory Configuration (Option 6)**: Personalize your AI assistant:
47
+ - **AI Output Language**: Set the language for AI responses (Chinese, English, or custom)
48
+ - **Global Output Style**: Configure AI personality and response style
49
+
34
50
  ### Or, use direct commands:
35
51
 
36
52
  #### 🆕 First time using Claude Code
@@ -102,7 +118,7 @@ When using `--skip-prompt`, the following parameters are available:
102
118
  | `--api-type, -t` | API configuration type | `auth_token`, `api_key`, `ccr_proxy`, `skip` | No | `skip` |
103
119
  | `--api-key, -k` | API key (for both API key and auth token types) | string | Required when `api-type` is not `skip` | - |
104
120
  | `--api-url, -u` | Custom API URL | URL string | No | official API |
105
- | `--mcp-services, -m` | MCP services to install (multi-select, comma-separated) | `context7`, `mcp-deepwiki`, `Playwright`, `exa`, or `skip` for none | No | `all` |
121
+ | `--mcp-services, -m` | MCP services to install (multi-select, comma-separated) | `context7`, `open-websearch`, `spec-workflow`, `mcp-deepwiki`, `Playwright`, `exa`, or `skip` for none | No | `all` |
106
122
  | `--workflows, -w` | Workflows to install (multi-select, comma-separated) | `commonTools`, `sixStepsWorkflow`, `featPlanUx`, `gitWorkflow`, `bmadWorkflow`, or `skip` for none | No | `all` |
107
123
  | `--output-styles, -o` | Output styles to install (multi-select, comma-separated) | `engineer-professional`, `nekomata-engineer`, `laowang-engineer`, or `skip` for none | No | `all` |
108
124
  | `--default-output-style, -d` | Default output style | Same as output styles plus built-in: `default`, `explanatory`, `learning` | No | `engineer-professional` |
@@ -167,6 +183,16 @@ Alternatively, you can install the [VS Code extension](https://marketplace.visua
167
183
 
168
184
  **Usage Guide**: For detailed usage instructions and best practices, see the [official Spec Workflow documentation](https://github.com/Pimzino/spec-workflow-mcp/blob/main/README.md#quick-start).
169
185
 
186
+ #### 🔍 Open Web Search (v2.12.9+ New Feature)
187
+
188
+ [Open Web Search](https://github.com/Aas-ee/open-webSearch) is a versatile web search MCP service that provides access to multiple search engines:
189
+
190
+ - **Multi-Engine Support**: Search across DuckDuckGo, Bing, and Brave search engines
191
+ - **Privacy-Focused**: Uses privacy-respecting search engines as defaults
192
+ - **Flexible Configuration**: Customizable search engine preferences
193
+ - **No API Key Required**: Ready to use without additional authentication
194
+ - **Search Aggregation**: Ability to combine results from multiple engines
195
+
170
196
  #### 🚀 CCR (Claude Code Router) Support (v2.8+ Enhanced)
171
197
 
172
198
  [CCR](https://github.com/musistudio/claude-code-router/blob/main/README.md) is a powerful proxy router that enables:
@@ -311,7 +337,7 @@ Select function:
311
337
  2. Import workflow - Import/update workflow-related files only
312
338
  3. Configure API - Configure API URL and authentication (supports CCR proxy)
313
339
  4. Configure MCP - Configure MCP services (includes Windows fix)
314
- 5. Configure default model - Set default model (opus/sonnet)
340
+ 5. Configure default model - Set default model (opus/sonnet/opusplan/custom)
315
341
  6. Configure Claude global memory - Configure AI output language and output styles
316
342
  7. Import recommended environment variables and permissions - Import privacy protection environment variables and system permissions
317
343
 
@@ -2,20 +2,20 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, readd
2
2
  import process from 'node:process';
3
3
  import ansis from 'ansis';
4
4
  import inquirer from 'inquirer';
5
- import { fileURLToPath } from 'node:url';
6
- import i18next from 'i18next';
7
- import Backend from 'i18next-fs-backend';
8
- import { dirname, join } from 'pathe';
9
5
  import { exec as exec$1 } from 'node:child_process';
10
6
  import { homedir, platform } from 'node:os';
11
7
  import { promisify } from 'node:util';
12
8
  import dayjs from 'dayjs';
9
+ import { dirname, join } from 'pathe';
10
+ import { fileURLToPath } from 'node:url';
13
11
  import ora from 'ora';
14
12
  import semver from 'semver';
15
13
  import { exec } from 'tinyexec';
16
14
  import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
15
+ import i18next from 'i18next';
16
+ import Backend from 'i18next-fs-backend';
17
17
 
18
- const version = "2.12.7";
18
+ const version = "2.12.9";
19
19
  const homepage = "https://github.com/UfoMiao/zcf";
20
20
 
21
21
  const i18n = i18next.createInstance();
@@ -131,6 +131,20 @@ const MCP_SERVICE_CONFIGS = [
131
131
  env: {}
132
132
  }
133
133
  },
134
+ {
135
+ id: "open-websearch",
136
+ requiresApiKey: false,
137
+ config: {
138
+ type: "stdio",
139
+ command: "npx",
140
+ args: ["-y", "open-websearch@latest"],
141
+ env: {
142
+ MODE: "stdio",
143
+ DEFAULT_SEARCH_ENGINE: "duckduckgo",
144
+ ALLOWED_SEARCH_ENGINES: "duckduckgo,bing,brave"
145
+ }
146
+ }
147
+ },
134
148
  {
135
149
  id: "spec-workflow",
136
150
  requiresApiKey: false,
@@ -178,21 +192,20 @@ const MCP_SERVICE_CONFIGS = [
178
192
  async function getMcpServices() {
179
193
  ensureI18nInitialized();
180
194
  const mcpServiceList = [
181
- {
182
- id: "Playwright",
183
- name: i18n.t("mcp:services.Playwright.name"),
184
- description: i18n.t("mcp:services.Playwright.description")
185
- },
186
195
  {
187
196
  id: "context7",
188
197
  name: i18n.t("mcp:services.context7.name"),
189
198
  description: i18n.t("mcp:services.context7.description")
190
199
  },
191
200
  {
192
- id: "exa",
193
- name: i18n.t("mcp:services.exa.name"),
194
- description: i18n.t("mcp:services.exa.description"),
195
- apiKeyPrompt: i18n.t("mcp:services.exa.apiKeyPrompt")
201
+ id: "open-websearch",
202
+ name: i18n.t("mcp:services.open-websearch.name"),
203
+ description: i18n.t("mcp:services.open-websearch.description")
204
+ },
205
+ {
206
+ id: "spec-workflow",
207
+ name: i18n.t("mcp:services.spec-workflow.name"),
208
+ description: i18n.t("mcp:services.spec-workflow.description")
196
209
  },
197
210
  {
198
211
  id: "mcp-deepwiki",
@@ -200,9 +213,15 @@ async function getMcpServices() {
200
213
  description: i18n.t("mcp:services.mcp-deepwiki.description")
201
214
  },
202
215
  {
203
- id: "spec-workflow",
204
- name: i18n.t("mcp:services.spec-workflow.name"),
205
- description: i18n.t("mcp:services.spec-workflow.description")
216
+ id: "Playwright",
217
+ name: i18n.t("mcp:services.Playwright.name"),
218
+ description: i18n.t("mcp:services.Playwright.description")
219
+ },
220
+ {
221
+ id: "exa",
222
+ name: i18n.t("mcp:services.exa.name"),
223
+ description: i18n.t("mcp:services.exa.description"),
224
+ apiKeyPrompt: i18n.t("mcp:services.exa.apiKeyPrompt")
206
225
  }
207
226
  ];
208
227
  return MCP_SERVICE_CONFIGS.map((config) => {
@@ -345,22 +364,10 @@ const AI_OUTPUT_LANGUAGES = {
345
364
  "en": { directive: "Always respond in English" },
346
365
  "custom": { directive: "" }
347
366
  };
348
- let _i18n = null;
349
- function getI18nInstance() {
350
- if (!_i18n) {
351
- try {
352
- const i18nModule = eval('require("./i18n")');
353
- _i18n = i18nModule.i18n;
354
- } catch {
355
- }
356
- }
357
- return _i18n;
358
- }
359
367
  function getAiOutputLanguageLabel(lang) {
360
368
  if (lang in LANG_LABELS) {
361
369
  return LANG_LABELS[lang];
362
370
  }
363
- const i18n = getI18nInstance();
364
371
  if (lang === "custom" && i18n?.isInitialized) {
365
372
  try {
366
373
  return i18n.t("language:labels.custom");
@@ -883,14 +890,42 @@ function mergeConfigs(sourceFile, targetFile) {
883
890
  const merged = deepMerge(target, source);
884
891
  writeJsonConfig(targetFile, merged);
885
892
  }
893
+ function updateCustomModel(primaryModel, fastModel) {
894
+ if (!primaryModel?.trim() && !fastModel?.trim()) {
895
+ return;
896
+ }
897
+ let settings = getDefaultSettings();
898
+ const existingSettings = readJsonConfig(SETTINGS_FILE);
899
+ if (existingSettings) {
900
+ settings = existingSettings;
901
+ }
902
+ delete settings.model;
903
+ settings.env = settings.env || {};
904
+ if (primaryModel?.trim()) {
905
+ settings.env.ANTHROPIC_MODEL = primaryModel.trim();
906
+ }
907
+ if (fastModel?.trim()) {
908
+ settings.env.ANTHROPIC_SMALL_FAST_MODEL = fastModel.trim();
909
+ }
910
+ writeJsonConfig(SETTINGS_FILE, settings);
911
+ }
886
912
  function updateDefaultModel(model) {
887
913
  let settings = getDefaultSettings();
888
914
  const existingSettings = readJsonConfig(SETTINGS_FILE);
889
915
  if (existingSettings) {
890
916
  settings = existingSettings;
891
917
  }
918
+ if (!settings.env) {
919
+ settings.env = {};
920
+ }
921
+ if (model !== "custom" && settings.env) {
922
+ delete settings.env.ANTHROPIC_MODEL;
923
+ delete settings.env.ANTHROPIC_SMALL_FAST_MODEL;
924
+ }
892
925
  if (model === "default") {
893
926
  delete settings.model;
927
+ } else if (model === "custom") {
928
+ delete settings.model;
894
929
  } else {
895
930
  settings.model = model;
896
931
  }
@@ -940,6 +975,9 @@ function getExistingModelConfig() {
940
975
  if (!settings) {
941
976
  return null;
942
977
  }
978
+ if (settings.env && (settings.env.ANTHROPIC_MODEL || settings.env.ANTHROPIC_SMALL_FAST_MODEL)) {
979
+ return "custom";
980
+ }
943
981
  if (!settings.model) {
944
982
  return "default";
945
983
  }
@@ -1484,8 +1522,7 @@ async function checkClaudeCodeVersionAndPrompt(skipPrompt = false) {
1484
1522
  return;
1485
1523
  }
1486
1524
  const { updateClaudeCode } = await Promise.resolve().then(function () { return autoUpdater; });
1487
- const forceUpdate = skipPrompt;
1488
- await updateClaudeCode(forceUpdate);
1525
+ await updateClaudeCode(false, skipPrompt);
1489
1526
  } catch (error) {
1490
1527
  const errorMessage = error instanceof Error ? error.message : String(error);
1491
1528
  console.warn(`Claude Code version check failed: ${errorMessage}`);
@@ -1493,7 +1530,7 @@ async function checkClaudeCodeVersionAndPrompt(skipPrompt = false) {
1493
1530
  }
1494
1531
 
1495
1532
  const execAsync$2 = promisify(exec$1);
1496
- async function updateCcr(force = false) {
1533
+ async function updateCcr(force = false, skipPrompt = false) {
1497
1534
  ensureI18nInitialized();
1498
1535
  const spinner = ora(i18n.t("updater:checkingVersion")).start();
1499
1536
  try {
@@ -1513,15 +1550,19 @@ async function updateCcr(force = false) {
1513
1550
  }
1514
1551
  console.log(ansis.cyan(format(i18n.t("updater:currentVersion"), { version: currentVersion || "" })));
1515
1552
  console.log(ansis.cyan(format(i18n.t("updater:latestVersion"), { version: latestVersion })));
1516
- const { confirm } = await inquirer.prompt({
1517
- type: "confirm",
1518
- name: "confirm",
1519
- message: format(i18n.t("updater:confirmUpdate"), { tool: "CCR" }),
1520
- default: true
1521
- });
1522
- if (!confirm) {
1523
- console.log(ansis.gray(i18n.t("updater:updateSkipped")));
1524
- return true;
1553
+ if (!skipPrompt) {
1554
+ const { confirm } = await inquirer.prompt({
1555
+ type: "confirm",
1556
+ name: "confirm",
1557
+ message: format(i18n.t("updater:confirmUpdate"), { tool: "CCR" }),
1558
+ default: true
1559
+ });
1560
+ if (!confirm) {
1561
+ console.log(ansis.gray(i18n.t("updater:updateSkipped")));
1562
+ return true;
1563
+ }
1564
+ } else {
1565
+ console.log(ansis.cyan(format(i18n.t("updater:autoUpdating"), { tool: "CCR" })));
1525
1566
  }
1526
1567
  const updateSpinner = ora(format(i18n.t("updater:updating"), { tool: "CCR" })).start();
1527
1568
  try {
@@ -1539,7 +1580,7 @@ async function updateCcr(force = false) {
1539
1580
  return false;
1540
1581
  }
1541
1582
  }
1542
- async function updateClaudeCode(force = false) {
1583
+ async function updateClaudeCode(force = false, skipPrompt = false) {
1543
1584
  ensureI18nInitialized();
1544
1585
  const spinner = ora(i18n.t("updater:checkingVersion")).start();
1545
1586
  try {
@@ -1559,15 +1600,19 @@ async function updateClaudeCode(force = false) {
1559
1600
  }
1560
1601
  console.log(ansis.cyan(format(i18n.t("updater:currentVersion"), { version: currentVersion || "" })));
1561
1602
  console.log(ansis.cyan(format(i18n.t("updater:latestVersion"), { version: latestVersion })));
1562
- const { confirm } = await inquirer.prompt({
1563
- type: "confirm",
1564
- name: "confirm",
1565
- message: format(i18n.t("updater:confirmUpdate"), { tool: "Claude Code" }),
1566
- default: true
1567
- });
1568
- if (!confirm) {
1569
- console.log(ansis.gray(i18n.t("updater:updateSkipped")));
1570
- return true;
1603
+ if (!skipPrompt) {
1604
+ const { confirm } = await inquirer.prompt({
1605
+ type: "confirm",
1606
+ name: "confirm",
1607
+ message: format(i18n.t("updater:confirmUpdate"), { tool: "Claude Code" }),
1608
+ default: true
1609
+ });
1610
+ if (!confirm) {
1611
+ console.log(ansis.gray(i18n.t("updater:updateSkipped")));
1612
+ return true;
1613
+ }
1614
+ } else {
1615
+ console.log(ansis.cyan(format(i18n.t("updater:autoUpdating"), { tool: "Claude Code" })));
1571
1616
  }
1572
1617
  const updateSpinner = ora(format(i18n.t("updater:updating"), { tool: "Claude Code" })).start();
1573
1618
  try {
@@ -1585,7 +1630,7 @@ async function updateClaudeCode(force = false) {
1585
1630
  return false;
1586
1631
  }
1587
1632
  }
1588
- async function updateCometixLine(force = false) {
1633
+ async function updateCometixLine(force = false, skipPrompt = false) {
1589
1634
  ensureI18nInitialized();
1590
1635
  const spinner = ora(i18n.t("updater:checkingVersion")).start();
1591
1636
  try {
@@ -1605,15 +1650,19 @@ async function updateCometixLine(force = false) {
1605
1650
  }
1606
1651
  console.log(ansis.cyan(format(i18n.t("updater:currentVersion"), { version: currentVersion || "" })));
1607
1652
  console.log(ansis.cyan(format(i18n.t("updater:latestVersion"), { version: latestVersion })));
1608
- const { confirm } = await inquirer.prompt({
1609
- type: "confirm",
1610
- name: "confirm",
1611
- message: format(i18n.t("updater:confirmUpdate"), { tool: "CCometixLine" }),
1612
- default: true
1613
- });
1614
- if (!confirm) {
1615
- console.log(ansis.gray(i18n.t("updater:updateSkipped")));
1616
- return true;
1653
+ if (!skipPrompt) {
1654
+ const { confirm } = await inquirer.prompt({
1655
+ type: "confirm",
1656
+ name: "confirm",
1657
+ message: format(i18n.t("updater:confirmUpdate"), { tool: "CCometixLine" }),
1658
+ default: true
1659
+ });
1660
+ if (!confirm) {
1661
+ console.log(ansis.gray(i18n.t("updater:updateSkipped")));
1662
+ return true;
1663
+ }
1664
+ } else {
1665
+ console.log(ansis.cyan(format(i18n.t("updater:autoUpdating"), { tool: "CCometixLine" })));
1617
1666
  }
1618
1667
  const updateSpinner = ora(format(i18n.t("updater:updating"), { tool: "CCometixLine" })).start();
1619
1668
  try {
@@ -1631,16 +1680,49 @@ async function updateCometixLine(force = false) {
1631
1680
  return false;
1632
1681
  }
1633
1682
  }
1634
- async function checkAndUpdateTools() {
1683
+ async function checkAndUpdateTools(skipPrompt = false) {
1635
1684
  ensureI18nInitialized();
1636
1685
  console.log(ansis.bold.cyan(`
1637
1686
  \u{1F50D} ${i18n.t("updater:checkingTools")}
1638
1687
  `));
1639
- await updateCcr();
1688
+ const results = [];
1689
+ try {
1690
+ const success = await updateCcr(false, skipPrompt);
1691
+ results.push({ tool: "CCR", success });
1692
+ } catch (error) {
1693
+ const errorMessage = error instanceof Error ? error.message : String(error);
1694
+ console.error(ansis.red(`\u274C ${format(i18n.t("updater:updateFailed"), { tool: "CCR" })}: ${errorMessage}`));
1695
+ results.push({ tool: "CCR", success: false, error: errorMessage });
1696
+ }
1640
1697
  console.log();
1641
- await updateClaudeCode();
1698
+ try {
1699
+ const success = await updateClaudeCode(false, skipPrompt);
1700
+ results.push({ tool: "Claude Code", success });
1701
+ } catch (error) {
1702
+ const errorMessage = error instanceof Error ? error.message : String(error);
1703
+ console.error(ansis.red(`\u274C ${format(i18n.t("updater:updateFailed"), { tool: "Claude Code" })}: ${errorMessage}`));
1704
+ results.push({ tool: "Claude Code", success: false, error: errorMessage });
1705
+ }
1642
1706
  console.log();
1643
- await updateCometixLine();
1707
+ try {
1708
+ const success = await updateCometixLine(false, skipPrompt);
1709
+ results.push({ tool: "CCometixLine", success });
1710
+ } catch (error) {
1711
+ const errorMessage = error instanceof Error ? error.message : String(error);
1712
+ console.error(ansis.red(`\u274C ${format(i18n.t("updater:updateFailed"), { tool: "CCometixLine" })}: ${errorMessage}`));
1713
+ results.push({ tool: "CCometixLine", success: false, error: errorMessage });
1714
+ }
1715
+ if (skipPrompt) {
1716
+ console.log(ansis.bold.cyan(`
1717
+ \u{1F4CB} ${i18n.t("updater:updateSummary")}`));
1718
+ for (const result of results) {
1719
+ if (result.success) {
1720
+ console.log(ansis.green(`\u2714 ${result.tool}: ${i18n.t("updater:success")}`));
1721
+ } else {
1722
+ console.log(ansis.red(`\u274C ${result.tool}: ${i18n.t("updater:failed")} ${result.error ? `(${result.error})` : ""}`));
1723
+ }
1724
+ }
1725
+ }
1644
1726
  }
1645
1727
 
1646
1728
  const autoUpdater = {
@@ -3156,4 +3238,4 @@ async function openSettingsJson() {
3156
3238
  }
3157
3239
  }
3158
3240
 
3159
- export { getMcpServices as $, AI_OUTPUT_LANGUAGES as A, readMcpConfig as B, CLAUDE_DIR as C, writeMcpConfig as D, backupMcpConfig as E, mergeMcpServers as F, buildMcpServerConfig as G, fixWindowsMcpConfig as H, addCompletedOnboarding as I, ensureI18nInitialized as J, i18n as K, LEGACY_ZCF_CONFIG_FILE as L, readCcrConfig as M, isCcrInstalled as N, installCcr as O, configureCcrFeature as P, handleExitPromptError as Q, handleGeneralError as R, SETTINGS_FILE as S, addNumbersToChoices as T, updateZcfConfig as U, changeLanguage as V, readZcfConfig as W, configureOutputStyle as X, isWindows as Y, ZCF_CONFIG_FILE as Z, selectMcpServices as _, commandExists as a, formatApiKeyDisplay as a0, modifyApiConfigPartially as a1, setupCcrConfiguration as a2, validateApiKey as a3, COMETIX_COMMAND_NAME as a4, COMETIX_COMMANDS as a5, installCometixLine as a6, checkAndUpdateTools as a7, displayBanner as a8, resolveAiOutputLanguage as a9, updatePromptOnly as aa, selectAndInstallWorkflows as ab, checkClaudeCodeVersionAndPrompt as ac, version as ad, displayBannerWithInfo as ae, readZcfConfigAsync as af, initI18n as ag, selectScriptLanguage as ah, prompts as ai, importRecommendedEnv as b, cleanupPermissions as c, importRecommendedPermissions 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, getAiOutputLanguageLabel as k, ensureClaudeDir as l, mergeAndCleanPermissions as m, backupExistingConfig as n, openSettingsJson as o, copyConfigFiles as p, configureApi as q, mergeConfigs as r, mergeSettingsFile as s, getExistingModelConfig as t, updateDefaultModel as u, getExistingApiConfig as v, applyAiLanguageDirective as w, isClaudeCodeInstalled as x, installClaudeCode as y, getMcpConfigPath as z };
3241
+ export { selectMcpServices as $, AI_OUTPUT_LANGUAGES as A, getMcpConfigPath as B, CLAUDE_DIR as C, readMcpConfig as D, writeMcpConfig as E, backupMcpConfig as F, mergeMcpServers as G, buildMcpServerConfig as H, fixWindowsMcpConfig as I, addCompletedOnboarding as J, ensureI18nInitialized as K, LEGACY_ZCF_CONFIG_FILE as L, i18n as M, readCcrConfig as N, isCcrInstalled as O, installCcr as P, configureCcrFeature as Q, handleExitPromptError as R, SETTINGS_FILE as S, handleGeneralError as T, addNumbersToChoices as U, updateZcfConfig as V, changeLanguage as W, readZcfConfig as X, configureOutputStyle as Y, ZCF_CONFIG_FILE as Z, isWindows as _, commandExists as a, getMcpServices as a0, formatApiKeyDisplay as a1, modifyApiConfigPartially as a2, setupCcrConfiguration as a3, validateApiKey as a4, COMETIX_COMMAND_NAME as a5, COMETIX_COMMANDS as a6, installCometixLine as a7, checkAndUpdateTools as a8, displayBanner as a9, resolveAiOutputLanguage as aa, updatePromptOnly as ab, selectAndInstallWorkflows as ac, checkClaudeCodeVersionAndPrompt as ad, version as ae, displayBannerWithInfo as af, readZcfConfigAsync as ag, initI18n as ah, selectScriptLanguage as ai, prompts as aj, importRecommendedEnv as b, cleanupPermissions as c, importRecommendedPermissions 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, getAiOutputLanguageLabel as k, ensureClaudeDir as l, mergeAndCleanPermissions as m, backupExistingConfig as n, openSettingsJson as o, copyConfigFiles as p, configureApi as q, mergeConfigs as r, updateDefaultModel as s, mergeSettingsFile as t, updateCustomModel as u, getExistingModelConfig as v, getExistingApiConfig as w, applyAiLanguageDirective as x, isClaudeCodeInstalled as y, installClaudeCode 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 { 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';
4
+ import { K as ensureI18nInitialized, M as i18n, N as readCcrConfig, O as isCcrInstalled, P as installCcr, Q as configureCcrFeature, R as handleExitPromptError, T as handleGeneralError, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, U as addNumbersToChoices, j as LANG_LABELS, V as updateZcfConfig, W as changeLanguage, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, X as readZcfConfig, x as applyAiLanguageDirective, Y as configureOutputStyle, v as getExistingModelConfig, u as updateCustomModel, s as updateDefaultModel, _ as isWindows, D as readMcpConfig, I as fixWindowsMcpConfig, E as writeMcpConfig, $ as selectMcpServices, F as backupMcpConfig, a0 as getMcpServices, H as buildMcpServerConfig, G as mergeMcpServers, w as getExistingApiConfig, a1 as formatApiKeyDisplay, J as addCompletedOnboarding, a2 as modifyApiConfigPartially, a3 as setupCcrConfiguration, a4 as validateApiKey, q as configureApi, a5 as COMETIX_COMMAND_NAME, a6 as COMETIX_COMMANDS, a7 as installCometixLine, a8 as checkAndUpdateTools, a9 as displayBanner, aa as resolveAiOutputLanguage, ab as updatePromptOnly, ac as selectAndInstallWorkflows, ad as checkClaudeCodeVersionAndPrompt, ae as version, af as displayBannerWithInfo, i as init, ag as readZcfConfigAsync, ah as initI18n, ai as selectScriptLanguage } from './chunks/simple-config.mjs';
5
5
  import { existsSync, unlinkSync } from 'node:fs';
6
6
  import { homedir } from 'node:os';
7
7
  import inquirer from 'inquirer';
@@ -10,13 +10,13 @@ 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 'node:url';
14
- import 'i18next';
15
- import 'i18next-fs-backend';
16
13
  import 'dayjs';
14
+ import 'node:url';
17
15
  import 'ora';
18
16
  import 'semver';
19
17
  import 'node:fs/promises';
18
+ import 'i18next';
19
+ import 'i18next-fs-backend';
20
20
 
21
21
  const execAsync$1 = promisify(exec);
22
22
  async function runCcrUi(apiKey) {
@@ -340,10 +340,11 @@ ${ansis.blue(`\u2139 ${i18n.t("api:existingApiConfig")}`)}`);
340
340
  const { url } = await inquirer.prompt({
341
341
  type: "input",
342
342
  name: "url",
343
- message: i18n.t("api:enterApiUrl"),
344
- validate: async (value) => {
345
- if (!value)
346
- return i18n.t("api:urlRequired");
343
+ message: `${i18n.t("api:enterApiUrl")}${i18n.t("common:emptyToSkip")}`,
344
+ validate: (value) => {
345
+ if (!value) {
346
+ return true;
347
+ }
347
348
  try {
348
349
  void new URL(value);
349
350
  return true;
@@ -352,27 +353,27 @@ ${ansis.blue(`\u2139 ${i18n.t("api:existingApiConfig")}`)}`);
352
353
  }
353
354
  }
354
355
  });
355
- if (!url) {
356
+ if (url === void 0 || !url) {
356
357
  await handleCancellation();
357
358
  return;
358
359
  }
359
- const keyMessage = apiChoice === "auth_token" ? i18n.t("api:enterAuthToken") : i18n.t("api:enterApiKey");
360
+ const keyMessage = apiChoice === "auth_token" ? `${i18n.t("api:enterAuthToken")}${i18n.t("common:emptyToSkip")}` : `${i18n.t("api:enterApiKey")}${i18n.t("common:emptyToSkip")}`;
360
361
  const { key } = await inquirer.prompt({
361
362
  type: "input",
362
363
  name: "key",
363
364
  message: keyMessage,
364
- validate: async (value) => {
365
+ validate: (value) => {
365
366
  if (!value) {
366
- return i18n.t("api:keyRequired");
367
+ return true;
367
368
  }
368
- const validation = await validateApiKey(value);
369
+ const validation = validateApiKey(value);
369
370
  if (!validation.isValid) {
370
371
  return validation.error || i18n.t("api:invalidKeyFormat");
371
372
  }
372
373
  return true;
373
374
  }
374
375
  });
375
- if (!key) {
376
+ if (key === void 0 || !key) {
376
377
  await handleCancellation();
377
378
  return;
378
379
  }
@@ -473,17 +474,46 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingModelConfig") || "Existing
473
474
  {
474
475
  name: i18n.t("configuration:opusPlanModelOption") || "OpusPlan - Use Opus for planning, write code with sonnet, recommended",
475
476
  value: "opusplan"
477
+ },
478
+ {
479
+ name: i18n.t("configuration:customModelOption") || "Custom - Specify custom model names",
480
+ value: "custom"
476
481
  }
477
482
  ]),
478
- default: existingModel ? ["default", "opus", "opusplan"].indexOf(existingModel) : 0
483
+ default: existingModel ? ["default", "opus", "opusplan", "custom"].indexOf(existingModel) : 0
479
484
  });
480
485
  if (!model) {
481
486
  await handleCancellation();
482
487
  return;
483
488
  }
489
+ if (model === "custom") {
490
+ const { primaryModel, fastModel } = await promptCustomModels();
491
+ if (!primaryModel.trim() && !fastModel.trim()) {
492
+ console.log(ansis.yellow(`\u26A0 ${i18n.t("configuration:customModelSkipped") || "Custom model configuration skipped"}`));
493
+ return;
494
+ }
495
+ updateCustomModel(primaryModel, fastModel);
496
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:customModelConfigured") || "Custom model configuration completed"}`));
497
+ return;
498
+ }
484
499
  updateDefaultModel(model);
485
500
  console.log(ansis.green(`\u2714 ${i18n.t("configuration:modelConfigured") || "Default model configured"}`));
486
501
  }
502
+ async function promptCustomModels() {
503
+ const { primaryModel } = await inquirer.prompt({
504
+ type: "input",
505
+ name: "primaryModel",
506
+ message: `${i18n.t("configuration:enterPrimaryModel")}${i18n.t("common:emptyToSkip")}`,
507
+ default: ""
508
+ });
509
+ const { fastModel } = await inquirer.prompt({
510
+ type: "input",
511
+ name: "fastModel",
512
+ message: `${i18n.t("configuration:enterFastModel")}${i18n.t("common:emptyToSkip")}`,
513
+ default: ""
514
+ });
515
+ return { primaryModel, fastModel };
516
+ }
487
517
  async function configureAiMemoryFeature() {
488
518
  ensureI18nInitialized();
489
519
  const { option } = await inquirer.prompt({
@@ -525,7 +555,7 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existi
525
555
  return;
526
556
  }
527
557
  }
528
- const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.ai; });
558
+ const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aj; });
529
559
  const aiOutputLang = await selectAiOutputLanguage();
530
560
  applyAiLanguageDirective(aiOutputLang);
531
561
  updateZcfConfig({ aiOutputLang });
@@ -825,11 +855,13 @@ async function runCometixMenuFeature() {
825
855
  await showCometixMenu();
826
856
  }
827
857
 
828
- async function checkUpdates() {
858
+ async function checkUpdates(options = {}) {
829
859
  try {
830
- await checkAndUpdateTools();
860
+ const skipPrompt = options.skipPrompt || false;
861
+ await checkAndUpdateTools(skipPrompt);
831
862
  } catch (error) {
832
- console.error(ansis.red(i18n.t("updater:errorCheckingUpdates")), error);
863
+ const errorMessage = error instanceof Error ? error.message : String(error);
864
+ console.error(ansis.red(`${i18n.t("updater:errorCheckingUpdates")} ${errorMessage}`));
833
865
  process.exit(1);
834
866
  }
835
867
  }
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "multiSelectHint": " (Space to select, a to select all, i to invert, Enter to confirm)",
3
3
  "skip": "Skip",
4
+ "emptyToSkip": " (press Enter with empty content to skip)",
4
5
  "cancelled": "Operation cancelled",
5
6
  "error": "Error",
6
7
  "complete": "🎉 Setup complete! Use 'claude' command to start.",
@@ -8,10 +8,15 @@
8
8
  "configureAiLanguage": "Configure AI output language",
9
9
  "configureOutputStyle": "Configure global AI output style",
10
10
  "confirmClearCache": "Confirm clear all ZCF preference cache?",
11
+ "customModelConfigured": "Custom model configuration completed",
12
+ "customModelOption": "Custom - Specify custom model names",
13
+ "customModelSkipped": "Custom model configuration skipped",
11
14
  "currentLanguage": "Current language",
12
15
  "currentModel": "Current model",
13
16
  "defaultModelOption": "Default - Let Claude Code choose",
14
17
  "defaultStyle": "Default style",
18
+ "enterFastModel": "Enter fast model name for background tasks",
19
+ "enterPrimaryModel": "Enter primary model name",
15
20
  "envImportSuccess": "Environment variables imported",
16
21
  "existingConfig": "Existing config detected. How to proceed?",
17
22
  "existingLanguageConfig": "Existing AI output language configuration detected",
@@ -7,6 +7,8 @@
7
7
  "services.Playwright.name": "Playwright Browser Control",
8
8
  "services.context7.description": "Query latest library documentation and code examples",
9
9
  "services.context7.name": "Context7 Docs",
10
+ "services.open-websearch.description": "Web search using DuckDuckGo, Bing, and Brave search engines",
11
+ "services.open-websearch.name": "Open Web Search",
10
12
  "services.exa.apiKeyPrompt": "Enter Exa API Key",
11
13
  "services.exa.description": "Web search using Exa AI",
12
14
  "services.exa.name": "Exa AI Search",
@@ -9,7 +9,7 @@
9
9
  "menuDescriptions.configureApiOrCcr": "Configure API URL, authentication or CCR proxy",
10
10
  "menuDescriptions.configureEnvPermission": "Import privacy protection environment variables and system permissions",
11
11
  "menuDescriptions.configureMcp": "Configure MCP services (includes Windows fix)",
12
- "menuDescriptions.configureModel": "Set default model (opus/sonnet)",
12
+ "menuDescriptions.configureModel": "Set default model (opus/sonnet/opusplan/custom)",
13
13
  "menuDescriptions.fullInit": "Install Claude Code + Import workflow + Configure API or CCR proxy + Configure MCP services",
14
14
  "menuDescriptions.importWorkflow": "Import/update workflow-related files only",
15
15
  "menuOptions.ccrManagement": "CCR",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "autoUpdating": "Auto-updating {tool}...",
2
3
  "cannotCheckVersion": "Cannot check latest version",
3
4
  "ccrNotInstalled": "CCR is not installed",
4
5
  "ccrUpToDate": "CCR is up to date (v{version})",
@@ -12,9 +13,12 @@
12
13
  "confirmUpdate": "Update {tool} to the latest version?",
13
14
  "currentVersion": "Current version: v{version}",
14
15
  "errorCheckingUpdates": "Error checking updates:",
16
+ "failed": "failed",
15
17
  "latestVersion": "Latest version: v{version}",
18
+ "success": "success",
16
19
  "updateFailed": "{tool} update failed",
17
20
  "updateSkipped": "Update skipped",
18
21
  "updateSuccess": "{tool} updated successfully!",
22
+ "updateSummary": "Update Summary",
19
23
  "updating": "Updating {tool}..."
20
24
  }
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "multiSelectHint": "(空格选择,a全选,i反选,回车确认)",
3
3
  "skip": "跳过",
4
+ "emptyToSkip": "(空内容回车则跳过)",
4
5
  "cancelled": "操作已取消",
5
6
  "error": "错误",
6
7
  "complete": "🎉 配置完成!使用 'claude' 命令开始体验。",
@@ -8,10 +8,15 @@
8
8
  "configureAiLanguage": "配置 AI 输出语言",
9
9
  "configureOutputStyle": "配置全局 AI 输出风格",
10
10
  "confirmClearCache": "确认清除所有 ZCF 偏好缓存?",
11
+ "customModelConfigured": "自定义模型配置完成",
12
+ "customModelOption": "自定义 - 指定自定义模型名称",
13
+ "customModelSkipped": "已跳过自定义模型配置",
11
14
  "currentLanguage": "当前语言",
12
15
  "currentModel": "当前模型",
13
16
  "defaultModelOption": "默认 - 让 Claude Code 自动选择",
14
17
  "defaultStyle": "默认风格",
18
+ "enterFastModel": "请输入后台任务的快速模型名称",
19
+ "enterPrimaryModel": "请输入主要使用的模型名称",
15
20
  "envImportSuccess": "环境变量已导入",
16
21
  "existingConfig": "检测到已有配置文件,如何处理?",
17
22
  "existingLanguageConfig": "检测到已有 AI 输出语言配置",
@@ -7,6 +7,8 @@
7
7
  "services.Playwright.name": "Playwright 浏览器控制",
8
8
  "services.context7.description": "查询最新的库文档和代码示例",
9
9
  "services.context7.name": "Context7 文档查询",
10
+ "services.open-websearch.description": "使用 DuckDuckGo、Bing 和 Brave 搜索引擎进行网页搜索",
11
+ "services.open-websearch.name": "open-websearch",
10
12
  "services.exa.apiKeyPrompt": "请输入 Exa API Key",
11
13
  "services.exa.description": "使用 Exa AI 进行网页搜索",
12
14
  "services.exa.name": "Exa AI 搜索",
@@ -9,7 +9,7 @@
9
9
  "menuDescriptions.configureApiOrCcr": "配置 API URL、认证信息或 CCR 代理",
10
10
  "menuDescriptions.configureEnvPermission": "导入隐私保护环境变量和系统权限配置",
11
11
  "menuDescriptions.configureMcp": "配置 MCP 服务(含 Windows 修复)",
12
- "menuDescriptions.configureModel": "设置默认模型(opus/sonnet",
12
+ "menuDescriptions.configureModel": "设置默认模型(opus/sonnet/opusplan/自定义)",
13
13
  "menuDescriptions.fullInit": "安装 Claude Code + 导入工作流 + 配置 API 或 CCR 代理 + 配置 MCP 服务",
14
14
  "menuDescriptions.importWorkflow": "仅导入/更新工作流相关文件",
15
15
  "menuOptions.ccrManagement": "CCR",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "autoUpdating": "正在自动更新 {tool}...",
2
3
  "cannotCheckVersion": "无法检查最新版本",
3
4
  "ccrNotInstalled": "CCR 未安装",
4
5
  "ccrUpToDate": "CCR 已是最新版本 (v{version})",
@@ -12,9 +13,12 @@
12
13
  "confirmUpdate": "将 {tool} 更新到最新版本?",
13
14
  "currentVersion": "当前版本: v{version}",
14
15
  "errorCheckingUpdates": "检查更新时出错:",
16
+ "failed": "失败",
15
17
  "latestVersion": "最新版本: v{version}",
18
+ "success": "成功",
16
19
  "updateFailed": "{tool} 更新失败",
17
20
  "updateSkipped": "跳过更新",
18
21
  "updateSuccess": "{tool} 更新成功!",
22
+ "updateSummary": "更新摘要",
19
23
  "updating": "正在更新 {tool}..."
20
24
  }
package/dist/index.d.mts CHANGED
@@ -79,7 +79,18 @@ declare function backupExistingConfig(): string | null;
79
79
  declare function copyConfigFiles(onlyMd?: boolean): void;
80
80
  declare function configureApi(apiConfig: ApiConfig | null): ApiConfig | null;
81
81
  declare function mergeConfigs(sourceFile: string, targetFile: string): void;
82
- declare function updateDefaultModel(model: 'opus' | 'sonnet' | 'opusplan' | 'default'): void;
82
+ /**
83
+ * Update custom model configuration using environment variables
84
+ * @param primaryModel - Primary model name for general tasks
85
+ * @param fastModel - Fast model name for background tasks (optional)
86
+ */
87
+ declare function updateCustomModel(primaryModel?: string, fastModel?: string): void;
88
+ /**
89
+ * Update the default model configuration in settings.json
90
+ * @param model - The model type to set: opus, sonnet, opusplan, default, or custom
91
+ * Note: 'custom' model type is handled differently - it should use environment variables instead
92
+ */
93
+ declare function updateDefaultModel(model: 'opus' | 'sonnet' | 'opusplan' | 'default' | 'custom'): void;
83
94
  /**
84
95
  * Merge settings.json intelligently
85
96
  * Preserves user's environment variables and custom configurations
@@ -88,7 +99,7 @@ declare function mergeSettingsFile(templatePath: string, targetPath: string): vo
88
99
  /**
89
100
  * Get existing model configuration from settings.json
90
101
  */
91
- declare function getExistingModelConfig(): 'opus' | 'sonnet' | 'opusplan' | 'default' | null;
102
+ declare function getExistingModelConfig(): 'opus' | 'sonnet' | 'opusplan' | 'default' | 'custom' | null;
92
103
  /**
93
104
  * Get existing API configuration from settings.json
94
105
  */
@@ -127,12 +138,12 @@ declare function cleanupPermissions(templatePermissions: string[], userPermissio
127
138
  */
128
139
  declare function mergeAndCleanPermissions(templatePermissions: string[] | undefined, userPermissions: string[] | undefined): string[];
129
140
 
130
- declare function getPlatform(): "windows" | "macos" | "linux";
141
+ declare function getPlatform(): 'windows' | 'macos' | 'linux';
131
142
  declare function commandExists(command: string): Promise<boolean>;
132
143
 
133
144
  declare function importRecommendedEnv(): Promise<void>;
134
145
  declare function importRecommendedPermissions(): Promise<void>;
135
146
  declare function openSettingsJson(): Promise<void>;
136
147
 
137
- export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateDefaultModel, writeMcpConfig };
148
+ export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateCustomModel, updateDefaultModel, writeMcpConfig };
138
149
  export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, McpServerConfig, McpService, SupportedLang };
package/dist/index.d.ts CHANGED
@@ -79,7 +79,18 @@ declare function backupExistingConfig(): string | null;
79
79
  declare function copyConfigFiles(onlyMd?: boolean): void;
80
80
  declare function configureApi(apiConfig: ApiConfig | null): ApiConfig | null;
81
81
  declare function mergeConfigs(sourceFile: string, targetFile: string): void;
82
- declare function updateDefaultModel(model: 'opus' | 'sonnet' | 'opusplan' | 'default'): void;
82
+ /**
83
+ * Update custom model configuration using environment variables
84
+ * @param primaryModel - Primary model name for general tasks
85
+ * @param fastModel - Fast model name for background tasks (optional)
86
+ */
87
+ declare function updateCustomModel(primaryModel?: string, fastModel?: string): void;
88
+ /**
89
+ * Update the default model configuration in settings.json
90
+ * @param model - The model type to set: opus, sonnet, opusplan, default, or custom
91
+ * Note: 'custom' model type is handled differently - it should use environment variables instead
92
+ */
93
+ declare function updateDefaultModel(model: 'opus' | 'sonnet' | 'opusplan' | 'default' | 'custom'): void;
83
94
  /**
84
95
  * Merge settings.json intelligently
85
96
  * Preserves user's environment variables and custom configurations
@@ -88,7 +99,7 @@ declare function mergeSettingsFile(templatePath: string, targetPath: string): vo
88
99
  /**
89
100
  * Get existing model configuration from settings.json
90
101
  */
91
- declare function getExistingModelConfig(): 'opus' | 'sonnet' | 'opusplan' | 'default' | null;
102
+ declare function getExistingModelConfig(): 'opus' | 'sonnet' | 'opusplan' | 'default' | 'custom' | null;
92
103
  /**
93
104
  * Get existing API configuration from settings.json
94
105
  */
@@ -127,12 +138,12 @@ declare function cleanupPermissions(templatePermissions: string[], userPermissio
127
138
  */
128
139
  declare function mergeAndCleanPermissions(templatePermissions: string[] | undefined, userPermissions: string[] | undefined): string[];
129
140
 
130
- declare function getPlatform(): "windows" | "macos" | "linux";
141
+ declare function getPlatform(): 'windows' | 'macos' | 'linux';
131
142
  declare function commandExists(command: string): Promise<boolean>;
132
143
 
133
144
  declare function importRecommendedEnv(): Promise<void>;
134
145
  declare function importRecommendedPermissions(): Promise<void>;
135
146
  declare function openSettingsJson(): Promise<void>;
136
147
 
137
- export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateDefaultModel, writeMcpConfig };
148
+ export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateCustomModel, updateDefaultModel, writeMcpConfig };
138
149
  export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, McpServerConfig, McpService, SupportedLang };
package/dist/index.mjs CHANGED
@@ -1,17 +1,17 @@
1
- export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, j as LANG_LABELS, L as LEGACY_ZCF_CONFIG_FILE, S as SETTINGS_FILE, h as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE, I as addCompletedOnboarding, w as applyAiLanguageDirective, n as backupExistingConfig, E as backupMcpConfig, G as buildMcpServerConfig, c as cleanupPermissions, a as commandExists, q as configureApi, p as copyConfigFiles, l as ensureClaudeDir, H as fixWindowsMcpConfig, k as getAiOutputLanguageLabel, v as getExistingApiConfig, t as getExistingModelConfig, z as getMcpConfigPath, g as getPlatform, b as importRecommendedEnv, d as importRecommendedPermissions, i as init, y as installClaudeCode, x as isClaudeCodeInstalled, m as mergeAndCleanPermissions, r as mergeConfigs, F as mergeMcpServers, s as mergeSettingsFile, o as openSettingsJson, B as readMcpConfig, u as updateDefaultModel, D as writeMcpConfig } from './chunks/simple-config.mjs';
1
+ export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, j as LANG_LABELS, L as LEGACY_ZCF_CONFIG_FILE, S as SETTINGS_FILE, h as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE, J as addCompletedOnboarding, x as applyAiLanguageDirective, n as backupExistingConfig, F as backupMcpConfig, H as buildMcpServerConfig, c as cleanupPermissions, a as commandExists, q as configureApi, p as copyConfigFiles, l as ensureClaudeDir, I as fixWindowsMcpConfig, k as getAiOutputLanguageLabel, w as getExistingApiConfig, v as getExistingModelConfig, B as getMcpConfigPath, g as getPlatform, b as importRecommendedEnv, d as importRecommendedPermissions, i as init, z as installClaudeCode, y as isClaudeCodeInstalled, m as mergeAndCleanPermissions, r as mergeConfigs, G as mergeMcpServers, t as mergeSettingsFile, o as openSettingsJson, D as readMcpConfig, u as updateCustomModel, s as updateDefaultModel, E as writeMcpConfig } from './chunks/simple-config.mjs';
2
2
  import 'node:fs';
3
3
  import 'node:process';
4
4
  import 'ansis';
5
5
  import 'inquirer';
6
- import 'node:url';
7
- import 'i18next';
8
- import 'i18next-fs-backend';
9
- import 'pathe';
10
6
  import 'node:child_process';
11
7
  import 'node:os';
12
8
  import 'node:util';
13
9
  import 'dayjs';
10
+ import 'pathe';
11
+ import 'node:url';
14
12
  import 'ora';
15
13
  import 'semver';
16
14
  import 'tinyexec';
17
15
  import 'node:fs/promises';
16
+ import 'i18next';
17
+ import 'i18next-fs-backend';
package/package.json CHANGED
@@ -1,14 +1,20 @@
1
1
  {
2
2
  "name": "zcf",
3
3
  "type": "module",
4
- "version": "2.12.7",
4
+ "version": "2.12.9",
5
5
  "description": "Zero-Config Claude-Code Flow - One-click configuration tool for Claude Code",
6
+ "author": {
7
+ "name": "Miao Da",
8
+ "email": "ufo025174@gmail.com",
9
+ "url": "https://github.com/WitMiao"
10
+ },
6
11
  "license": "MIT",
7
12
  "homepage": "https://github.com/UfoMiao/zcf",
8
13
  "repository": {
9
14
  "type": "git",
10
15
  "url": "git+https://github.com/UfoMiao/zcf.git"
11
16
  },
17
+ "bugs": "https://github.com/UfoMiao/zcf/issues",
12
18
  "keywords": [
13
19
  "claude",
14
20
  "claude-code",
@@ -35,13 +41,13 @@
35
41
  ],
36
42
  "dependencies": {
37
43
  "@types/semver": "^7.7.0",
38
- "ansis": "^3.17.0",
44
+ "ansis": "^4.1.0",
39
45
  "cac": "^6.7.14",
40
- "dayjs": "^1.11.13",
46
+ "dayjs": "^1.11.18",
41
47
  "find-up-simple": "^1.0.1",
42
48
  "i18next": "^25.4.2",
43
49
  "i18next-fs-backend": "^2.6.0",
44
- "inquirer": "^12.9.0",
50
+ "inquirer": "^12.9.4",
45
51
  "ora": "^8.2.0",
46
52
  "pathe": "^2.0.3",
47
53
  "semver": "^7.7.2",
@@ -49,19 +55,29 @@
49
55
  },
50
56
  "devDependencies": {
51
57
  "@antfu/eslint-config": "^5.2.1",
52
- "@changesets/cli": "^2.29.5",
53
- "@types/inquirer": "^9.0.8",
54
- "@types/node": "^22.17.0",
58
+ "@changesets/cli": "^2.29.6",
59
+ "@commitlint/cli": "^19.8.1",
60
+ "@commitlint/config-conventional": "^19.8.1",
61
+ "@commitlint/types": "^19.8.1",
62
+ "@types/inquirer": "^9.0.9",
63
+ "@types/node": "^22.18.0",
55
64
  "@vitest/coverage-v8": "^3.2.4",
56
65
  "@vitest/ui": "^3.2.4",
57
- "eslint": "^9.33.0",
66
+ "eslint": "^9.34.0",
58
67
  "eslint-plugin-format": "^1.0.1",
59
68
  "glob": "^11.0.3",
60
- "tsx": "^4.20.3",
69
+ "husky": "^9.1.7",
70
+ "lint-staged": "^16.1.6",
71
+ "tsx": "^4.20.5",
61
72
  "typescript": "^5.9.2",
62
- "unbuild": "^3.6.0",
73
+ "unbuild": "^3.6.1",
63
74
  "vitest": "^3.2.4"
64
75
  },
76
+ "lint-staged": {
77
+ "*": [
78
+ "pnpm lint"
79
+ ]
80
+ },
65
81
  "scripts": {
66
82
  "dev": "tsx ./src/cli.ts",
67
83
  "build": "unbuild",
@@ -76,6 +92,9 @@
76
92
  "test:watch": "vitest watch",
77
93
  "changeset": "changeset",
78
94
  "version": "changeset version",
79
- "release": "pnpm build && changeset publish"
95
+ "update:deps": "pnpx taze major -r -w",
96
+ "release": "pnpm build && changeset publish",
97
+ "commitlint": "commitlint",
98
+ "commitlint:check": "commitlint --from HEAD~1 --to HEAD --verbose"
80
99
  }
81
100
  }
@@ -22,6 +22,7 @@
22
22
  "TodoWrite",
23
23
  "NotebookRead",
24
24
  "NotebookEdit",
25
+ "mcp__ide",
25
26
  "mcp__exa",
26
27
  "mcp__context7",
27
28
  "mcp__mcp-deepwiki",