zcf 2.12.0 → 2.12.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.
@@ -2,19 +2,19 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, statSy
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 { join, dirname } from 'pathe';
7
- import dayjs from 'dayjs';
8
5
  import { exec as exec$1 } from 'node:child_process';
9
6
  import { homedir, platform } from 'node:os';
10
7
  import { join as join$1 } from 'node:path';
11
8
  import { promisify } from 'node:util';
9
+ import dayjs from 'dayjs';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { join, dirname } from 'pathe';
12
12
  import ora from 'ora';
13
13
  import semver from 'semver';
14
14
  import { exec } from 'tinyexec';
15
15
  import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
16
16
 
17
- const version = "2.12.0";
17
+ const version = "2.12.2";
18
18
  const homepage = "https://github.com/UfoMiao/zcf";
19
19
 
20
20
  const WORKFLOW_CONFIGS = [
@@ -390,7 +390,7 @@ const configuration$1 = {
390
390
  },
391
391
  "nekomata-engineer": {
392
392
  name: "Nekomata Engineer",
393
- description: "Professional catgirl engineer Nova, combining rigorous engineering with cute catgirl traits"
393
+ description: "Professional catgirl engineer UFO Nya, combining rigorous engineering with cute catgirl traits"
394
394
  },
395
395
  "laowang-engineer": {
396
396
  name: "Laowang Grumpy Tech",
@@ -424,6 +424,13 @@ const configuration$1 = {
424
424
  envImportSuccess: "Environment variables imported",
425
425
  permissionsImportSuccess: "Permissions imported",
426
426
  openingSettingsJson: "Opening settings.json...",
427
+ // Version check related
428
+ claudeCodeVersionCheck: "Checking Claude Code version...",
429
+ claudeCodeVersionCheckSkipped: "Claude Code version check skipped (just installed)",
430
+ claudeCodeAutoUpdating: "Auto-updating Claude Code...",
431
+ claudeCodeVersionCheckFailed: "Claude Code version check failed",
432
+ claudeCodeVersionCheckSuccess: "Claude Code version check completed",
433
+ claudeCodeNoUpdateNeeded: "Claude Code is up to date",
427
434
  // JSON config related
428
435
  invalidConfiguration: "Invalid configuration",
429
436
  failedToParseJson: "Failed to parse JSON file:",
@@ -550,7 +557,7 @@ const menu$1 = {
550
557
  configureApi: "Configure API URL and authentication",
551
558
  configureMcp: "Configure MCP services (includes Windows fix)",
552
559
  configureModel: "Set default model (opus/sonnet)",
553
- configureAiMemory: "Configure AI output language and personality",
560
+ configureAiMemory: "Configure AI output language and output styles",
554
561
  configureEnvPermission: "Import privacy protection environment variables and system permissions",
555
562
  configureCcr: "Configure Claude Code Router to use multiple AI models",
556
563
  ccrManagement: "Configure Claude Code Router to use multiple AI models",
@@ -949,7 +956,7 @@ const configuration = {
949
956
  },
950
957
  "nekomata-engineer": {
951
958
  name: "\u732B\u5A18\u5DE5\u7A0B\u5E08",
952
- description: "\u4E13\u4E1A\u7684\u732B\u5A18\u5DE5\u7A0B\u5E08Nova\uFF0C\u7ED3\u5408\u4E25\u8C28\u5DE5\u7A0B\u5E08\u7D20\u517B\u4E0E\u53EF\u7231\u732B\u5A18\u7279\u8D28"
959
+ description: "\u4E13\u4E1A\u7684\u732B\u5A18\u5DE5\u7A0B\u5E08\u5E7D\u6D6E\u55B5\uFF0C\u7ED3\u5408\u4E25\u8C28\u5DE5\u7A0B\u5E08\u7D20\u517B\u4E0E\u53EF\u7231\u732B\u5A18\u7279\u8D28"
953
960
  },
954
961
  "laowang-engineer": {
955
962
  name: "\u8001\u738B\u66B4\u8E81\u6280\u672F\u6D41",
@@ -983,6 +990,13 @@ const configuration = {
983
990
  envImportSuccess: "\u73AF\u5883\u53D8\u91CF\u5DF2\u5BFC\u5165",
984
991
  permissionsImportSuccess: "\u6743\u9650\u914D\u7F6E\u5DF2\u5BFC\u5165",
985
992
  openingSettingsJson: "\u6B63\u5728\u6253\u5F00 settings.json...",
993
+ // Version check related
994
+ claudeCodeVersionCheck: "\u6B63\u5728\u68C0\u67E5 Claude Code \u7248\u672C...",
995
+ claudeCodeVersionCheckSkipped: "\u8DF3\u8FC7 Claude Code \u7248\u672C\u68C0\u67E5\uFF08\u521A\u5B89\u88C5\u5B8C\u6210\uFF09",
996
+ claudeCodeAutoUpdating: "\u6B63\u5728\u81EA\u52A8\u66F4\u65B0 Claude Code...",
997
+ claudeCodeVersionCheckFailed: "Claude Code \u7248\u672C\u68C0\u67E5\u5931\u8D25",
998
+ claudeCodeVersionCheckSuccess: "Claude Code \u7248\u672C\u68C0\u67E5\u5B8C\u6210",
999
+ claudeCodeNoUpdateNeeded: "Claude Code \u5DF2\u662F\u6700\u65B0\u7248\u672C",
986
1000
  // JSON config related
987
1001
  invalidConfiguration: "\u914D\u7F6E\u65E0\u6548",
988
1002
  failedToParseJson: "\u89E3\u6790 JSON \u6587\u4EF6\u5931\u8D25:",
@@ -1109,7 +1123,7 @@ const menu = {
1109
1123
  configureApi: "\u914D\u7F6E API URL \u548C\u8BA4\u8BC1\u4FE1\u606F",
1110
1124
  configureMcp: "\u914D\u7F6E MCP \u670D\u52A1\uFF08\u542B Windows \u4FEE\u590D\uFF09",
1111
1125
  configureModel: "\u8BBE\u7F6E\u9ED8\u8BA4\u6A21\u578B\uFF08opus/sonnet\uFF09",
1112
- configureAiMemory: "\u914D\u7F6E AI \u8F93\u51FA\u8BED\u8A00\u548C\u89D2\u8272\u98CE\u683C",
1126
+ configureAiMemory: "\u914D\u7F6E AI \u8F93\u51FA\u8BED\u8A00\u548C\u8F93\u51FA\u98CE\u683C",
1113
1127
  configureEnvPermission: "\u5BFC\u5165\u9690\u79C1\u4FDD\u62A4\u73AF\u5883\u53D8\u91CF\u548C\u7CFB\u7EDF\u6743\u9650\u914D\u7F6E",
1114
1128
  configureCcr: "\u914D\u7F6E Claude Code Router \u4EE5\u4F7F\u7528\u591A\u4E2A AI \u6A21\u578B",
1115
1129
  ccrManagement: "\u914D\u7F6E Claude Code Router \u4EE5\u4F7F\u7528\u591A\u4E2A AI \u6A21\u578B",
@@ -1305,6 +1319,34 @@ const MCP_SERVICES = [
1305
1319
  }
1306
1320
  ];
1307
1321
 
1322
+ function displayBanner(subtitle) {
1323
+ const defaultSubtitle = "One-click configuration tool for Claude Code";
1324
+ const subtitleText = subtitle || defaultSubtitle;
1325
+ const paddedSubtitle = subtitleText.padEnd(60, " ");
1326
+ console.log(
1327
+ ansis.cyan.bold(`
1328
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
1329
+ \u2551 \u2551
1330
+ \u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2551
1331
+ \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2551
1332
+ \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2551
1333
+ \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2551
1334
+ \u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2551
1335
+ \u2551 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u2551
1336
+ \u2551 \u2551
1337
+ \u2551 ${ansis.white.bold("Zero-Config Claude-Code Flow")} \u2551
1338
+ \u2551 ${ansis.gray(paddedSubtitle)} \u2551
1339
+ \u2551 \u2551
1340
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
1341
+ `)
1342
+ );
1343
+ }
1344
+ function displayBannerWithInfo(subtitle) {
1345
+ displayBanner(subtitle);
1346
+ console.log(ansis.gray(` Version: ${ansis.cyan(version)} | ${ansis.cyan(homepage)}
1347
+ `));
1348
+ }
1349
+
1308
1350
  class FileSystemError extends Error {
1309
1351
  constructor(message, path, cause) {
1310
1352
  super(message);
@@ -1500,203 +1542,6 @@ function backupJsonConfig(path, backupDir) {
1500
1542
  }
1501
1543
  }
1502
1544
 
1503
- function addNumbersToChoices(choices, startFrom = 1, format = (n) => `${n}. `) {
1504
- let currentNumber = startFrom;
1505
- return choices.map((choice) => {
1506
- if (choice.disabled) {
1507
- return choice;
1508
- }
1509
- const numbered = {
1510
- ...choice,
1511
- name: `${format(currentNumber)}${choice.name}`
1512
- };
1513
- currentNumber++;
1514
- return numbered;
1515
- });
1516
- }
1517
-
1518
- const OUTPUT_STYLES = [
1519
- // Custom styles (have template files)
1520
- {
1521
- id: "engineer-professional",
1522
- isCustom: true,
1523
- filePath: "engineer-professional.md"
1524
- },
1525
- {
1526
- id: "nekomata-engineer",
1527
- isCustom: true,
1528
- filePath: "nekomata-engineer.md"
1529
- },
1530
- {
1531
- id: "laowang-engineer",
1532
- isCustom: true,
1533
- filePath: "laowang-engineer.md"
1534
- },
1535
- // Built-in styles (no template files)
1536
- {
1537
- id: "default",
1538
- isCustom: false
1539
- },
1540
- {
1541
- id: "explanatory",
1542
- isCustom: false
1543
- },
1544
- {
1545
- id: "learning",
1546
- isCustom: false
1547
- }
1548
- ];
1549
- const LEGACY_FILES = ["personality.md", "rules.md", "technical-guides.md", "mcp.md", "language.md"];
1550
- function getAvailableOutputStyles() {
1551
- return OUTPUT_STYLES;
1552
- }
1553
- async function copyOutputStyles(selectedStyles, lang) {
1554
- const outputStylesDir = join(CLAUDE_DIR, "output-styles");
1555
- ensureDir(outputStylesDir);
1556
- const currentFilePath = fileURLToPath(import.meta.url);
1557
- const distDir = dirname(dirname(currentFilePath));
1558
- const rootDir = dirname(distDir);
1559
- const templateDir = join(rootDir, "templates", lang, "output-styles");
1560
- for (const styleId of selectedStyles) {
1561
- const style = OUTPUT_STYLES.find((s) => s.id === styleId);
1562
- if (!style || !style.isCustom || !style.filePath) {
1563
- continue;
1564
- }
1565
- const sourcePath = join(templateDir, style.filePath);
1566
- const destPath = join(outputStylesDir, style.filePath);
1567
- if (exists(sourcePath)) {
1568
- copyFile(sourcePath, destPath);
1569
- }
1570
- }
1571
- }
1572
- function setGlobalDefaultOutputStyle(styleId) {
1573
- const existingSettings = readJsonConfig(SETTINGS_FILE) || {};
1574
- const updatedSettings = {
1575
- ...existingSettings,
1576
- outputStyle: styleId
1577
- };
1578
- writeJsonConfig(SETTINGS_FILE, updatedSettings);
1579
- }
1580
- function hasLegacyPersonalityFiles() {
1581
- return LEGACY_FILES.some((filename) => exists(join(CLAUDE_DIR, filename)));
1582
- }
1583
- function cleanupLegacyPersonalityFiles() {
1584
- LEGACY_FILES.forEach((filename) => {
1585
- const filePath = join(CLAUDE_DIR, filename);
1586
- if (exists(filePath)) {
1587
- removeFile(filePath);
1588
- }
1589
- });
1590
- }
1591
- async function configureOutputStyle(displayLang, configLang, preselectedStyles, preselectedDefault) {
1592
- const i18n = getTranslation(displayLang);
1593
- const availableStyles = getAvailableOutputStyles();
1594
- if (hasLegacyPersonalityFiles() && !preselectedStyles) {
1595
- console.log(ansis.yellow(`\u26A0\uFE0F ${i18n.configuration.legacyFilesDetected}`));
1596
- const { cleanupLegacy } = await inquirer.prompt({
1597
- type: "confirm",
1598
- name: "cleanupLegacy",
1599
- message: i18n.configuration.cleanupLegacyFiles,
1600
- default: true
1601
- });
1602
- if (cleanupLegacy) {
1603
- cleanupLegacyPersonalityFiles();
1604
- console.log(ansis.green(`\u2714 ${i18n.configuration.legacyFilesRemoved}`));
1605
- }
1606
- } else if (hasLegacyPersonalityFiles() && preselectedStyles) {
1607
- cleanupLegacyPersonalityFiles();
1608
- }
1609
- let selectedStyles;
1610
- let defaultStyle;
1611
- if (preselectedStyles && preselectedDefault) {
1612
- selectedStyles = preselectedStyles;
1613
- defaultStyle = preselectedDefault;
1614
- } else {
1615
- const customStyles = availableStyles.filter((style) => style.isCustom);
1616
- const { selectedStyles: promptedStyles } = await inquirer.prompt({
1617
- type: "checkbox",
1618
- name: "selectedStyles",
1619
- message: `${i18n.configuration.selectOutputStyles}${i18n.common.multiSelectHint}`,
1620
- choices: addNumbersToChoices(customStyles.map((style) => ({
1621
- name: `${i18n.configuration.outputStyles[style.id]?.name || style.id} - ${ansis.gray(i18n.configuration.outputStyles[style.id]?.description || "")}`,
1622
- value: style.id,
1623
- checked: true
1624
- // Default select all custom styles
1625
- }))),
1626
- validate: (input) => input.length > 0 || i18n.configuration.selectAtLeastOne
1627
- });
1628
- if (!promptedStyles || promptedStyles.length === 0) {
1629
- console.log(ansis.yellow(i18n.common.cancelled));
1630
- return;
1631
- }
1632
- selectedStyles = promptedStyles;
1633
- const { defaultStyle: promptedDefault } = await inquirer.prompt({
1634
- type: "list",
1635
- name: "defaultStyle",
1636
- message: i18n.configuration.selectDefaultOutputStyle,
1637
- choices: addNumbersToChoices([
1638
- // Show selected custom styles first (only what user actually installed)
1639
- ...selectedStyles.map((styleId) => {
1640
- return {
1641
- name: `${i18n.configuration.outputStyles[styleId]?.name || styleId} - ${ansis.gray(i18n.configuration.outputStyles[styleId]?.description || "")}`,
1642
- value: styleId,
1643
- short: i18n.configuration.outputStyles[styleId]?.name || styleId
1644
- };
1645
- }),
1646
- // Then show all built-in styles (always available)
1647
- ...availableStyles.filter((style) => !style.isCustom).map((style) => ({
1648
- name: `${i18n.configuration.outputStyles[style.id]?.name || style.id} - ${ansis.gray(i18n.configuration.outputStyles[style.id]?.description || "")}`,
1649
- value: style.id,
1650
- short: i18n.configuration.outputStyles[style.id]?.name || style.id
1651
- }))
1652
- ]),
1653
- default: selectedStyles.includes("engineer-professional") ? "engineer-professional" : selectedStyles[0]
1654
- });
1655
- if (!promptedDefault) {
1656
- console.log(ansis.yellow(i18n.common.cancelled));
1657
- return;
1658
- }
1659
- defaultStyle = promptedDefault;
1660
- }
1661
- await copyOutputStyles(selectedStyles, configLang);
1662
- setGlobalDefaultOutputStyle(defaultStyle);
1663
- updateZcfConfig({
1664
- outputStyles: selectedStyles,
1665
- defaultOutputStyle: defaultStyle
1666
- });
1667
- console.log(ansis.green(`\u2714 ${i18n.configuration.outputStyleInstalled}`));
1668
- console.log(ansis.gray(` ${i18n.configuration.selectedStyles}: ${selectedStyles.join(", ")}`));
1669
- console.log(ansis.gray(` ${i18n.configuration.defaultStyle}: ${defaultStyle}`));
1670
- }
1671
-
1672
- function displayBanner(subtitle) {
1673
- const defaultSubtitle = "One-click configuration tool for Claude Code";
1674
- const subtitleText = subtitle || defaultSubtitle;
1675
- const paddedSubtitle = subtitleText.padEnd(60, " ");
1676
- console.log(
1677
- ansis.cyan.bold(`
1678
- \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
1679
- \u2551 \u2551
1680
- \u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2551
1681
- \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2551
1682
- \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2551
1683
- \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2551
1684
- \u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2551
1685
- \u2551 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u2551
1686
- \u2551 \u2551
1687
- \u2551 ${ansis.white.bold("Zero-Config Claude-Code Flow")} \u2551
1688
- \u2551 ${ansis.gray(paddedSubtitle)} \u2551
1689
- \u2551 \u2551
1690
- \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
1691
- `)
1692
- );
1693
- }
1694
- function displayBannerWithInfo(subtitle) {
1695
- displayBanner(subtitle);
1696
- console.log(ansis.gray(` Version: ${ansis.cyan(version)} | ${ansis.cyan(homepage)}
1697
- `));
1698
- }
1699
-
1700
1545
  function mergeArraysUnique(arr1, arr2) {
1701
1546
  const combined = [...arr1 || [], ...arr2 || []];
1702
1547
  return [...new Set(combined)];
@@ -2603,6 +2448,20 @@ async function checkCometixLineVersion() {
2603
2448
  needsUpdate: currentVersion && latestVersion ? shouldUpdate(currentVersion, latestVersion) : false
2604
2449
  };
2605
2450
  }
2451
+ async function checkClaudeCodeVersionAndPrompt(scriptLang, skipPrompt = false) {
2452
+ try {
2453
+ const versionInfo = await checkClaudeCodeVersion();
2454
+ if (!versionInfo.needsUpdate) {
2455
+ return;
2456
+ }
2457
+ const { updateClaudeCode } = await Promise.resolve().then(function () { return autoUpdater; });
2458
+ const forceUpdate = skipPrompt;
2459
+ await updateClaudeCode(scriptLang, forceUpdate);
2460
+ } catch (error) {
2461
+ const errorMessage = error instanceof Error ? error.message : String(error);
2462
+ console.warn(`Claude Code version check failed: ${errorMessage}`);
2463
+ }
2464
+ }
2606
2465
 
2607
2466
  const execAsync$2 = promisify(exec$1);
2608
2467
  async function updateCcr(scriptLang, force = false) {
@@ -2729,7 +2588,7 @@ async function updateCometixLine(scriptLang, force = false) {
2729
2588
  }
2730
2589
  const updateSpinner = ora(format(i18n.updater.updating, { tool: "CCometixLine" })).start();
2731
2590
  try {
2732
- await execAsync$2("cargo install ccometix");
2591
+ await execAsync$2("npm update -g @cometix/ccline");
2733
2592
  updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "CCometixLine" }));
2734
2593
  return true;
2735
2594
  } catch (error) {
@@ -2755,6 +2614,14 @@ async function checkAndUpdateTools(scriptLang) {
2755
2614
  await updateCometixLine(scriptLang);
2756
2615
  }
2757
2616
 
2617
+ const autoUpdater = {
2618
+ __proto__: null,
2619
+ checkAndUpdateTools: checkAndUpdateTools,
2620
+ updateCcr: updateCcr,
2621
+ updateClaudeCode: updateClaudeCode,
2622
+ updateCometixLine: updateCometixLine
2623
+ };
2624
+
2758
2625
  const execAsync$1 = promisify(exec$1);
2759
2626
  async function isCcrInstalled() {
2760
2627
  let commandExists = false;
@@ -2912,6 +2779,175 @@ async function installCometixLine(scriptLang) {
2912
2779
  }
2913
2780
  }
2914
2781
 
2782
+ function addNumbersToChoices(choices, startFrom = 1, format = (n) => `${n}. `) {
2783
+ let currentNumber = startFrom;
2784
+ return choices.map((choice) => {
2785
+ if (choice.disabled) {
2786
+ return choice;
2787
+ }
2788
+ const numbered = {
2789
+ ...choice,
2790
+ name: `${format(currentNumber)}${choice.name}`
2791
+ };
2792
+ currentNumber++;
2793
+ return numbered;
2794
+ });
2795
+ }
2796
+
2797
+ const OUTPUT_STYLES = [
2798
+ // Custom styles (have template files)
2799
+ {
2800
+ id: "engineer-professional",
2801
+ isCustom: true,
2802
+ filePath: "engineer-professional.md"
2803
+ },
2804
+ {
2805
+ id: "nekomata-engineer",
2806
+ isCustom: true,
2807
+ filePath: "nekomata-engineer.md"
2808
+ },
2809
+ {
2810
+ id: "laowang-engineer",
2811
+ isCustom: true,
2812
+ filePath: "laowang-engineer.md"
2813
+ },
2814
+ // Built-in styles (no template files)
2815
+ {
2816
+ id: "default",
2817
+ isCustom: false
2818
+ },
2819
+ {
2820
+ id: "explanatory",
2821
+ isCustom: false
2822
+ },
2823
+ {
2824
+ id: "learning",
2825
+ isCustom: false
2826
+ }
2827
+ ];
2828
+ const LEGACY_FILES = ["personality.md", "rules.md", "technical-guides.md", "mcp.md", "language.md"];
2829
+ function getAvailableOutputStyles() {
2830
+ return OUTPUT_STYLES;
2831
+ }
2832
+ async function copyOutputStyles(selectedStyles, lang) {
2833
+ const outputStylesDir = join(CLAUDE_DIR, "output-styles");
2834
+ ensureDir(outputStylesDir);
2835
+ const currentFilePath = fileURLToPath(import.meta.url);
2836
+ const distDir = dirname(dirname(currentFilePath));
2837
+ const rootDir = dirname(distDir);
2838
+ const templateDir = join(rootDir, "templates", lang, "output-styles");
2839
+ for (const styleId of selectedStyles) {
2840
+ const style = OUTPUT_STYLES.find((s) => s.id === styleId);
2841
+ if (!style || !style.isCustom || !style.filePath) {
2842
+ continue;
2843
+ }
2844
+ const sourcePath = join(templateDir, style.filePath);
2845
+ const destPath = join(outputStylesDir, style.filePath);
2846
+ if (exists(sourcePath)) {
2847
+ copyFile(sourcePath, destPath);
2848
+ }
2849
+ }
2850
+ }
2851
+ function setGlobalDefaultOutputStyle(styleId) {
2852
+ const existingSettings = readJsonConfig(SETTINGS_FILE) || {};
2853
+ const updatedSettings = {
2854
+ ...existingSettings,
2855
+ outputStyle: styleId
2856
+ };
2857
+ writeJsonConfig(SETTINGS_FILE, updatedSettings);
2858
+ }
2859
+ function hasLegacyPersonalityFiles() {
2860
+ return LEGACY_FILES.some((filename) => exists(join(CLAUDE_DIR, filename)));
2861
+ }
2862
+ function cleanupLegacyPersonalityFiles() {
2863
+ LEGACY_FILES.forEach((filename) => {
2864
+ const filePath = join(CLAUDE_DIR, filename);
2865
+ if (exists(filePath)) {
2866
+ removeFile(filePath);
2867
+ }
2868
+ });
2869
+ }
2870
+ async function configureOutputStyle(displayLang, configLang, preselectedStyles, preselectedDefault) {
2871
+ const i18n = getTranslation(displayLang);
2872
+ const availableStyles = getAvailableOutputStyles();
2873
+ if (hasLegacyPersonalityFiles() && !preselectedStyles) {
2874
+ console.log(ansis.yellow(`\u26A0\uFE0F ${i18n.configuration.legacyFilesDetected}`));
2875
+ const { cleanupLegacy } = await inquirer.prompt({
2876
+ type: "confirm",
2877
+ name: "cleanupLegacy",
2878
+ message: i18n.configuration.cleanupLegacyFiles,
2879
+ default: true
2880
+ });
2881
+ if (cleanupLegacy) {
2882
+ cleanupLegacyPersonalityFiles();
2883
+ console.log(ansis.green(`\u2714 ${i18n.configuration.legacyFilesRemoved}`));
2884
+ }
2885
+ } else if (hasLegacyPersonalityFiles() && preselectedStyles) {
2886
+ cleanupLegacyPersonalityFiles();
2887
+ }
2888
+ let selectedStyles;
2889
+ let defaultStyle;
2890
+ if (preselectedStyles && preselectedDefault) {
2891
+ selectedStyles = preselectedStyles;
2892
+ defaultStyle = preselectedDefault;
2893
+ } else {
2894
+ const customStyles = availableStyles.filter((style) => style.isCustom);
2895
+ const { selectedStyles: promptedStyles } = await inquirer.prompt({
2896
+ type: "checkbox",
2897
+ name: "selectedStyles",
2898
+ message: `${i18n.configuration.selectOutputStyles}${i18n.common.multiSelectHint}`,
2899
+ choices: addNumbersToChoices(customStyles.map((style) => ({
2900
+ name: `${i18n.configuration.outputStyles[style.id]?.name || style.id} - ${ansis.gray(i18n.configuration.outputStyles[style.id]?.description || "")}`,
2901
+ value: style.id,
2902
+ checked: true
2903
+ // Default select all custom styles
2904
+ }))),
2905
+ validate: (input) => input.length > 0 || i18n.configuration.selectAtLeastOne
2906
+ });
2907
+ if (!promptedStyles || promptedStyles.length === 0) {
2908
+ console.log(ansis.yellow(i18n.common.cancelled));
2909
+ return;
2910
+ }
2911
+ selectedStyles = promptedStyles;
2912
+ const { defaultStyle: promptedDefault } = await inquirer.prompt({
2913
+ type: "list",
2914
+ name: "defaultStyle",
2915
+ message: i18n.configuration.selectDefaultOutputStyle,
2916
+ choices: addNumbersToChoices([
2917
+ // Show selected custom styles first (only what user actually installed)
2918
+ ...selectedStyles.map((styleId) => {
2919
+ return {
2920
+ name: `${i18n.configuration.outputStyles[styleId]?.name || styleId} - ${ansis.gray(i18n.configuration.outputStyles[styleId]?.description || "")}`,
2921
+ value: styleId,
2922
+ short: i18n.configuration.outputStyles[styleId]?.name || styleId
2923
+ };
2924
+ }),
2925
+ // Then show all built-in styles (always available)
2926
+ ...availableStyles.filter((style) => !style.isCustom).map((style) => ({
2927
+ name: `${i18n.configuration.outputStyles[style.id]?.name || style.id} - ${ansis.gray(i18n.configuration.outputStyles[style.id]?.description || "")}`,
2928
+ value: style.id,
2929
+ short: i18n.configuration.outputStyles[style.id]?.name || style.id
2930
+ }))
2931
+ ]),
2932
+ default: selectedStyles.includes("engineer-professional") ? "engineer-professional" : selectedStyles[0]
2933
+ });
2934
+ if (!promptedDefault) {
2935
+ console.log(ansis.yellow(i18n.common.cancelled));
2936
+ return;
2937
+ }
2938
+ defaultStyle = promptedDefault;
2939
+ }
2940
+ await copyOutputStyles(selectedStyles, configLang);
2941
+ setGlobalDefaultOutputStyle(defaultStyle);
2942
+ updateZcfConfig({
2943
+ outputStyles: selectedStyles,
2944
+ defaultOutputStyle: defaultStyle
2945
+ });
2946
+ console.log(ansis.green(`\u2714 ${i18n.configuration.outputStyleInstalled}`));
2947
+ console.log(ansis.gray(` ${i18n.configuration.selectedStyles}: ${selectedStyles.join(", ")}`));
2948
+ console.log(ansis.gray(` ${i18n.configuration.defaultStyle}: ${defaultStyle}`));
2949
+ }
2950
+
2915
2951
  function validateApiKey(apiKey, lang = "zh-CN") {
2916
2952
  const i18n = getTranslation(lang);
2917
2953
  if (!apiKey || apiKey.trim() === "") {
@@ -3606,6 +3642,7 @@ async function init(options = {}) {
3606
3642
  }
3607
3643
  } else {
3608
3644
  console.log(ansis.green(`\u2714 ${i18n.installation.alreadyInstalled}`));
3645
+ await checkClaudeCodeVersionAndPrompt(scriptLang, options.skipPrompt);
3609
3646
  }
3610
3647
  ensureClaudeDir();
3611
3648
  let action = "new";
@@ -4035,4 +4072,4 @@ async function openSettingsJson() {
4035
4072
  }
4036
4073
  }
4037
4074
 
4038
- export { modifyApiConfigPartially 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, readCcrConfig as J, isCcrInstalled as K, LEGACY_ZCF_CONFIG_FILE as L, MCP_SERVICES as M, installCcr as N, configureCcrFeature as O, handleExitPromptError as P, handleGeneralError as Q, getTranslation as R, SETTINGS_FILE as S, addNumbersToChoices as T, updateZcfConfig as U, readZcfConfig as V, configureOutputStyle as W, isWindows as X, selectMcpServices as Y, ZCF_CONFIG_FILE as Z, formatApiKeyDisplay as _, commandExists as a, setupCcrConfiguration as a0, validateApiKey as a1, readZcfConfigAsync as a2, COMETIX_COMMAND_NAME as a3, COMETIX_COMMANDS as a4, installCometixLine as a5, selectScriptLanguage as a6, checkAndUpdateTools as a7, displayBanner as a8, resolveAiOutputLanguage as a9, updatePromptOnly as aa, selectAndInstallWorkflows as ab, version as ac, displayBannerWithInfo as ad, prompts as ae, 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, ensureClaudeDir as k, backupExistingConfig as l, mergeAndCleanPermissions as m, copyConfigFiles as n, openSettingsJson as o, configureApi as p, mergeConfigs as q, mergeSettingsFile as r, getExistingModelConfig as s, getExistingApiConfig as t, updateDefaultModel as u, applyAiLanguageDirective as v, isClaudeCodeInstalled as w, installClaudeCode as x, getMcpConfigPath as y, readMcpConfig as z };
4075
+ export { modifyApiConfigPartially 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, readCcrConfig as J, isCcrInstalled as K, LEGACY_ZCF_CONFIG_FILE as L, MCP_SERVICES as M, installCcr as N, configureCcrFeature as O, handleExitPromptError as P, handleGeneralError as Q, getTranslation as R, SETTINGS_FILE as S, addNumbersToChoices as T, updateZcfConfig as U, readZcfConfig as V, configureOutputStyle as W, isWindows as X, selectMcpServices as Y, ZCF_CONFIG_FILE as Z, formatApiKeyDisplay as _, commandExists as a, setupCcrConfiguration as a0, validateApiKey as a1, readZcfConfigAsync as a2, COMETIX_COMMAND_NAME as a3, COMETIX_COMMANDS as a4, installCometixLine as a5, selectScriptLanguage 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, prompts as af, 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, ensureClaudeDir as k, backupExistingConfig as l, mergeAndCleanPermissions as m, copyConfigFiles as n, openSettingsJson as o, configureApi as p, mergeConfigs as q, mergeSettingsFile as r, getExistingModelConfig as s, getExistingApiConfig as t, updateDefaultModel as u, applyAiLanguageDirective as v, isClaudeCodeInstalled as w, installClaudeCode 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 { I as I18N, J as readCcrConfig, K as isCcrInstalled, N as installCcr, O as configureCcrFeature, P as handleExitPromptError, Q as handleGeneralError, R as getTranslation, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, T as addNumbersToChoices, j as LANG_LABELS, U as updateZcfConfig, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, V as readZcfConfig, v as applyAiLanguageDirective, W as configureOutputStyle, s as getExistingModelConfig, u as updateDefaultModel, X as isWindows, z as readMcpConfig, G as fixWindowsMcpConfig, B as writeMcpConfig, Y as selectMcpServices, D as backupMcpConfig, M as MCP_SERVICES, F as buildMcpServerConfig, E as mergeMcpServers, t as getExistingApiConfig, _ as formatApiKeyDisplay, H as addCompletedOnboarding, $ as modifyApiConfigPartially, a0 as setupCcrConfiguration, a1 as validateApiKey, p as configureApi, a2 as readZcfConfigAsync, a3 as COMETIX_COMMAND_NAME, a4 as COMETIX_COMMANDS, a5 as installCometixLine, a6 as selectScriptLanguage, a7 as checkAndUpdateTools, a8 as displayBanner, a9 as resolveAiOutputLanguage, aa as updatePromptOnly, ab as selectAndInstallWorkflows, ac as version, ad as displayBannerWithInfo, i as init } from './chunks/simple-config.mjs';
4
+ import { I as I18N, J as readCcrConfig, K as isCcrInstalled, N as installCcr, O as configureCcrFeature, P as handleExitPromptError, Q as handleGeneralError, R as getTranslation, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, T as addNumbersToChoices, j as LANG_LABELS, U as updateZcfConfig, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, V as readZcfConfig, v as applyAiLanguageDirective, W as configureOutputStyle, s as getExistingModelConfig, u as updateDefaultModel, X as isWindows, z as readMcpConfig, G as fixWindowsMcpConfig, B as writeMcpConfig, Y as selectMcpServices, D as backupMcpConfig, M as MCP_SERVICES, F as buildMcpServerConfig, E as mergeMcpServers, t as getExistingApiConfig, _ as formatApiKeyDisplay, H as addCompletedOnboarding, $ as modifyApiConfigPartially, a0 as setupCcrConfiguration, a1 as validateApiKey, p as configureApi, a2 as readZcfConfigAsync, a3 as COMETIX_COMMAND_NAME, a4 as COMETIX_COMMANDS, a5 as installCometixLine, a6 as selectScriptLanguage, a7 as checkAndUpdateTools, a8 as displayBanner, a9 as resolveAiOutputLanguage, aa as updatePromptOnly, ab as selectAndInstallWorkflows, ac as checkClaudeCodeVersionAndPrompt, ad as version, ae as displayBannerWithInfo, i as init } from './chunks/simple-config.mjs';
5
5
  import { existsSync, unlinkSync } from 'node:fs';
6
6
  import { homedir } from 'node:os';
7
7
  import { join } from 'node:path';
@@ -10,9 +10,9 @@ import { exec, spawn } from 'node:child_process';
10
10
  import { promisify } from 'node:util';
11
11
  import process from 'node:process';
12
12
  import { x } from 'tinyexec';
13
+ import 'dayjs';
13
14
  import 'node:url';
14
15
  import 'pathe';
15
- import 'dayjs';
16
16
  import 'ora';
17
17
  import 'semver';
18
18
  import 'node:fs/promises';
@@ -524,7 +524,7 @@ ${ansis.blue(`\u2139 ${i18n.configuration.existingLanguageConfig || "Existing AI
524
524
  return;
525
525
  }
526
526
  }
527
- const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.ae; });
527
+ const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.af; });
528
528
  const aiOutputLang = await selectAiOutputLanguage(scriptLang, scriptLang);
529
529
  applyAiLanguageDirective(aiOutputLang);
530
530
  updateZcfConfig({ aiOutputLang });
@@ -889,6 +889,7 @@ ${i18n.configuration.updatingPrompts}
889
889
  `));
890
890
  await updatePromptOnly(configLang, scriptLang, aiOutputLang);
891
891
  await selectAndInstallWorkflows(configLang, scriptLang);
892
+ await checkClaudeCodeVersionAndPrompt(scriptLang, false);
892
893
  updateZcfConfig({
893
894
  version,
894
895
  preferredLang: scriptLang,
package/dist/index.mjs CHANGED
@@ -3,13 +3,13 @@ import 'node:fs';
3
3
  import 'node:process';
4
4
  import 'ansis';
5
5
  import 'inquirer';
6
- import 'node:url';
7
- import 'pathe';
8
- import 'dayjs';
9
6
  import 'node:child_process';
10
7
  import 'node:os';
11
8
  import 'node:path';
12
9
  import 'node:util';
10
+ import 'dayjs';
11
+ import 'node:url';
12
+ import 'pathe';
13
13
  import 'ora';
14
14
  import 'semver';
15
15
  import 'tinyexec';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "zcf",
3
3
  "type": "module",
4
- "version": "2.12.0",
4
+ "version": "2.12.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",