@byh3071/vhk 0.7.0 → 0.8.0

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/dist/index.js CHANGED
@@ -2,10 +2,15 @@
2
2
  import {
3
3
  __commonJS,
4
4
  __toESM,
5
+ env,
6
+ envCheck,
7
+ ko,
8
+ printNextStep,
5
9
  safeExecFile,
6
10
  safeExecFileStream,
7
- startMcpServer
8
- } from "./chunk-NJDRNI3S.js";
11
+ startMcpServer,
12
+ t
13
+ } from "./chunk-NQ4V3VN4.js";
9
14
 
10
15
  // node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js
11
16
  var require_ignore = __commonJS({
@@ -467,7 +472,7 @@ var require_ignore = __commonJS({
467
472
 
468
473
  // src/index.ts
469
474
  import { Command, Help } from "commander";
470
- import inquirer10 from "inquirer";
475
+ import inquirer12 from "inquirer";
471
476
 
472
477
  // src/lib/nlp-router.ts
473
478
  function normalize(input) {
@@ -511,6 +516,30 @@ var RULES = [
511
516
  confidence: "high",
512
517
  test: (t2) => /mcp.*(설정|연동|초기|init)|커서.*(연동|설정|mcp)|cursor.*mcp/.test(t2)
513
518
  },
519
+ {
520
+ command: "design-palette",
521
+ explanation: "\uCEEC\uB7EC \uD314\uB808\uD2B8 \uC120\uD0DD (vhk design-palette)",
522
+ confidence: "high",
523
+ test: (t2) => /팔레트|palette|컬러\s*(고|선택|바꿔|변경)|색상\s*(고|선택|변경)|색깔\s*선택/.test(t2)
524
+ },
525
+ {
526
+ command: "design",
527
+ explanation: "\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131 (vhk design)",
528
+ confidence: "high",
529
+ test: (t2) => /디자인\s*(토큰|시스템|만들|생성|셋업|설정)|design\s*(token|system|setup)|토큰\s*만들|css\s*변수.*만들|tailwind\s*(컬러|설정)/.test(t2)
530
+ },
531
+ {
532
+ command: "theme",
533
+ explanation: "\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uD14C\uB9C8 \uC801\uC6A9 (vhk theme)",
534
+ confidence: "high",
535
+ test: (t2) => /테마(?!\s*(파일|이름))|theme|다크\s*모드|라이트\s*모드|dark\s*mode|light\s*mode|색상\s*모드|모드\s*전환/.test(t2)
536
+ },
537
+ {
538
+ command: "ref",
539
+ explanation: "\uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D (vhk ref list)",
540
+ confidence: "high",
541
+ test: (t2) => /^레퍼런스$|^ref$|레퍼런스.*(보|목록|확인|있|뭐)|참고\s*(사이트|목록|링크)|reference.*list/.test(t2) && !/(add|추가|open|열|https?:\/\/)/.test(t2)
542
+ },
514
543
  {
515
544
  command: "secure",
516
545
  explanation: "\uBCF4\uC548 \uC2A4\uCE94 (vhk \uBCF4\uC548)",
@@ -669,6 +698,14 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
669
698
  "publish",
670
699
  "\uCD9C\uC2DC",
671
700
  "\uCD9C\uD558",
701
+ "design",
702
+ "\uB514\uC790\uC778",
703
+ "design-palette",
704
+ "\uD314\uB808\uD2B8",
705
+ "theme",
706
+ "\uD14C\uB9C8",
707
+ "ref",
708
+ "\uB808\uD37C\uB7F0\uC2A4",
672
709
  "help"
673
710
  ]);
674
711
  function isOptionToken(token) {
@@ -692,330 +729,12 @@ function detectNaturalLanguageInput(argv) {
692
729
  }
693
730
 
694
731
  // src/lib/nlp-run.ts
695
- import chalk20 from "chalk";
696
- import inquirer9 from "inquirer";
697
-
698
- // src/i18n/ko.ts
699
- var ko = {
700
- status: {
701
- title: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC",
702
- notGitRepo: "Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2C8\uC5D0\uC694. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
703
- branch: "\uBE0C\uB79C\uCE58:",
704
- changes: "\uBCC0\uACBD:",
705
- recentCommits: "\uCD5C\uADFC \uCEE4\uBC0B (3):",
706
- noCommits: "\uCEE4\uBC0B \uC5C6\uC74C",
707
- remote: "\uC6D0\uACA9:",
708
- noUpstream: "upstream \uC5C6\uC74C",
709
- inSync: "\uB3D9\uAE30\uD654\uB428",
710
- ahead: (n) => `\u2191${n} ahead`,
711
- behind: (n) => `\u2193${n} behind`,
712
- package: "package.json:",
713
- noPackage: "package.json \uC5C6\uC74C",
714
- detached: "(detached HEAD)",
715
- unknownBranch: "(\uC54C \uC218 \uC5C6\uC74C)"
716
- },
717
- save: {
718
- title: "\uC800\uC7A5\uD558\uAE30",
719
- notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
720
- noChanges: "\uC800\uC7A5\uD560 \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
721
- filesHeader: (n) => `\uBCC0\uACBD\uB41C \uD30C\uC77C (${n}\uAC1C):`,
722
- commitMessage: "\uCEE4\uBC0B \uBA54\uC2DC\uC9C0 (Enter\uB85C \uAE30\uBCF8\uAC12 \uC0AC\uC6A9):",
723
- saving: "\uC800\uC7A5 \uC911...",
724
- pushing: "\uC6D0\uACA9 \uC800\uC7A5\uC18C\uC5D0 \uC62C\uB9AC\uB294 \uC911...",
725
- successWithPush: "\uC800\uC7A5 + \uC6D0\uACA9 \uC5C5\uB85C\uB4DC \uC644\uB8CC!",
726
- successLocal: "\uB85C\uCEEC \uC800\uC7A5 \uC644\uB8CC!",
727
- noRemote: "\uC6D0\uACA9 \uC800\uC7A5\uC18C\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC544 push\uB97C \uAC74\uB108\uB6F0\uC5C8\uC2B5\uB2C8\uB2E4.",
728
- failed: "\uC800\uC7A5 \uC2E4\uD328",
729
- stagedAfterFail: "\uCEE4\uBC0B\uC740 \uC2E4\uD328\uD588\uC9C0\uB9CC \uD30C\uC77C\uC740 \uC2A4\uD14C\uC774\uC9D5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uD655\uC778: git status / \uCDE8\uC18C: git reset HEAD",
730
- securityWarnHeader: "\uC800\uC7A5 \uC804 \uBCF4\uC548 \uD655\uC778:",
731
- secretsFound: (n) => `\uCF54\uB4DC\uC5D0\uC11C CRITICAL/HIGH \uC2DC\uD06C\uB9BF \uD328\uD134 ${n}\uAC74 \uAC10\uC9C0`,
732
- secretsConfirm: "\uADF8\uB798\uB3C4 \uCEE4\uBC0B\xB7push\uB97C \uC9C4\uD589\uD560\uAE4C\uC694?",
733
- cancelled: "\uC800\uC7A5\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4.",
734
- pushFailed: "push \uC2E4\uD328 (\uB85C\uCEEC \uCEE4\uBC0B\uC740 \uC644\uB8CC\uB428)",
735
- commitOkPushFailed: "\uB85C\uCEEC \uCEE4\uBC0B\uC740 \uB410\uC9C0\uB9CC \uC6D0\uACA9 push\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. git push\uB97C \uC9C1\uC811 \uD655\uC778\uD558\uC138\uC694.",
736
- done: (n) => `${n}\uAC1C \uD30C\uC77C \uC800\uC7A5 \uC644\uB8CC!`,
737
- doneLocalOnly: (n) => `${n}\uAC1C \uD30C\uC77C \uB85C\uCEEC \uC800\uC7A5\uB428 (push\uB294 \uC2E4\uD328)`
738
- },
739
- undo: {
740
- title: "\uB418\uB3CC\uB9AC\uAE30",
741
- notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
742
- noCommits: "\uB418\uB3CC\uB9B4 \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
743
- recentHeader: "\u{1F4CB} \uCD5C\uADFC \uCEE4\uBC0B:",
744
- howMany: "\uBA87 \uAC1C\uC758 \uCEE4\uBC0B\uC744 \uB418\uB3CC\uB9B4\uAE4C\uC694?",
745
- alreadyPushed: "\uC774 \uCEE4\uBC0B\uC740 \uC774\uBBF8 \uC6D0\uACA9\uC5D0 \uC62C\uB77C\uAC14\uC2B5\uB2C8\uB2E4. \uB418\uB3CC\uB9AC\uBA74 \uCDA9\uB3CC\uC774 \uC0DD\uAE38 \uC218 \uC788\uC5B4\uC694.",
746
- noUpstreamWarning: "upstream \uBE0C\uB79C\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774\uBBF8 push\uD55C \uCEE4\uBC0B\uC77C \uC218 \uC788\uC5B4\uC694. \uB418\uB3CC\uB9B0 \uB4A4 force push\uAC00 \uD544\uC694\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
747
- confirmMessage: "\uCD5C\uADFC \uCEE4\uBC0B\uC744 \uB418\uB3CC\uB9AC\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
748
- confirmRisky: (n) => `\u26A0\uFE0F \uC704\uD5D8: \uCD5C\uADFC ${n}\uAC1C \uCEE4\uBC0B\uC744 soft reset\uD569\uB2C8\uB2E4. \uC6D0\uACA9\uACFC \uC5B4\uAE0B\uB0A0 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD560\uAE4C\uC694?`,
749
- cancelled: "\uCDE8\uC18C\uB428",
750
- success: "\uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC! \uBCC0\uACBD\uC0AC\uD56D\uC740 \uADF8\uB300\uB85C \uB0A8\uC544\uC788\uC2B5\uB2C8\uB2E4.",
751
- stagedHint: "\uBCC0\uACBD\uC0AC\uD56D\uC740 \uC2A4\uD14C\uC774\uC9D5 \uC601\uC5ED\uC5D0 \uB0A8\uC544 \uC788\uC5B4\uC694.",
752
- rootCommit: "\uCCAB \uCEE4\uBC0B\uB9CC \uC788\uC5B4\uC11C \uB354 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
753
- forcePushHint: "\uC6D0\uACA9\uACFC \uB9DE\uCD94\uB824\uBA74: git push --force-with-lease (\uD63C\uC790 \uC791\uC5C5\uD55C \uBE0C\uB79C\uCE58\uC5D0\uC11C\uB9CC, \uD300\uACFC \uD569\uC758 \uD6C4)",
754
- failed: "\uB418\uB3CC\uB9AC\uAE30 \uC2E4\uD328"
755
- },
756
- diff: {
757
- title: "\uBCC0\uACBD\uC0AC\uD56D \uD655\uC778",
758
- notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
759
- noChanges: "\uBCC0\uACBD\uC0AC\uD56D \uC5C6\uC74C! \uAE68\uB057\uD569\uB2C8\uB2E4.",
760
- stagedHeader: "\u{1F4E6} \uCEE4\uBC0B \uB300\uAE30 (staged):",
761
- unstagedHeader: "\u270F\uFE0F \uC218\uC815\uB428 (unstaged):",
762
- untrackedHeader: (n) => `\u2795 \uC0C8 \uD30C\uC77C (${n}\uAC1C):`,
763
- summaryHeader: "\u{1F4CA} \uCD1D \uBCC0\uACBD \uC694\uC57D (\uC791\uC5C5 \uD2B8\uB9AC vs HEAD)",
764
- filesLine: (n) => `\uD30C\uC77C: ${n}\uAC1C`
765
- },
766
- start: {
767
- title: "\u{1F527} VHK \u2014 \uBB34\uC5C7\uC744 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
768
- subtitle: "\uBC88\uD638\uB9CC \uACE0\uB974\uBA74 \uB429\uB2C8\uB2E4. \uBA85\uB839\uC5B4\uB97C \uC678\uC6B8 \uD544\uC694 \uC5C6\uC5B4\uC694.",
769
- menuPrompt: "\uC5B4\uB5A4 \uC791\uC5C5\uC744 \uD560\uAE4C\uC694?",
770
- choiceGate: "1) \uC0C8 \uC544\uC774\uB514\uC5B4 \uAC80\uC99D\uD558\uAE30",
771
- choiceInit: "2) \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30 \u2014 \uD3F4\uB354\xB7\uD30C\uC77C \uB9CC\uB4E4\uAE30",
772
- choiceInitSkipGate: "3) \uAE30\uD68D\uC740 \uB05D\uB0AC\uC5B4\uC694 \u2014 \uBC14\uB85C \uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uAE30",
773
- choiceRecap: "4) \uC624\uB298 \uD55C \uC77C \uC815\uB9AC\uD558\uAE30",
774
- choiceSync: "5) \uADDC\uCE59 \uD30C\uC77C \uB9DE\uCD94\uAE30",
775
- choiceCheck: "6) \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59 \uC810\uAC80\uD558\uAE30",
776
- choiceSecure: "7) \uBE44\uBC00\uBC88\uD638\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC\uD558\uAE30",
777
- choiceExit: "\uB098\uAC00\uAE30",
778
- goodbye: "\uB2E4\uC74C\uC5D0 \uB610 \uBD88\uB7EC\uC8FC\uC138\uC694."
779
- },
780
- gate: {
781
- title: "\u{1F4A1} \uC544\uC774\uB514\uC5B4 \uAC80\uC99D",
782
- welcome: "\uC0C8 \uC544\uC774\uB514\uC5B4\uB97C \uAC80\uC99D\uD569\uB2C8\uB2E4. \uC9C8\uBB38\uC5D0 \uB2F5\uD574\uC8FC\uC138\uC694.",
783
- modePrompt: "\uC5B4\uB5BB\uAC8C \uAC80\uC99D\uD560\uAE4C\uC694?",
784
- modeQuickLabel: "\u26A1 \uC9E7\uAC8C (\uD575\uC2EC 5\uBB38\uD56D) \u2014 \uB9C9 \uB5A0\uC62C\uB790\uC744 \uB54C",
785
- modeFullLabel: "\u{1F50D} \uC790\uC138\uD788 (13\uBB38\uD56D) \u2014 \uAE30\uD68D\uC774 \uC5B4\uB290 \uC815\uB3C4 \uC7A1\uD614\uC744 \uB54C",
786
- modeSkipLabel: "\u23ED\uFE0F \uAC74\uB108\uB6F0\uAE30 \u2014 \uB178\uC158\xB7\uBB38\uC11C\uC5D0 \uC774\uBBF8 \uAE30\uD68D\uD574 \uB460",
787
- skipSourcePrompt: "\u{1F4C4} \uAE30\uD68D \uBB38\uC11C \uC704\uCE58 (\uB178\uC158 \uC8FC\uC18C, \uD30C\uC77C \uACBD\uB85C \uB4F1):",
788
- skipGo: "\u2705 \uC2DC\uC791\uD574\uB3C4 \uB3FC\uC694! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694 (vhk init)",
789
- skipSourceLabel: (source) => `\uAE30\uD68D \uBB38\uC11C: ${source}`,
790
- quickHeader: "\u26A1 \uC9E7\uC740 \uAC80\uC99D",
791
- fullHeader: "\u{1F50D} \uC790\uC138\uD55C \uAC80\uC99D",
792
- modeCountSuffix: (total) => `\u2014 ${total}\uBB38\uD56D`,
793
- idea: "\u{1F4A1} \uC5B4\uB5A4 \uAC78 \uB9CC\uB4E4 \uAC74\uAC00\uC694? (\uD55C \uC904)",
794
- ideaHint: '\uC608: "\uD300 \uD560 \uC77C\uC744 3\uCD08\uC5D0 \uCD94\uAC00\uD558\uB294 \uC571"',
795
- painPoint: "\u{1F624} \uC774 \uBB38\uC81C, \uB204\uAC00 \uC5BC\uB9C8\uB098 \uC544\uD30C\uD574\uC694?",
796
- painPointHint: '\uC608: "\uB9E4\uC77C \uC5D1\uC140\uC5D0 \uBCF5\uBD99\uD558\uB290\uB77C 30\uBD84\uC529 \uB0A0\uB9BC"',
797
- edge: "\u{1F4AA} \uB098\uB9CC\uC758 \uAC15\uC810\uC740? (\uBE44\uC2B7\uD55C \uAC8C \uC788\uB294\uB370 \uC65C \uC774\uAC78?)",
798
- edgeHint: '\uC608: "\uD55C\uAD6D\uC5B4\uB85C \uB41C \uAC00\uC774\uB4DC + \uBC14\uB85C \uC4F0\uB294 \uD15C\uD50C\uB9BF"',
799
- checklistStart: "\u2500\u2500\u2500 \uC774\uC5B4\uC11C \uC9C8\uBB38\uD569\uB2C8\uB2E4 \u2500\u2500\u2500",
800
- hintPrefix: " \u{1F4A1}",
801
- verdictPrompt: (_failIf) => " \u2192 \uC9C0\uAE08 \uC0C1\uD0DC\uB294?",
802
- statusPassChoice: "\u2705 \uAD1C\uCC2E\uC544\uC694",
803
- statusHoldChoice: "\u{1F7E1} \uC544\uC9C1 \uBAA8\uB974\uACA0\uC5B4\uC694 (\uB098\uC911\uC5D0 \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4)",
804
- statusFailChoice: "\u{1F504} \uBC94\uC704\uB97C \uC904\uC5EC\uBCFC\uAC8C\uC694",
805
- statusPassLine: " \u2705 \uAD1C\uCC2E\uC544\uC694",
806
- statusHoldLine: " \u{1F7E1} \uBCF4\uB958 \u2014 \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4",
807
- statusFailLine: " \u{1F504} \uBC94\uC704 \uC870\uC815\uC774 \uD544\uC694\uD574 \uBCF4\uC5EC\uC694",
808
- verdictTitle: "\u2550\u2550\u2550 \uACB0\uACFC \u2550\u2550\u2550",
809
- ideaLabel: "\uB9CC\uB4E4 \uAC83:",
810
- painPointLabel: "\uC544\uD508 \uC810:",
811
- edgeLabel: "\uB098\uB9CC\uC758 \uAC15\uC810:",
812
- countLine: (failCount, holdCount, total) => `\uBC94\uC704 \uC870\uC815 ${failCount}\uAC1C \xB7 \uBCF4\uB958 ${holdCount}\uAC1C / ${total}\uBB38\uD56D`,
813
- go: "\u2705 \uC2DC\uC791\uD574\uB3C4 \uB3FC\uC694! \uB2E4\uC74C \uB2E8\uACC4(\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uAE30)\uB85C \uB118\uC5B4\uAC00\uC138\uC694.",
814
- refine: "\u{1F504} \uC870\uAE08 \uB354 \uB2E4\uB4EC\uC73C\uBA74 \uC88B\uACA0\uC5B4\uC694. \uC704 \uD56D\uBAA9\uC744 \uBCF4\uC644\uD574 \uBCF4\uC138\uC694.",
815
- drop: "\u{1F4A1} \uB2E4\uB978 \uC544\uC774\uB514\uC5B4\uB97C \uAC80\uD1A0\uD574 \uBCF4\uB294 \uAC74 \uC5B4\uB5A8\uAE4C\uC694?",
816
- nextCommand: "\uB2E4\uC74C: vhk init (\uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30)",
817
- holdRemainHint: "\u{1F4A1} \uBCF4\uB958\uD55C \uD56D\uBAA9\uC740 \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uAD1C\uCC2E\uC544\uC694.",
818
- failMessage: "\uC544\uC9C1 \uBAA8\uB974\uACA0\uC5B4\uC694 \u2192 \uAD1C\uCC2E\uC544\uC694, \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4."
819
- },
820
- init: {
821
- title: "\u{1F6E0}\uFE0F \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30",
822
- skipGate: "\u23ED\uFE0F 1\uB2E8\uACC4(\uC544\uC774\uB514\uC5B4 \uAC80\uC99D) \uAC74\uB108\uB6F0\uAE30 \u2014 \uAE30\uD68D\xB7\uC124\uACC4\uAC00 \uC774\uBBF8 \uC788\uC5B4\uC694",
823
- projectName: "\u{1F4E6} \uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC740?",
824
- projectNameHint: '\uC608: "\uD300 \uD560 \uC77C \uC571"',
825
- description: "\u{1F4DD} \uD55C \uC904\uB85C \uC124\uBA85\uD558\uBA74?",
826
- descriptionHint: '\uC608: "3\uCD08 \uB9CC\uC5D0 \uD560 \uC77C \uCD94\uAC00"',
827
- projectType: "\u{1F3D7}\uFE0F \uC5B4\uB5A4 \uC885\uB958\uC778\uAC00\uC694?",
828
- confirmStack: "\uC774 \uAE30\uC220 \uBB36\uC74C\uC73C\uB85C \uC9C4\uD589\uD560\uAE4C\uC694?",
829
- canceled: "\uCDE8\uC18C\uD588\uC5B4\uC694. \uAE30\uC220 \uBB36\uC74C\uC744 \uBC14\uAFB8\uB824\uBA74 \uB2E4\uC2DC vhk init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
830
- recommendedStack: "\uCD94\uCC9C \uAE30\uC220 \uBB36\uC74C:",
831
- filesGenerating: "\u{1F4C2} \uD544\uC694\uD55C \uD30C\uC77C \uB9CC\uB4DC\uB294 \uC911...",
832
- overwrite: (filePath) => ` \u26A0\uFE0F ${filePath} \uD30C\uC77C\uC774 \uC788\uC5B4\uC694. \uB36E\uC5B4\uC4F8\uAE4C\uC694?`,
833
- skipped: (filePath) => `${filePath} \u2014 \uAC74\uB108\uB700`,
834
- done: "\u{1F389} \uD504\uB85C\uC81D\uD2B8 \uBF08\uB300\uAC00 \uC900\uBE44\uB410\uC5B4\uC694!",
835
- nextSteps: "\uB2E4\uC74C\uC5D0 \uD560 \uC77C:",
836
- fillHint: "CLAUDE.md \xB7 .cursorrules\uC5D0\uC11C \u{1F449} \uC5EC\uAE30\uB97C \uCC44\uC6CC\uC8FC\uC138\uC694 \uD45C\uC2DC\uB97C \uCC3E\uC544 \uCC44\uC6B0\uC138\uC694",
837
- prdHint: "docs/PRD.md\uC5D0 1\uCC28 \uBC84\uC804\uC5D0 \uB123\uC744 \uAE30\uB2A5\xB7\uBE7C\uB294 \uAE30\uB2A5\uC744 \uC801\uC5B4 \uBCF4\uC138\uC694",
838
- notionFetching: "\u{1F4E1} \uB178\uC158 \uAE30\uD68D \uD398\uC774\uC9C0 \uBD88\uB7EC\uC624\uB294 \uC911...",
839
- notionDone: (name) => `\uB178\uC158\uC5D0\uC11C \uAC00\uC838\uC624\uAE30 \uC644\uB8CC: ${name}`,
840
- notionReviewHint: "docs/PRD.md\uB97C \uC77D\uACE0 \u{1F449} \uC5EC\uAE30\uB97C \uCC44\uC6CC\uC8FC\uC138\uC694 \uD56D\uBAA9\uC744 \uCC44\uC6B0\uC138\uC694",
841
- gitHintLabel: "\uD130\uBBF8\uB110\uC5D0 \uBCF5\uC0AC\uD560 \uBA85\uB839 (\uC544\uB798 \uBC15\uC2A4 \uBCF5\uBD99):",
842
- gitHintCommand: 'git init && git add . && git commit -m "feat: \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791"',
843
- startDev: "\uC774\uC81C \uAC1C\uBC1C\uD574 \uBCF4\uC138\uC694! \u{1F680}",
844
- commandsMdDone: "\u{1F4CB} COMMANDS.md \uC0DD\uC131",
845
- scriptsDone: "\u{1F4E6} package.json scripts \uCD94\uAC00"
846
- },
847
- recap: {
848
- title: "\u{1F4DD} \uC624\uB298 \uD55C \uC77C \uC815\uB9AC",
849
- analyzing: "\u{1F4CA} \uC624\uB298 \uBC14\uB010 \uD30C\uC77C\xB7\uCEE4\uBC0B\uC744 \uC0B4\uD3B4\uBCF4\uB294 \uC911...",
850
- noRepo: "\u274C Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2C8\uC5D0\uC694. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
851
- noChanges: "\u26A0\uFE0F \uC624\uB298 \uBC14\uB010 \uB0B4\uC6A9\uC774 \uC5C6\uC5B4\uC694.",
852
- summary: "\u{1F4DD} \uC774\uBC88\uC5D0 \uBB58 \uD588\uB098\uC694? (1~3\uC904)",
853
- summaryHint: '\uC608: "\uB85C\uADF8\uC778 \uD654\uBA74 \uB9CC\uB4E4\uACE0 \uBC84\uD2BC \uC0C9 \uACE0\uCE68"',
854
- decisions: "\u{1F9ED} \uC815\uD55C \uACB0\uC815\uC774 \uC788\uB098\uC694? (\uC5C6\uC73C\uBA74 Enter)",
855
- nextTodo: "\u23ED\uFE0F \uB2E4\uC74C\uC5D0 \uD560 \uC77C\uC740?",
856
- blockers: "\u{1F6A7} \uB9C9\uD78C \uAC8C \uC788\uB098\uC694? (\uC5C6\uC73C\uBA74 Enter)",
857
- done: "\u2705 \uC624\uB298 \uAE30\uB85D\uC744 \uC800\uC7A5\uD588\uC5B4\uC694!",
858
- updateClaude: 'CLAUDE.md "\uC9C0\uAE08 \uC0C1\uD0DC"\uB3C4 \uAC19\uC774 \uACE0\uCE60\uAE4C\uC694?',
859
- adrDetected: "\u{1F4D0} \uC4F0\uB294 \uAE30\uC220\xB7\uC124\uC815\uC774 \uBC14\uB010 \uAC83 \uAC19\uC544\uC694!",
860
- createAdr: "\uC65C \uADF8\uB807\uAC8C \uD588\uB294\uC9C0 \uAE30\uB85D \uBB38\uC11C\uB97C \uB9CC\uB4E4\uAE4C\uC694?",
861
- troubleDetected: "\u{1F527} \uBC84\uADF8\xB7\uC624\uB958\uB97C \uACE0\uCE5C \uCEE4\uBC0B\uC774 \uBCF4\uC5EC\uC694!",
862
- createTroubleshoot: "\uC5B4\uB5BB\uAC8C \uACE0\uCCE4\uB294\uC9C0 \uBA54\uBAA8\uB97C \uB0A8\uAE38\uAE4C\uC694?"
863
- },
864
- check: {
865
- title: "\u{1F50D} \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59 \uC810\uAC80",
866
- noRules: "\u26A0\uFE0F RULES.md \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.",
867
- noAutoRules: "\u26A0\uFE0F \uC790\uB3D9\uC73C\uB85C \uAC80\uC0AC\uD560 \uADDC\uCE59\uC774 \uC5C6\uC5B4\uC694.",
868
- allPassed: "\u{1F389} \uADDC\uCE59\uC744 \uBAA8\uB450 \uC9C0\uCF30\uC5B4\uC694!",
869
- summary: "\u{1F4CA} \uC810\uAC80 \uACB0\uACFC:"
870
- },
871
- doctor: {
872
- title: "\u{1FA7A} \uAC1C\uBC1C \uD658\uACBD \uC810\uAC80",
873
- allOk: "\u{1F389} \uAC1C\uBC1C \uD658\uACBD \uC900\uBE44 \uC644\uB8CC!",
874
- missing: "\u26A0\uFE0F \uC77C\uBD80 \uB3C4\uAD6C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
875
- missingHint: "\uC704 \uC548\uB0B4\uB97C \uB530\uB77C \uC124\uCE58\uD558\uC138\uC694.",
876
- projectFiles: "\u{1F4C1} \uD504\uB85C\uC81D\uD2B8 \uD30C\uC77C \uD655\uC778:",
877
- envNotIgnored: "\u26A0\uFE0F .env\uAC00 .gitignore\uC5D0 \uC5C6\uC74C! \uCD94\uAC00\uD558\uC138\uC694",
878
- nextOkMessage: "\uD658\uACBD \uC810\uAC80 \uD1B5\uACFC! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uC2DC\uC791\uD558\uC138\uC694.",
879
- nextRetryMessage: "\uC704 \uB3C4\uAD6C\uB97C \uC124\uCE58\uD55C \uD6C4 \uB2E4\uC2DC \uC810\uAC80\uD558\uC138\uC694.",
880
- updateAvailable: (latest) => `\u{1F195} v${latest} \uC0AC\uC6A9 \uAC00\uB2A5 \u2014 npm i -g @byh3071/vhk`,
881
- updateCurrent: "\uCD5C\uC2E0 \uBC84\uC804\uC744 \uC4F0\uACE0 \uC788\uC5B4\uC694"
882
- },
883
- nlp: {
884
- matched: "\uC774\uAC8C \uB9DE\uB098\uC694?",
885
- notMatched: "\uBB34\uC2A8 \uB73B\uC778\uC9C0 \uBAA8\uB974\uACA0\uC5B4\uC694. vhk\uB97C \uC785\uB825\uD558\uBA74 \uBA54\uB274\uC5D0\uC11C \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
886
- menuHint: "vhk\uB97C \uC785\uB825\uD558\uBA74 \uBA54\uB274\uC5D0\uC11C \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
887
- },
888
- secure: {
889
- title: "\u{1F512} \uBE44\uBC00\uBC88\uD638\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC",
890
- noGitignore: "\u26A0\uFE0F .gitignore \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694!",
891
- noEnvInGitignore: "\u26A0\uFE0F .gitignore\uC5D0 .env\uAC00 \uC5C6\uC5B4\uC694!",
892
- scanning: "\u{1F50D} \uD30C\uC77C\uC744 \uC0B4\uD3B4\uBCF4\uB294 \uC911...",
893
- clean: "\u{1F389} \uBE44\uBC00\uBC88\uD638\xB7\uD0A4\uAC00 \uCF54\uB4DC\uC5D0 \uBCF4\uC774\uC9C0 \uC54A\uC544\uC694!",
894
- summary: "\u{1F4CA} \uAC80\uC0AC \uC694\uC57D:"
895
- },
896
- sync: {
897
- title: "\u{1F504} \uADDC\uCE59 \uD30C\uC77C \uB9DE\uCD94\uAE30",
898
- noRules: "\u26A0\uFE0F RULES.md \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.",
899
- cursorrulesDone: "\u2705 .cursorrules \uB9DE\uCDA4 \uC644\uB8CC",
900
- claudeDone: "\u2705 CLAUDE.md \uB9DE\uCDA4 \uC644\uB8CC",
901
- done: "\u{1F504} \uB9DE\uCD94\uAE30 \uC644\uB8CC!"
902
- },
903
- ship: {
904
- title: "\u{1F680} \uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
905
- checklist: "\u{1F4CB} \uBC30\uD3EC \uC804 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
906
- retro: "\u{1F50D} \uBC30\uD3EC \uD68C\uACE0",
907
- buildLogCreated: "\u2705 \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131 \uC644\uB8CC",
908
- buildLogDone: (rel) => `\u2705 \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131 \uC644\uB8CC: ${rel}`,
909
- questionWell: "\uC798\uB41C \uC810\uC740?",
910
- questionWrong: "\uC5B4\uB824\uC6E0\uB358 \uC810\uC740?",
911
- questionLearned: "\uBC30\uC6B4 \uC810\uC740?",
912
- questionNext: "\uB2E4\uC74C \uBC84\uC804\uC5D0\uC11C \uD560 \uAC83\uC740?",
913
- checkboxPrompt: "\uC644\uB8CC\uD55C \uD56D\uBAA9\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
914
- incompleteHeader: "\u26A0\uFE0F \uC544\uC9C1 \uC644\uB8CC\uD558\uC9C0 \uC54A\uC740 \uD56D\uBAA9:",
915
- proceedConfirm: "\uADF8\uB798\uB3C4 \uACC4\uC18D \uC9C4\uD589\uD560\uAE4C\uC694?",
916
- allPassed: "\u2705 \uBAA8\uB4E0 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 \uD1B5\uACFC!",
917
- retryMessage: "\uCCB4\uD06C\uB9AC\uC2A4\uD2B8\uB97C \uB9C8\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD574 \uBCF4\uC138\uC694.",
918
- retryCursorHint: "\uBE4C\uB4DC\uD558\uACE0 \uD14C\uC2A4\uD2B8 \uB3CC\uB824\uC918",
919
- versionPrompt: "\uBC30\uD3EC \uBC84\uC804\uC740?",
920
- versionHint: "\uC608: 0.4.0",
921
- emptySection: "(\uBBF8\uC791\uC131)",
922
- emptyNext: "(\uBBF8\uC815)",
923
- deployMessage: "\uBE4C\uB4DC \uB85C\uADF8\uB97C \uC800\uC7A5\uD588\uC5B4\uC694! \uC774\uC81C \uC2E4\uC81C \uBC30\uD3EC\uB97C \uC9C4\uD589\uD558\uC138\uC694.",
924
- deployCursorHint: "\uBC30\uD3EC\uD574\uC918",
925
- checkBuild: "\uBE4C\uB4DC\uAC00 \uC131\uACF5\uD588\uB098\uC694?",
926
- hintBuild: "pnpm build",
927
- checkTest: "\uBAA8\uB4E0 \uD14C\uC2A4\uD2B8\uAC00 \uD1B5\uACFC\uD588\uB098\uC694?",
928
- hintTest: "pnpm test --run",
929
- checkVersion: "package.json \uBC84\uC804\uC744 \uC62C\uB838\uB098\uC694?",
930
- hintVersion: "version \uD544\uB4DC \uD655\uC778",
931
- checkChangelog: "\uBCC0\uACBD \uB0B4\uC6A9\uC744 \uAE30\uB85D\uD588\uB098\uC694?",
932
- hintChangelog: "README \uB610\uB294 CHANGELOG",
933
- checkSecurity: "\uBCF4\uC548 \uC2A4\uCE94\uC744 \uB3CC\uB838\uB098\uC694?",
934
- hintSecurity: "vhk \uBCF4\uC548 scan",
935
- checkCommit: "\uBAA8\uB4E0 \uBCC0\uACBD\uC774 \uCEE4\uBC0B\uB418\uC5C8\uB098\uC694?",
936
- hintCommit: "git status \uD655\uC778",
937
- changelogUpdated: (version) => `CHANGELOG.md \uAC31\uC2E0\uB428 \u2014 [Unreleased] \u2192 [${version}] \uC139\uC158\uC73C\uB85C \uC774\uB3D9`,
938
- changelogNoUnreleased: "CHANGELOG.md\uC5D0 [Unreleased] \uC139\uC158\uC774 \uC5C6\uC5B4 \uC790\uB3D9 \uAC31\uC2E0\uC744 \uC2A4\uD0B5\uD588\uC5B4\uC694",
939
- changelogMissing: "CHANGELOG.md\uAC00 \uC5C6\uC5B4\uC694. \uB9CC\uB4E4\uBA74 ship\uC774 \uC790\uB3D9\uC73C\uB85C [Unreleased] \u2192 \uBC84\uC804 \uC139\uC158\uC73C\uB85C \uC62E\uACA8\uC90D\uB2C8\uB2E4."
940
- },
941
- mcp: {
942
- initTitle: "Cursor MCP \uC5F0\uB3D9 \uC124\uC815",
943
- serverStarted: "VHK MCP \uC11C\uBC84 \uC2DC\uC791\uB428"
944
- },
945
- deploy: {
946
- title: "\uBC30\uD3EC\uD558\uAE30",
947
- selectPlatform: "\uC5B4\uB5A4 \uD50C\uB7AB\uD3FC\uC5D0 \uBC30\uD3EC\uD560\uAE4C\uC694?",
948
- deploying: "\uBC30\uD3EC \uC911...",
949
- success: "\uBC30\uD3EC \uC131\uACF5!",
950
- failed: "\uBC30\uD3EC \uC2E4\uD328"
951
- },
952
- env: {
953
- title: "\uD658\uACBD\uBCC0\uC218 \uAD00\uB9AC",
954
- checkTitle: "\uD658\uACBD\uBCC0\uC218 \uC810\uAC80"
955
- },
956
- publish: {
957
- title: "npm \uBC30\uD3EC",
958
- selectBump: "\uBC84\uC804\uC744 \uC5B4\uB5BB\uAC8C \uC62C\uB9B4\uAE4C\uC694?",
959
- building: "\uBE4C\uB4DC \uC911...",
960
- buildSuccess: "\uBE4C\uB4DC \uC131\uACF5",
961
- buildFailed: "\uBE4C\uB4DC \uC2E4\uD328",
962
- testing: "\uD14C\uC2A4\uD2B8 \uC911...",
963
- testSuccess: "\uD14C\uC2A4\uD2B8 \uD1B5\uACFC",
964
- testFailed: "\uD14C\uC2A4\uD2B8 \uC2E4\uD328",
965
- publishing: "npm \uBC30\uD3EC \uC911...",
966
- publishSuccess: "npm \uBC30\uD3EC \uC131\uACF5!",
967
- publishFailed: "npm \uBC30\uD3EC \uC2E4\uD328"
968
- }
969
- };
970
- function lookup(path15) {
971
- const parts = path15.split(".");
972
- let cur = ko;
973
- for (const part of parts) {
974
- if (cur === null || typeof cur !== "object") return void 0;
975
- cur = cur[part];
976
- }
977
- return cur;
978
- }
979
- function t(key, ...args) {
980
- const value = lookup(key);
981
- if (typeof value === "function") {
982
- return value(...args);
983
- }
984
- if (typeof value === "string") return value;
985
- return key;
986
- }
732
+ import chalk21 from "chalk";
733
+ import inquirer11 from "inquirer";
987
734
 
988
735
  // src/commands/gate.ts
989
736
  import inquirer from "inquirer";
990
- import chalk2 from "chalk";
991
-
992
- // src/lib/next-step.ts
993
737
  import chalk from "chalk";
994
- function printNextStep(step) {
995
- console.log("");
996
- console.log(chalk.cyan.bold("\u2501\u2501\u2501 \uB2E4\uC74C\uC5D0 \uC774\uAC83\uB9CC \uD558\uC138\uC694 \u2501\u2501\u2501"));
997
- console.log("");
998
- console.log(` ${step.message}`);
999
- if (step.command) {
1000
- console.log("");
1001
- console.log(chalk.white.bgGray(" \uD130\uBBF8\uB110\uC5D0 \uBCF5\uBD99 "));
1002
- console.log(chalk.green(` ${step.command}`));
1003
- }
1004
- if (step.cursorHint) {
1005
- console.log("");
1006
- console.log(chalk.white.bgBlue(" Cursor\uC5D0\uAC8C \uB9D0\uD558\uAE30 "));
1007
- console.log(chalk.blue(` "${step.cursorHint}"`));
1008
- }
1009
- if (step.alternative) {
1010
- console.log("");
1011
- console.log(chalk.dim(` \uB610\uB294: ${step.alternative}`));
1012
- }
1013
- console.log("");
1014
- console.log(chalk.cyan.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
1015
- console.log("");
1016
- }
1017
-
1018
- // src/commands/gate.ts
1019
738
  var GATE_QUESTIONS = [
1020
739
  { id: 1, stage: "\uBB38\uC81C \uC815\uC758", question: "\uC774 \uC544\uC774\uB514\uC5B4\uAC00 \uD574\uACB0\uD558\uB294 \uBB38\uC81C\uB97C \uD55C \uBB38\uC7A5\uC73C\uB85C \uB9D0\uD574\uBCF4\uC138\uC694.", failIf: "\uD55C \uBB38\uC7A5 \uBD88\uAC00 \u2192 \uBBF8\uC131\uC219", quick: true },
1021
740
  { id: 2, stage: "\uD575\uC2EC \uAE30\uB2A5", question: "\uB531 1\uAC1C \uAE30\uB2A5\uB9CC \uACE0\uB974\uBA74?", failIf: "2\uAC1C \uC774\uC0C1 \u2192 \uBC94\uC704 \uCD08\uACFC", quick: true },
@@ -1037,7 +756,7 @@ function judgeGate(failCount, holdCount) {
1037
756
  return "DROP";
1038
757
  }
1039
758
  async function gate() {
1040
- console.log(chalk2.bold(`
759
+ console.log(chalk.bold(`
1041
760
  ${ko.gate.title}
1042
761
  `));
1043
762
  const { mode } = await inquirer.prompt([{
@@ -1056,33 +775,33 @@ ${ko.gate.title}
1056
775
  name: "source",
1057
776
  message: ko.gate.skipSourcePrompt
1058
777
  }]);
1059
- console.log(chalk2.green.bold(`
778
+ console.log(chalk.green.bold(`
1060
779
  ${ko.gate.skipGo}`));
1061
- console.log(chalk2.dim(ko.gate.skipSourceLabel(source)));
780
+ console.log(chalk.dim(ko.gate.skipSourceLabel(source)));
1062
781
  return;
1063
782
  }
1064
783
  const questions = mode === "quick" ? GATE_QUESTIONS.filter((q) => q.quick) : GATE_QUESTIONS;
1065
784
  const total = questions.length;
1066
785
  const header = mode === "quick" ? ko.gate.quickHeader : ko.gate.fullHeader;
1067
- console.log(chalk2.dim(`
786
+ console.log(chalk.dim(`
1068
787
  ${header} ${ko.gate.modeCountSuffix(total)}
1069
788
  `));
1070
- console.log(chalk2.dim(`
789
+ console.log(chalk.dim(`
1071
790
  ${ko.gate.welcome}
1072
791
  `));
1073
- console.log(chalk2.dim(` ${ko.gate.ideaHint}`));
792
+ console.log(chalk.dim(` ${ko.gate.ideaHint}`));
1074
793
  const { idea } = await inquirer.prompt([
1075
794
  { type: "input", name: "idea", message: ko.gate.idea }
1076
795
  ]);
1077
- console.log(chalk2.dim(` ${ko.gate.painPointHint}`));
796
+ console.log(chalk.dim(` ${ko.gate.painPointHint}`));
1078
797
  const { painPoint } = await inquirer.prompt([
1079
798
  { type: "input", name: "painPoint", message: ko.gate.painPoint }
1080
799
  ]);
1081
- console.log(chalk2.dim(` ${ko.gate.edgeHint}`));
800
+ console.log(chalk.dim(` ${ko.gate.edgeHint}`));
1082
801
  const { edge } = await inquirer.prompt([
1083
802
  { type: "input", name: "edge", message: ko.gate.edge }
1084
803
  ]);
1085
- console.log(chalk2.dim(`
804
+ console.log(chalk.dim(`
1086
805
  ${ko.gate.checklistStart}
1087
806
  `));
1088
807
  let failCount = 0;
@@ -1090,7 +809,7 @@ ${ko.gate.checklistStart}
1090
809
  const results = [];
1091
810
  for (let i = 0; i < questions.length; i++) {
1092
811
  const q = questions[i];
1093
- if (q.hint) console.log(chalk2.dim(`${ko.gate.hintPrefix} ${q.hint}`));
812
+ if (q.hint) console.log(chalk.dim(`${ko.gate.hintPrefix} ${q.hint}`));
1094
813
  const { answer } = await inquirer.prompt([{
1095
814
  type: "input",
1096
815
  name: "answer",
@@ -1109,22 +828,22 @@ ${ko.gate.checklistStart}
1109
828
  if (status2 === "fail") failCount++;
1110
829
  if (status2 === "hold") holdCount++;
1111
830
  results.push({ id: q.id, stage: q.stage, status: status2, answer });
1112
- const icon = status2 === "pass" ? chalk2.green(ko.gate.statusPassLine) : status2 === "hold" ? chalk2.yellow(ko.gate.statusHoldLine) : chalk2.red(ko.gate.statusFailLine);
831
+ const icon = status2 === "pass" ? chalk.green(ko.gate.statusPassLine) : status2 === "hold" ? chalk.yellow(ko.gate.statusHoldLine) : chalk.red(ko.gate.statusFailLine);
1113
832
  console.log(icon);
1114
833
  }
1115
- console.log(chalk2.bold(`
834
+ console.log(chalk.bold(`
1116
835
  ${ko.gate.verdictTitle}
1117
836
  `));
1118
- console.log(`${ko.gate.ideaLabel} ${chalk2.cyan(idea)}`);
837
+ console.log(`${ko.gate.ideaLabel} ${chalk.cyan(idea)}`);
1119
838
  console.log(`${ko.gate.painPointLabel} ${painPoint}`);
1120
839
  console.log(`${ko.gate.edgeLabel} ${edge}`);
1121
840
  console.log(`${ko.gate.countLine(failCount, holdCount, total)}
1122
841
  `);
1123
842
  const verdict = judgeGate(failCount, holdCount);
1124
843
  if (verdict === "GO") {
1125
- console.log(chalk2.green.bold(ko.gate.go));
844
+ console.log(chalk.green.bold(ko.gate.go));
1126
845
  if (holdCount > 0) {
1127
- console.log(chalk2.yellow(ko.gate.holdRemainHint));
846
+ console.log(chalk.yellow(ko.gate.holdRemainHint));
1128
847
  }
1129
848
  printNextStep({
1130
849
  message: "\uC544\uC774\uB514\uC5B4 \uD1B5\uACFC! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E4\uC5B4\uBCF4\uC138\uC694.",
@@ -1132,20 +851,20 @@ ${ko.gate.verdictTitle}
1132
851
  cursorHint: "\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uC5B4\uC918"
1133
852
  });
1134
853
  } else if (verdict === "REFINE") {
1135
- console.log(chalk2.yellow.bold(ko.gate.refine));
854
+ console.log(chalk.yellow.bold(ko.gate.refine));
1136
855
  printNextStep({
1137
856
  message: "\uC870\uAE08 \uB354 \uB2E4\uB4EC\uC740 \uD6C4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uBCF4\uC138\uC694.",
1138
857
  command: "vhk \uAC80\uC99D",
1139
858
  cursorHint: "\uC544\uC774\uB514\uC5B4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uC918"
1140
859
  });
1141
860
  } else {
1142
- console.log(chalk2.red.bold(ko.gate.drop));
861
+ console.log(chalk.red.bold(ko.gate.drop));
1143
862
  }
1144
863
  }
1145
864
 
1146
865
  // src/commands/init.ts
1147
866
  import inquirer2 from "inquirer";
1148
- import chalk5 from "chalk";
867
+ import chalk4 from "chalk";
1149
868
  import fs3 from "fs";
1150
869
  import path3 from "path";
1151
870
 
@@ -1361,7 +1080,7 @@ function COMMANDS_MD_TEMPLATE() {
1361
1080
  var import_ignore = __toESM(require_ignore(), 1);
1362
1081
  import fs from "fs";
1363
1082
  import path from "path";
1364
- import chalk3 from "chalk";
1083
+ import chalk2 from "chalk";
1365
1084
  function loadGitignore(rootDir) {
1366
1085
  const ig = (0, import_ignore.default)();
1367
1086
  const gitignorePath = path.join(rootDir, ".gitignore");
@@ -1434,7 +1153,7 @@ function printSecurityWarnings(rootDir = process.cwd()) {
1434
1153
  const result = checkProjectSecurity(rootDir);
1435
1154
  if (result.ok) return true;
1436
1155
  for (const w of result.warnings) {
1437
- console.log(chalk3.yellow(` \u26A0\uFE0F ${w}`));
1156
+ console.log(chalk2.yellow(` \u26A0\uFE0F ${w}`));
1438
1157
  }
1439
1158
  return false;
1440
1159
  }
@@ -1444,13 +1163,13 @@ function filterTrackedPaths(paths, rootDir = process.cwd()) {
1444
1163
  }
1445
1164
 
1446
1165
  // src/utils/logger.ts
1447
- import chalk4 from "chalk";
1166
+ import chalk3 from "chalk";
1448
1167
  var log = {
1449
- success: (msg) => console.log(chalk4.green(`\u2705 ${msg}`)),
1450
- error: (msg) => console.log(chalk4.red(`\u274C ${msg}`)),
1451
- warn: (msg) => console.log(chalk4.yellow(`\u26A0\uFE0F ${msg}`)),
1452
- info: (msg) => console.log(chalk4.blue(`\u2139\uFE0F ${msg}`)),
1453
- step: (msg) => console.log(chalk4.bold(`
1168
+ success: (msg) => console.log(chalk3.green(`\u2705 ${msg}`)),
1169
+ error: (msg) => console.log(chalk3.red(`\u274C ${msg}`)),
1170
+ warn: (msg) => console.log(chalk3.yellow(`\u26A0\uFE0F ${msg}`)),
1171
+ info: (msg) => console.log(chalk3.blue(`\u2139\uFE0F ${msg}`)),
1172
+ step: (msg) => console.log(chalk3.bold(`
1454
1173
  \u25B8 ${msg}`))
1455
1174
  };
1456
1175
 
@@ -1655,11 +1374,11 @@ async function collectAnswers(options, defaults = {}) {
1655
1374
  async function init(options = {}) {
1656
1375
  const skipGate = Boolean(options.skipGate || options.fromNotion);
1657
1376
  if (skipGate) {
1658
- console.log(chalk5.dim(`
1377
+ console.log(chalk4.dim(`
1659
1378
  ${ko.init.skipGate}
1660
1379
  `));
1661
1380
  }
1662
- console.log(chalk5.bold(`
1381
+ console.log(chalk4.bold(`
1663
1382
  ${ko.init.title}
1664
1383
  `));
1665
1384
  printSecurityWarnings();
@@ -1684,7 +1403,7 @@ ${ko.init.title}
1684
1403
  process.exit(1);
1685
1404
  }
1686
1405
  const stack = STACK_PRESETS[answers.type];
1687
- console.log(chalk5.dim(`
1406
+ console.log(chalk4.dim(`
1688
1407
  ${ko.init.recommendedStack} ${stack.join(" + ")}
1689
1408
  `));
1690
1409
  if (!options.yes) {
@@ -1720,21 +1439,21 @@ ${ko.init.recommendedStack} ${stack.join(" + ")}
1720
1439
  log.success(filePath);
1721
1440
  }
1722
1441
  await writeInitExtras(cwd);
1723
- console.log(chalk5.bold.green(`
1442
+ console.log(chalk4.bold.green(`
1724
1443
  ${ko.init.done}`));
1725
- console.log(chalk5.dim(`
1444
+ console.log(chalk4.dim(`
1726
1445
  ${ko.init.nextSteps}`));
1727
1446
  if (options.fromNotion) {
1728
1447
  console.log(` 1. ${ko.init.notionReviewHint}`);
1729
1448
  console.log(` 2. ${ko.init.gitHintLabel}`);
1730
- console.log(` ${chalk5.cyan(ko.init.gitHintCommand)}`);
1449
+ console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
1731
1450
  console.log(` 3. ${ko.init.startDev}
1732
1451
  `);
1733
1452
  } else {
1734
1453
  console.log(` 1. ${ko.init.fillHint}`);
1735
1454
  console.log(` 2. ${ko.init.prdHint}`);
1736
1455
  console.log(` 3. ${ko.init.gitHintLabel}`);
1737
- console.log(` ${chalk5.cyan(ko.init.gitHintCommand)}`);
1456
+ console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
1738
1457
  console.log(` 4. ${ko.init.startDev}
1739
1458
  `);
1740
1459
  }
@@ -1815,7 +1534,7 @@ async function writeInitExtras(projectDir) {
1815
1534
 
1816
1535
  // src/commands/recap.ts
1817
1536
  import inquirer3 from "inquirer";
1818
- import chalk6 from "chalk";
1537
+ import chalk5 from "chalk";
1819
1538
  import fs5 from "fs";
1820
1539
  import path6 from "path";
1821
1540
 
@@ -1974,40 +1693,40 @@ function createAdrFile(cwd, title, context, decision, consequences) {
1974
1693
 
1975
1694
  // src/commands/recap.ts
1976
1695
  async function recap(options = {}) {
1977
- console.log(chalk6.bold(`
1696
+ console.log(chalk5.bold(`
1978
1697
  ${ko.recap.title}
1979
1698
  `));
1980
1699
  if (!await isGitRepo()) {
1981
- console.log(chalk6.red(ko.recap.noRepo));
1700
+ console.log(chalk5.red(ko.recap.noRepo));
1982
1701
  return;
1983
1702
  }
1984
1703
  printSecurityWarnings();
1985
- console.log(chalk6.dim(`${ko.recap.analyzing}
1704
+ console.log(chalk5.dim(`${ko.recap.analyzing}
1986
1705
  `));
1987
1706
  const since = options.since || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1988
1707
  const diff2 = await getSessionDiff(since);
1989
1708
  const commits = await getRecentCommits(10, since);
1990
1709
  if (diff2.filesChanged === 0 && commits.length === 0) {
1991
- console.log(chalk6.yellow(ko.recap.noChanges));
1710
+ console.log(chalk5.yellow(ko.recap.noChanges));
1992
1711
  return;
1993
1712
  }
1994
- console.log(chalk6.bold("\u{1F4CA} \uBCC0\uACBD \uC694\uC57D:"));
1995
- console.log(` \uD30C\uC77C: ${chalk6.cyan(String(diff2.filesChanged))}\uAC1C \uBCC0\uACBD`);
1996
- console.log(` \uCD94\uAC00: ${chalk6.green("+" + diff2.insertions)} / \uC0AD\uC81C: ${chalk6.red("-" + diff2.deletions)}`);
1713
+ console.log(chalk5.bold("\u{1F4CA} \uBCC0\uACBD \uC694\uC57D:"));
1714
+ console.log(` \uD30C\uC77C: ${chalk5.cyan(String(diff2.filesChanged))}\uAC1C \uBCC0\uACBD`);
1715
+ console.log(` \uCD94\uAC00: ${chalk5.green("+" + diff2.insertions)} / \uC0AD\uC81C: ${chalk5.red("-" + diff2.deletions)}`);
1997
1716
  if (diff2.files.length > 0) {
1998
- console.log(chalk6.dim("\n \uBCC0\uACBD \uD30C\uC77C:"));
1717
+ console.log(chalk5.dim("\n \uBCC0\uACBD \uD30C\uC77C:"));
1999
1718
  diff2.files.slice(0, 15).forEach((f) => {
2000
- const icon = f.status === "new" ? chalk6.green("\u{1F195}") : f.status === "deleted" ? chalk6.red("\u{1F5D1}\uFE0F") : chalk6.yellow("\u270F\uFE0F");
1719
+ const icon = f.status === "new" ? chalk5.green("\u{1F195}") : f.status === "deleted" ? chalk5.red("\u{1F5D1}\uFE0F") : chalk5.yellow("\u270F\uFE0F");
2001
1720
  console.log(` ${icon} ${f.file}`);
2002
1721
  });
2003
1722
  if (diff2.files.length > 15) {
2004
- console.log(chalk6.dim(` ... \uC678 ${diff2.files.length - 15}\uAC1C`));
1723
+ console.log(chalk5.dim(` ... \uC678 ${diff2.files.length - 15}\uAC1C`));
2005
1724
  }
2006
1725
  }
2007
1726
  if (commits.length > 0) {
2008
- console.log(chalk6.dim("\n \uCD5C\uADFC \uCEE4\uBC0B:"));
1727
+ console.log(chalk5.dim("\n \uCD5C\uADFC \uCEE4\uBC0B:"));
2009
1728
  commits.slice(0, 5).forEach((c) => {
2010
- console.log(chalk6.dim(` \u2022 ${c.message}`));
1729
+ console.log(chalk5.dim(` \u2022 ${c.message}`));
2011
1730
  });
2012
1731
  }
2013
1732
  console.log("");
@@ -2075,11 +1794,11 @@ ${ko.recap.title}
2075
1794
  fs5.writeFileSync(filePath, content, "utf-8");
2076
1795
  const adrCandidates = detectAdrCandidates(diff2);
2077
1796
  if (adrCandidates.length > 0) {
2078
- console.log(chalk6.cyan.bold(`
1797
+ console.log(chalk5.cyan.bold(`
2079
1798
  ${ko.recap.adrDetected} (${adrCandidates.length}\uAC74)`));
2080
1799
  for (const candidate of adrCandidates) {
2081
- console.log(chalk6.cyan(` \u2022 ${candidate.title}: ${candidate.context}`));
2082
- candidate.files.forEach((f) => console.log(chalk6.dim(` ${f}`)));
1800
+ console.log(chalk5.cyan(` \u2022 ${candidate.title}: ${candidate.context}`));
1801
+ candidate.files.forEach((f) => console.log(chalk5.dim(` ${f}`)));
2083
1802
  }
2084
1803
  const { createAdr } = await inquirer3.prompt([{
2085
1804
  type: "confirm",
@@ -2109,17 +1828,17 @@ ${ko.recap.adrDetected} (${adrCandidates.length}\uAC74)`));
2109
1828
  adrAnswers.decision,
2110
1829
  adrAnswers.consequences
2111
1830
  );
2112
- console.log(chalk6.green(` \u2705 ADR \uC0DD\uC131: ${path6.relative(process.cwd(), adrPath)}`));
1831
+ console.log(chalk5.green(` \u2705 ADR \uC0DD\uC131: ${path6.relative(process.cwd(), adrPath)}`));
2113
1832
  }
2114
1833
  }
2115
1834
  }
2116
1835
  const troubleshootingKeywords = /fix|bug|error|crash|hotfix|patch|revert|트러블|에러|버그|수정|핫픽스/i;
2117
1836
  const troubleCommits = commits.filter((c) => troubleshootingKeywords.test(c.message));
2118
1837
  if (troubleCommits.length > 0) {
2119
- console.log(chalk6.yellow.bold(`
1838
+ console.log(chalk5.yellow.bold(`
2120
1839
  ${ko.recap.troubleDetected} (${troubleCommits.length}\uAC74)`));
2121
1840
  troubleCommits.forEach((c) => {
2122
- console.log(chalk6.dim(` \u2022 ${c.message}`));
1841
+ console.log(chalk5.dim(` \u2022 ${c.message}`));
2123
1842
  });
2124
1843
  const { createTroubleshoot } = await inquirer3.prompt([{
2125
1844
  type: "confirm",
@@ -2170,12 +1889,12 @@ ${ko.recap.troubleDetected} (${troubleCommits.length}\uAC74)`));
2170
1889
  `*Generated by \`vhk recap\` at ${(/* @__PURE__ */ new Date()).toISOString()}*`
2171
1890
  ].join("\n");
2172
1891
  fs5.writeFileSync(tsFilePath, tsContent, "utf-8");
2173
- console.log(chalk6.green(` \u2705 \uD2B8\uB7EC\uBE14\uC288\uD305 \uBB38\uC11C \uC0DD\uC131: ${path6.relative(process.cwd(), tsFilePath)}`));
1892
+ console.log(chalk5.green(` \u2705 \uD2B8\uB7EC\uBE14\uC288\uD305 \uBB38\uC11C \uC0DD\uC131: ${path6.relative(process.cwd(), tsFilePath)}`));
2174
1893
  }
2175
1894
  }
2176
- console.log(chalk6.green.bold(`
1895
+ console.log(chalk5.green.bold(`
2177
1896
  ${ko.recap.done}`));
2178
- console.log(chalk6.dim(` \u{1F4C4} ${path6.relative(process.cwd(), filePath)}`));
1897
+ console.log(chalk5.dim(` \u{1F4C4} ${path6.relative(process.cwd(), filePath)}`));
2179
1898
  const claudeMdPath = path6.join(process.cwd(), "CLAUDE.md");
2180
1899
  if (fs5.existsSync(claudeMdPath)) {
2181
1900
  const { updateClaude } = await inquirer3.prompt([{
@@ -2195,7 +1914,7 @@ ${ko.recap.done}`));
2195
1914
  `- **\uB2E4\uC74C \uC561\uC158:** ${answers.nextTodo}`
2196
1915
  );
2197
1916
  fs5.writeFileSync(claudeMdPath, claudeContent, "utf-8");
2198
- console.log(chalk6.green(" \u2705 CLAUDE.md \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC"));
1917
+ console.log(chalk5.green(" \u2705 CLAUDE.md \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC"));
2199
1918
  }
2200
1919
  }
2201
1920
  const gitSaveCmd = process.platform === "win32" ? 'git add .; git commit -m "recap: \uC138\uC158 \uAE30\uB85D"' : 'git add . && git commit -m "recap: \uC138\uC158 \uAE30\uB85D"';
@@ -2207,7 +1926,7 @@ ${ko.recap.done}`));
2207
1926
  }
2208
1927
 
2209
1928
  // src/commands/sync.ts
2210
- import chalk7 from "chalk";
1929
+ import chalk6 from "chalk";
2211
1930
  import fs6 from "fs";
2212
1931
  import path7 from "path";
2213
1932
  var CURSORRULES_KEYS = ["\uCF54\uB529 \uADDC\uCE59", "\uAE30\uC220 \uC2A4\uD0DD", "\uC544\uD0A4\uD14D\uCC98", "\uB514\uC790\uC778", "Anti-patterns", "\uCEE4\uBC0B"];
@@ -2277,32 +1996,32 @@ function toClaudeMd(sections, existing) {
2277
1996
  return lines.join("\n");
2278
1997
  }
2279
1998
  async function sync() {
2280
- console.log(chalk7.bold(`
1999
+ console.log(chalk6.bold(`
2281
2000
  ${ko.sync.title}
2282
2001
  `));
2283
2002
  const cwd = process.cwd();
2284
2003
  const rulesPath = path7.join(cwd, "RULES.md");
2285
2004
  if (!fs6.existsSync(rulesPath)) {
2286
- console.log(chalk7.yellow(ko.sync.noRules));
2287
- console.log(chalk7.dim(" RULES.md\uB294 \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59\uC758 Single Source of Truth\uC785\uB2C8\uB2E4."));
2288
- console.log(chalk7.dim(" \uC0DD\uC131\uD558\uB824\uBA74: vhk init \uC2E4\uD589 \uD6C4 RULES.md\uB97C \uC791\uC131\uD558\uC138\uC694."));
2005
+ console.log(chalk6.yellow(ko.sync.noRules));
2006
+ console.log(chalk6.dim(" RULES.md\uB294 \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59\uC758 Single Source of Truth\uC785\uB2C8\uB2E4."));
2007
+ console.log(chalk6.dim(" \uC0DD\uC131\uD558\uB824\uBA74: vhk init \uC2E4\uD589 \uD6C4 RULES.md\uB97C \uC791\uC131\uD558\uC138\uC694."));
2289
2008
  console.log("");
2290
- console.log(chalk7.dim(" RULES.md \uAE30\uBCF8 \uAD6C\uC870:"));
2291
- console.log(chalk7.dim(" ## \uD504\uB85C\uC81D\uD2B8 \uC815\uCCB4\uC131"));
2292
- console.log(chalk7.dim(" ## \uAE30\uC220 \uC2A4\uD0DD"));
2293
- console.log(chalk7.dim(" ## \uCF54\uB529 \uADDC\uCE59"));
2294
- console.log(chalk7.dim(" ## \uAE30\uB85D \uADDC\uCE59"));
2295
- console.log(chalk7.dim(" ## \uCEE4\uBC0B \uCEE8\uBCA4\uC158"));
2009
+ console.log(chalk6.dim(" RULES.md \uAE30\uBCF8 \uAD6C\uC870:"));
2010
+ console.log(chalk6.dim(" ## \uD504\uB85C\uC81D\uD2B8 \uC815\uCCB4\uC131"));
2011
+ console.log(chalk6.dim(" ## \uAE30\uC220 \uC2A4\uD0DD"));
2012
+ console.log(chalk6.dim(" ## \uCF54\uB529 \uADDC\uCE59"));
2013
+ console.log(chalk6.dim(" ## \uAE30\uB85D \uADDC\uCE59"));
2014
+ console.log(chalk6.dim(" ## \uCEE4\uBC0B \uCEE8\uBCA4\uC158"));
2296
2015
  return;
2297
2016
  }
2298
2017
  const rulesContent = fs6.readFileSync(rulesPath, "utf-8");
2299
2018
  const sections = parseRulesMd(rulesContent);
2300
- console.log(chalk7.dim(` \u{1F4C4} RULES.md \uD30C\uC2F1 \uC644\uB8CC \u2014 ${sections.length}\uAC1C \uC139\uC158`));
2019
+ console.log(chalk6.dim(` \u{1F4C4} RULES.md \uD30C\uC2F1 \uC644\uB8CC \u2014 ${sections.length}\uAC1C \uC139\uC158`));
2301
2020
  const firstLine = rulesContent.split("\n")[0];
2302
2021
  const projectName = firstLine.replace(/^#\s*/, "").replace(/\s*—.*/, "").trim() || "Project";
2303
2022
  const cursorrulesPath = path7.join(cwd, ".cursorrules");
2304
2023
  fs6.writeFileSync(cursorrulesPath, toCursorrules(sections, projectName), "utf-8");
2305
- console.log(chalk7.green(` ${ko.sync.cursorrulesDone}`));
2024
+ console.log(chalk6.green(` ${ko.sync.cursorrulesDone}`));
2306
2025
  const claudePath = path7.join(cwd, "CLAUDE.md");
2307
2026
  const existingClaude = fs6.existsSync(claudePath) ? fs6.readFileSync(claudePath, "utf-8") : `# \uAE30\uB85D \uADDC\uCE59 (${projectName})
2308
2027
 
@@ -2312,11 +2031,11 @@ ${ko.sync.title}
2312
2031
  - **\uB2E4\uC74C \uC561\uC158:** __FILL__
2313
2032
  - **\uB9C8\uC9C0\uB9C9 \uC5C5\uB370\uC774\uD2B8:** ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`;
2314
2033
  fs6.writeFileSync(claudePath, toClaudeMd(sections, existingClaude), "utf-8");
2315
- console.log(chalk7.green(` ${ko.sync.claudeDone}`));
2316
- console.log(chalk7.bold.green(`
2034
+ console.log(chalk6.green(` ${ko.sync.claudeDone}`));
2035
+ console.log(chalk6.bold.green(`
2317
2036
  ${ko.sync.done}`));
2318
- console.log(chalk7.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md (\uC790\uB3D9 \uC0DD\uC131)"));
2319
- console.log(chalk7.dim(" \uADDC\uCE59 \uBCC0\uACBD\uC740 \uD56D\uC0C1 RULES.md\uC5D0\uC11C\uB9CC \uD558\uC138\uC694."));
2037
+ console.log(chalk6.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md (\uC790\uB3D9 \uC0DD\uC131)"));
2038
+ console.log(chalk6.dim(" \uADDC\uCE59 \uBCC0\uACBD\uC740 \uD56D\uC0C1 RULES.md\uC5D0\uC11C\uB9CC \uD558\uC138\uC694."));
2320
2039
  printNextStep({
2321
2040
  message: "\uADDC\uCE59 \uB3D9\uAE30\uD654 \uC644\uB8CC! \uC774\uC81C Cursor\uAC00 \uC0C8 \uADDC\uCE59\uC744 \uB530\uB985\uB2C8\uB2E4.",
2322
2041
  command: "vhk \uC810\uAC80",
@@ -2325,7 +2044,7 @@ ${ko.sync.done}`));
2325
2044
  }
2326
2045
 
2327
2046
  // src/commands/check.ts
2328
- import chalk8 from "chalk";
2047
+ import chalk7 from "chalk";
2329
2048
  import path9 from "path";
2330
2049
  import fs8 from "fs";
2331
2050
 
@@ -2484,22 +2203,22 @@ function escapeRegex(str) {
2484
2203
 
2485
2204
  // src/commands/check.ts
2486
2205
  async function check() {
2487
- console.log(chalk8.bold(`
2206
+ console.log(chalk7.bold(`
2488
2207
  ${ko.check.title}
2489
2208
  `));
2490
2209
  const cwd = process.cwd();
2491
2210
  const rulesPath = path9.join(cwd, "RULES.md");
2492
2211
  if (!fs8.existsSync(rulesPath)) {
2493
- console.log(chalk8.yellow(ko.check.noRules));
2494
- console.log(chalk8.dim(" vhk init\uC73C\uB85C \uC2DC\uC791\uD558\uAC70\uB098 RULES.md\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694."));
2212
+ console.log(chalk7.yellow(ko.check.noRules));
2213
+ console.log(chalk7.dim(" vhk init\uC73C\uB85C \uC2DC\uC791\uD558\uAC70\uB098 RULES.md\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694."));
2495
2214
  return;
2496
2215
  }
2497
2216
  const rules = parseRules(rulesPath);
2498
- console.log(chalk8.dim(` \u{1F4CF} ${rules.length}\uAC1C \uAC80\uC99D \uAC00\uB2A5\uD55C \uADDC\uCE59 \uAC10\uC9C0
2217
+ console.log(chalk7.dim(` \u{1F4CF} ${rules.length}\uAC1C \uAC80\uC99D \uAC00\uB2A5\uD55C \uADDC\uCE59 \uAC10\uC9C0
2499
2218
  `));
2500
2219
  if (rules.length === 0) {
2501
- console.log(chalk8.yellow(ko.check.noAutoRules));
2502
- console.log(chalk8.dim(" RULES.md\uC5D0 \uD30C\uC77C \uC774\uB984\xB7\uD3F4\uB354 \uADDC\uCE59\uC744 \uC801\uC73C\uBA74 \uC790\uB3D9\uC73C\uB85C \uC810\uAC80\uD574\uC694."));
2220
+ console.log(chalk7.yellow(ko.check.noAutoRules));
2221
+ console.log(chalk7.dim(" RULES.md\uC5D0 \uD30C\uC77C \uC774\uB984\xB7\uD3F4\uB354 \uADDC\uCE59\uC744 \uC801\uC73C\uBA74 \uC790\uB3D9\uC73C\uB85C \uC810\uAC80\uD574\uC694."));
2503
2222
  return;
2504
2223
  }
2505
2224
  const allViolations = [];
@@ -2507,13 +2226,13 @@ ${ko.check.title}
2507
2226
  for (const rule of rules) {
2508
2227
  const violations = rule.check(cwd);
2509
2228
  if (violations.length === 0) {
2510
- console.log(chalk8.green(` \u2705 ${rule.id}`) + chalk8.dim(` \u2014 ${rule.description.slice(0, 60)}`));
2229
+ console.log(chalk7.green(` \u2705 ${rule.id}`) + chalk7.dim(` \u2014 ${rule.description.slice(0, 60)}`));
2511
2230
  passCount++;
2512
2231
  } else {
2513
- console.log(chalk8.red(` \u274C ${rule.id}`) + chalk8.dim(` \u2014 ${violations.length}\uAC74 \uC704\uBC18`));
2232
+ console.log(chalk7.red(` \u274C ${rule.id}`) + chalk7.dim(` \u2014 ${violations.length}\uAC74 \uC704\uBC18`));
2514
2233
  violations.forEach((v) => {
2515
- const loc = v.file ? chalk8.dim(` (${v.file}${v.line ? ":" + v.line : ""})`) : "";
2516
- const icon = v.severity === "error" ? chalk8.red("\u2716") : v.severity === "warning" ? chalk8.yellow("\u26A0") : chalk8.blue("\u2139");
2234
+ const loc = v.file ? chalk7.dim(` (${v.file}${v.line ? ":" + v.line : ""})`) : "";
2235
+ const icon = v.severity === "error" ? chalk7.red("\u2716") : v.severity === "warning" ? chalk7.yellow("\u26A0") : chalk7.blue("\u2139");
2517
2236
  console.log(` ${icon} ${v.message}${loc}`);
2518
2237
  });
2519
2238
  allViolations.push(...violations);
@@ -2523,17 +2242,17 @@ ${ko.check.title}
2523
2242
  const errors = allViolations.filter((v) => v.severity === "error").length;
2524
2243
  const warnings = allViolations.filter((v) => v.severity === "warning").length;
2525
2244
  if (allViolations.length === 0) {
2526
- console.log(chalk8.green.bold(`${ko.check.allPassed} (${passCount}/${rules.length})`));
2245
+ console.log(chalk7.green.bold(`${ko.check.allPassed} (${passCount}/${rules.length})`));
2527
2246
  printNextStep({
2528
2247
  message: "\uBAA8\uB4E0 \uADDC\uCE59 \uD1B5\uACFC! \uBCF4\uC548 \uC2A4\uCE94\uB3C4 \uD574\uBCFC\uAE4C\uC694?",
2529
2248
  command: "vhk \uBCF4\uC548 scan",
2530
2249
  cursorHint: "\uBCF4\uC548 \uC2A4\uCE94 \uB3CC\uB824\uC918"
2531
2250
  });
2532
2251
  } else {
2533
- console.log(chalk8.bold(ko.check.summary));
2534
- console.log(` \uADDC\uCE59: ${chalk8.cyan(String(rules.length))}\uAC1C | \uD1B5\uACFC: ${chalk8.green(String(passCount))}\uAC1C | \uC704\uBC18: ${chalk8.red(String(allViolations.length))}\uAC74`);
2535
- if (errors > 0) console.log(` ${chalk8.red(`\u2716 ${errors}\uAC1C \uC5D0\uB7EC`)}`);
2536
- if (warnings > 0) console.log(` ${chalk8.yellow(`\u26A0 ${warnings}\uAC1C \uACBD\uACE0`)}`);
2252
+ console.log(chalk7.bold(ko.check.summary));
2253
+ console.log(` \uADDC\uCE59: ${chalk7.cyan(String(rules.length))}\uAC1C | \uD1B5\uACFC: ${chalk7.green(String(passCount))}\uAC1C | \uC704\uBC18: ${chalk7.red(String(allViolations.length))}\uAC74`);
2254
+ if (errors > 0) console.log(` ${chalk7.red(`\u2716 ${errors}\uAC1C \uC5D0\uB7EC`)}`);
2255
+ if (warnings > 0) console.log(` ${chalk7.yellow(`\u26A0 ${warnings}\uAC1C \uACBD\uACE0`)}`);
2537
2256
  printNextStep({
2538
2257
  message: "\uC704\uBC18 \uD56D\uBAA9\uC744 \uC218\uC815\uD55C \uD6C4 \uB2E4\uC2DC \uC810\uAC80\uD558\uC138\uC694.",
2539
2258
  command: "vhk \uC810\uAC80",
@@ -2546,7 +2265,7 @@ ${ko.check.title}
2546
2265
  }
2547
2266
 
2548
2267
  // src/commands/secure.ts
2549
- import chalk9 from "chalk";
2268
+ import chalk8 from "chalk";
2550
2269
  import fs11 from "fs";
2551
2270
  import path11 from "path";
2552
2271
 
@@ -2747,32 +2466,32 @@ function filterSevereFindings(findings) {
2747
2466
 
2748
2467
  // src/commands/secure.ts
2749
2468
  async function secure() {
2750
- console.log(chalk9.bold(`
2469
+ console.log(chalk8.bold(`
2751
2470
  ${ko.secure.title}
2752
2471
  `));
2753
2472
  const cwd = process.cwd();
2754
2473
  const gitignorePath = path11.join(cwd, ".gitignore");
2755
2474
  const hasGitignore = fs11.existsSync(gitignorePath);
2756
2475
  if (!hasGitignore) {
2757
- console.log(chalk9.yellow(` ${ko.secure.noGitignore}`));
2758
- console.log(chalk9.dim(" .env \uD30C\uC77C\uC774 \uCEE4\uBC0B\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"));
2476
+ console.log(chalk8.yellow(` ${ko.secure.noGitignore}`));
2477
+ console.log(chalk8.dim(" .env \uD30C\uC77C\uC774 \uCEE4\uBC0B\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"));
2759
2478
  } else {
2760
2479
  const gitignoreContent = fs11.readFileSync(gitignorePath, "utf-8");
2761
2480
  if (!gitignoreContent.includes(".env")) {
2762
- console.log(chalk9.yellow(` ${ko.secure.noEnvInGitignore}`));
2763
- console.log(chalk9.dim(" \uCD94\uAC00\uB97C \uAD8C\uC7A5\uD569\uB2C8\uB2E4.\n"));
2481
+ console.log(chalk8.yellow(` ${ko.secure.noEnvInGitignore}`));
2482
+ console.log(chalk8.dim(" \uCD94\uAC00\uB97C \uAD8C\uC7A5\uD569\uB2C8\uB2E4.\n"));
2764
2483
  }
2765
2484
  }
2766
- console.log(chalk9.dim(` ${ko.secure.scanning}
2485
+ console.log(chalk8.dim(` ${ko.secure.scanning}
2767
2486
  `));
2768
2487
  const { findings, scannedFiles, truncated } = scanProjectForSecrets(cwd);
2769
- console.log(chalk9.dim(` \u{1F4C2} ${scannedFiles}\uAC1C \uD30C\uC77C \uC2A4\uCE94 \uC644\uB8CC (lock\xB7node_modules\xB7>${MAX_SCAN_FILE_BYTES / 1024}KB \uC81C\uC678)`));
2488
+ console.log(chalk8.dim(` \u{1F4C2} ${scannedFiles}\uAC1C \uD30C\uC77C \uC2A4\uCE94 \uC644\uB8CC (lock\xB7node_modules\xB7>${MAX_SCAN_FILE_BYTES / 1024}KB \uC81C\uC678)`));
2770
2489
  if (truncated) {
2771
- console.log(chalk9.yellow(` \u26A0\uFE0F \uACB0\uACFC ${MAX_SECRET_FINDINGS}\uAC74\uC5D0\uC11C \uCD9C\uB825\uC744 \uC81C\uD55C\uD588\uC2B5\uB2C8\uB2E4. lock \uD30C\uC77C \uB4F1\uC740 \uC790\uB3D9 \uC81C\uC678\uB429\uB2C8\uB2E4.`));
2490
+ console.log(chalk8.yellow(` \u26A0\uFE0F \uACB0\uACFC ${MAX_SECRET_FINDINGS}\uAC74\uC5D0\uC11C \uCD9C\uB825\uC744 \uC81C\uD55C\uD588\uC2B5\uB2C8\uB2E4. lock \uD30C\uC77C \uB4F1\uC740 \uC790\uB3D9 \uC81C\uC678\uB429\uB2C8\uB2E4.`));
2772
2491
  }
2773
2492
  console.log("");
2774
2493
  if (findings.length === 0) {
2775
- console.log(chalk9.green.bold(` ${ko.secure.clean}`));
2494
+ console.log(chalk8.green.bold(` ${ko.secure.clean}`));
2776
2495
  printNextStep({
2777
2496
  message: "\uBCF4\uC548 \uC774\uC0C1 \uC5C6\uC74C! \uAE68\uB057\uD569\uB2C8\uB2E4.",
2778
2497
  command: "vhk \uC815\uB9AC",
@@ -2784,43 +2503,43 @@ ${ko.secure.title}
2784
2503
  const high = findings.filter((f) => f.severity === "high");
2785
2504
  const medium = findings.filter((f) => f.severity === "medium");
2786
2505
  if (critical.length > 0) {
2787
- console.log(chalk9.red.bold(` \u{1F6A8} CRITICAL \u2014 ${critical.length}\uAC74`));
2506
+ console.log(chalk8.red.bold(` \u{1F6A8} CRITICAL \u2014 ${critical.length}\uAC74`));
2788
2507
  critical.forEach((f) => {
2789
- console.log(chalk9.red(` \u2716 ${f.patternName}`));
2790
- console.log(chalk9.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2508
+ console.log(chalk8.red(` \u2716 ${f.patternName}`));
2509
+ console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2791
2510
  });
2792
2511
  console.log("");
2793
2512
  }
2794
2513
  if (high.length > 0) {
2795
- console.log(chalk9.yellow.bold(` \u26A0\uFE0F HIGH \u2014 ${high.length}\uAC74`));
2514
+ console.log(chalk8.yellow.bold(` \u26A0\uFE0F HIGH \u2014 ${high.length}\uAC74`));
2796
2515
  high.forEach((f) => {
2797
- console.log(chalk9.yellow(` \u26A0 ${f.patternName}`));
2798
- console.log(chalk9.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2516
+ console.log(chalk8.yellow(` \u26A0 ${f.patternName}`));
2517
+ console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2799
2518
  });
2800
2519
  console.log("");
2801
2520
  }
2802
2521
  if (medium.length > 0) {
2803
- console.log(chalk9.blue.bold(` \u2139 MEDIUM \u2014 ${medium.length}\uAC74`));
2522
+ console.log(chalk8.blue.bold(` \u2139 MEDIUM \u2014 ${medium.length}\uAC74`));
2804
2523
  medium.forEach((f) => {
2805
- console.log(chalk9.blue(` \u2139 ${f.patternName}`));
2806
- console.log(chalk9.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2524
+ console.log(chalk8.blue(` \u2139 ${f.patternName}`));
2525
+ console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2807
2526
  });
2808
2527
  console.log("");
2809
2528
  }
2810
- console.log(chalk9.bold(` ${ko.secure.summary}`));
2811
- console.log(` \uCD1D ${chalk9.red(String(findings.length))}\uAC74 \uAC10\uC9C0 | CRITICAL: ${critical.length} | HIGH: ${high.length} | MEDIUM: ${medium.length}`);
2529
+ console.log(chalk8.bold(` ${ko.secure.summary}`));
2530
+ console.log(` \uCD1D ${chalk8.red(String(findings.length))}\uAC74 \uAC10\uC9C0 | CRITICAL: ${critical.length} | HIGH: ${high.length} | MEDIUM: ${medium.length}`);
2812
2531
  console.log("");
2813
- console.log(chalk9.dim(" \u{1F4A1} \uC870\uCE58 \uBC29\uBC95:"));
2814
- console.log(chalk9.dim(" 1. \uD574\uB2F9 \uD30C\uC77C\uC5D0\uC11C \uC2DC\uD06C\uB9BF\uC744 \uC81C\uAC70\uD558\uACE0 \uD658\uACBD\uBCC0\uC218\uB85C \uC774\uB3D9"));
2815
- console.log(chalk9.dim(" 2. git history\uC5D0\uC11C\uB3C4 \uC81C\uAC70: git filter-branch \uB610\uB294 BFG Repo-Cleaner"));
2816
- console.log(chalk9.dim(" 3. \uC720\uCD9C\uB41C \uD0A4\uB294 \uC989\uC2DC \uD3D0\uAE30\uD558\uACE0 \uC7AC\uBC1C\uAE09\n"));
2532
+ console.log(chalk8.dim(" \u{1F4A1} \uC870\uCE58 \uBC29\uBC95:"));
2533
+ console.log(chalk8.dim(" 1. \uD574\uB2F9 \uD30C\uC77C\uC5D0\uC11C \uC2DC\uD06C\uB9BF\uC744 \uC81C\uAC70\uD558\uACE0 \uD658\uACBD\uBCC0\uC218\uB85C \uC774\uB3D9"));
2534
+ console.log(chalk8.dim(" 2. git history\uC5D0\uC11C\uB3C4 \uC81C\uAC70: git filter-branch \uB610\uB294 BFG Repo-Cleaner"));
2535
+ console.log(chalk8.dim(" 3. \uC720\uCD9C\uB41C \uD0A4\uB294 \uC989\uC2DC \uD3D0\uAE30\uD558\uACE0 \uC7AC\uBC1C\uAE09\n"));
2817
2536
  if (critical.length > 0 || high.length > 0) {
2818
2537
  process.exitCode = 1;
2819
2538
  }
2820
2539
  }
2821
2540
 
2822
2541
  // src/commands/doctor.ts
2823
- import chalk10 from "chalk";
2542
+ import chalk9 from "chalk";
2824
2543
  import { execSync } from "child_process";
2825
2544
  import fs12 from "fs";
2826
2545
  import path12 from "path";
@@ -2873,7 +2592,7 @@ function compareSemver(a, b) {
2873
2592
  return a3 - b3;
2874
2593
  }
2875
2594
  async function doctor() {
2876
- console.log(chalk10.bold(`
2595
+ console.log(chalk9.bold(`
2877
2596
  ${ko.doctor.title}
2878
2597
  `));
2879
2598
  const checks = [
@@ -2885,30 +2604,30 @@ ${ko.doctor.title}
2885
2604
  let allOk = true;
2886
2605
  for (const check2 of checks) {
2887
2606
  if (check2.ok) {
2888
- console.log(chalk10.green(` \u2705 ${check2.name}`) + chalk10.dim(` \u2014 ${check2.version}`));
2607
+ console.log(chalk9.green(` \u2705 ${check2.name}`) + chalk9.dim(` \u2014 ${check2.version}`));
2889
2608
  } else {
2890
- console.log(chalk10.red(` \u274C ${check2.name} \uC5C6\uC74C`));
2891
- console.log(chalk10.dim(` \u2192 ${check2.hint}`));
2609
+ console.log(chalk9.red(` \u274C ${check2.name} \uC5C6\uC74C`));
2610
+ console.log(chalk9.dim(` \u2192 ${check2.hint}`));
2892
2611
  allOk = false;
2893
2612
  }
2894
2613
  }
2895
2614
  console.log("");
2896
2615
  const vhkVersion = getVhkVersion();
2897
2616
  if (vhkVersion) {
2898
- console.log(chalk10.green(" \u2705 VHK") + chalk10.dim(` \u2014 v${vhkVersion}`));
2617
+ console.log(chalk9.green(" \u2705 VHK") + chalk9.dim(` \u2014 v${vhkVersion}`));
2899
2618
  } else {
2900
- console.log(chalk10.green(" \u2705 VHK") + chalk10.dim(" \u2014 \uC124\uCE58\uB428"));
2619
+ console.log(chalk9.green(" \u2705 VHK") + chalk9.dim(" \u2014 \uC124\uCE58\uB428"));
2901
2620
  }
2902
2621
  if (vhkVersion) {
2903
2622
  const latest = fetchLatestNpmVersion("@byh3071/vhk");
2904
2623
  if (latest && compareSemver(latest, vhkVersion) > 0) {
2905
- console.log(chalk10.yellow(` ${ko.doctor.updateAvailable(latest)}`));
2624
+ console.log(chalk9.yellow(` ${ko.doctor.updateAvailable(latest)}`));
2906
2625
  } else if (latest) {
2907
- console.log(chalk10.dim(` ${ko.doctor.updateCurrent}`));
2626
+ console.log(chalk9.dim(` ${ko.doctor.updateCurrent}`));
2908
2627
  }
2909
2628
  }
2910
2629
  console.log("");
2911
- console.log(chalk10.bold(` ${ko.doctor.projectFiles}`));
2630
+ console.log(chalk9.bold(` ${ko.doctor.projectFiles}`));
2912
2631
  const cwd = process.cwd();
2913
2632
  const projectFiles = [
2914
2633
  { name: "RULES.md", hint: "vhk init\uC73C\uB85C \uC0DD\uC131 \uAC00\uB2A5" },
@@ -2920,30 +2639,30 @@ ${ko.doctor.title}
2920
2639
  for (const file of projectFiles) {
2921
2640
  const exists = fs12.existsSync(path12.join(cwd, file.name));
2922
2641
  if (exists) {
2923
- console.log(chalk10.green(` \u2705 ${file.name}`));
2642
+ console.log(chalk9.green(` \u2705 ${file.name}`));
2924
2643
  if (file.name === ".env") {
2925
2644
  const gitignorePath = path12.join(cwd, ".gitignore");
2926
2645
  if (fs12.existsSync(gitignorePath)) {
2927
2646
  const gitignore = fs12.readFileSync(gitignorePath, "utf-8");
2928
2647
  if (!gitignore.includes(".env")) {
2929
- console.log(chalk10.yellow(` ${ko.doctor.envNotIgnored}`));
2648
+ console.log(chalk9.yellow(` ${ko.doctor.envNotIgnored}`));
2930
2649
  }
2931
2650
  }
2932
2651
  }
2933
2652
  } else {
2934
- console.log(chalk10.dim(` \u2B1A ${file.name}`) + chalk10.dim(` \u2014 ${file.hint}`));
2653
+ console.log(chalk9.dim(` \u2B1A ${file.name}`) + chalk9.dim(` \u2014 ${file.hint}`));
2935
2654
  }
2936
2655
  }
2937
2656
  console.log("");
2938
2657
  if (allOk) {
2939
- console.log(chalk10.green.bold(` ${ko.doctor.allOk}`));
2658
+ console.log(chalk9.green.bold(` ${ko.doctor.allOk}`));
2940
2659
  printNextStep({
2941
2660
  message: ko.doctor.nextOkMessage,
2942
2661
  command: "vhk \uC2DC\uC791",
2943
2662
  cursorHint: "\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uC5B4\uC918"
2944
2663
  });
2945
2664
  } else {
2946
- console.log(chalk10.yellow.bold(` ${ko.doctor.missing} ${ko.doctor.missingHint}`));
2665
+ console.log(chalk9.yellow.bold(` ${ko.doctor.missing} ${ko.doctor.missingHint}`));
2947
2666
  printNextStep({
2948
2667
  message: ko.doctor.nextRetryMessage,
2949
2668
  command: "vhk doctor",
@@ -2954,7 +2673,7 @@ ${ko.doctor.title}
2954
2673
  }
2955
2674
 
2956
2675
  // src/commands/ship.ts
2957
- import chalk11 from "chalk";
2676
+ import chalk10 from "chalk";
2958
2677
  import inquirer4 from "inquirer";
2959
2678
  import fs13 from "fs";
2960
2679
  import path13 from "path";
@@ -2993,29 +2712,29 @@ function updateChangelogUnreleased(cwd, version, date) {
2993
2712
  return { status: "updated", version };
2994
2713
  }
2995
2714
  async function ship() {
2996
- console.log(chalk11.bold(`
2715
+ console.log(chalk10.bold(`
2997
2716
  ${ko.ship.title}
2998
2717
  `));
2999
2718
  const cwd = process.cwd();
3000
- console.log(chalk11.cyan.bold(` ${ko.ship.checklist}
2719
+ console.log(chalk10.cyan.bold(` ${ko.ship.checklist}
3001
2720
  `));
3002
2721
  const { passed } = await inquirer4.prompt([{
3003
2722
  type: "checkbox",
3004
2723
  name: "passed",
3005
2724
  message: ko.ship.checkboxPrompt,
3006
2725
  choices: CHECKLIST.map((c) => ({
3007
- name: `${ko.ship[c.questionKey]} ${chalk11.dim(`(${ko.ship[c.hintKey]})`)}`,
2726
+ name: `${ko.ship[c.questionKey]} ${chalk10.dim(`(${ko.ship[c.hintKey]})`)}`,
3008
2727
  value: c.id
3009
2728
  }))
3010
2729
  }]);
3011
2730
  const allPassed = passed.length === CHECKLIST.length;
3012
2731
  const skipped = CHECKLIST.filter((c) => !passed.includes(c.id));
3013
2732
  if (!allPassed) {
3014
- console.log(chalk11.yellow(`
2733
+ console.log(chalk10.yellow(`
3015
2734
  ${ko.ship.incompleteHeader}`));
3016
2735
  skipped.forEach((s) => {
3017
- console.log(chalk11.yellow(` \u2022 ${ko.ship[s.questionKey]}`));
3018
- console.log(chalk11.dim(` \u2192 ${ko.ship[s.hintKey]}`));
2736
+ console.log(chalk10.yellow(` \u2022 ${ko.ship[s.questionKey]}`));
2737
+ console.log(chalk10.dim(` \u2192 ${ko.ship[s.hintKey]}`));
3019
2738
  });
3020
2739
  const { proceed } = await inquirer4.prompt([{
3021
2740
  type: "confirm",
@@ -3032,13 +2751,13 @@ ${ko.ship.title}
3032
2751
  return;
3033
2752
  }
3034
2753
  } else {
3035
- console.log(chalk11.green(`
2754
+ console.log(chalk10.green(`
3036
2755
  ${ko.ship.allPassed}
3037
2756
  `));
3038
2757
  }
3039
- console.log(chalk11.cyan.bold(` ${ko.ship.retro}
2758
+ console.log(chalk10.cyan.bold(` ${ko.ship.retro}
3040
2759
  `));
3041
- console.log(chalk11.dim(` ${ko.ship.versionHint}`));
2760
+ console.log(chalk10.dim(` ${ko.ship.versionHint}`));
3042
2761
  const retro = await inquirer4.prompt([
3043
2762
  { type: "input", name: "version", message: ko.ship.versionPrompt },
3044
2763
  { type: "input", name: "whatWentWell", message: ko.ship.questionWell },
@@ -3081,7 +2800,7 @@ ${ko.ship.title}
3081
2800
  `*Generated by \`vhk ship\` at ${(/* @__PURE__ */ new Date()).toISOString()}*`
3082
2801
  ].join("\n");
3083
2802
  fs13.writeFileSync(filePath, content, "utf-8");
3084
- console.log(chalk11.green(`
2803
+ console.log(chalk10.green(`
3085
2804
  ${ko.ship.buildLogDone(path13.relative(cwd, filePath))}`));
3086
2805
  const changelogResult = updateChangelogUnreleased(cwd, versionSlug, today);
3087
2806
  if (changelogResult.status === "updated") {
@@ -3101,7 +2820,7 @@ ${ko.ship.title}
3101
2820
 
3102
2821
  // src/commands/save.ts
3103
2822
  import { execFileSync as execFileSync2 } from "child_process";
3104
- import chalk12 from "chalk";
2823
+ import chalk11 from "chalk";
3105
2824
  import ora from "ora";
3106
2825
  import inquirer5 from "inquirer";
3107
2826
 
@@ -3172,29 +2891,29 @@ function statusIcon(code) {
3172
2891
  return "\u{1F4C4}";
3173
2892
  }
3174
2893
  async function save() {
3175
- console.log(chalk12.bold(`
2894
+ console.log(chalk11.bold(`
3176
2895
  \u{1F4BE} ${t("save.title")}`));
3177
- console.log(chalk12.gray("\u2500".repeat(40)));
2896
+ console.log(chalk11.gray("\u2500".repeat(40)));
3178
2897
  let gitRoot;
3179
2898
  try {
3180
2899
  execFileSync2("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3181
2900
  gitRoot = getGitRoot();
3182
2901
  } catch {
3183
- console.log(chalk12.red(`\u274C ${t("save.notGitRepo")}`));
2902
+ console.log(chalk11.red(`\u274C ${t("save.notGitRepo")}`));
3184
2903
  return;
3185
2904
  }
3186
- console.log(chalk12.cyan(`
2905
+ console.log(chalk11.cyan(`
3187
2906
  \u{1F512} ${t("save.securityWarnHeader")}`));
3188
2907
  printSecurityWarnings(gitRoot);
3189
2908
  const severe = filterSevereFindings(scanProjectForSecrets(gitRoot).findings);
3190
2909
  if (severe.length > 0) {
3191
- console.log(chalk12.red(`
2910
+ console.log(chalk11.red(`
3192
2911
  \u26A0\uFE0F ${t("save.secretsFound", severe.length)}`));
3193
2912
  severe.slice(0, 5).forEach((f) => {
3194
- console.log(chalk12.dim(` ${f.file}:${f.line} \u2014 ${f.patternName}`));
2913
+ console.log(chalk11.dim(` ${f.file}:${f.line} \u2014 ${f.patternName}`));
3195
2914
  });
3196
2915
  if (severe.length > 5) {
3197
- console.log(chalk12.dim(` ... \uC678 ${severe.length - 5}\uAC74 (vhk \uBCF4\uC548 scan)`));
2916
+ console.log(chalk11.dim(` ... \uC678 ${severe.length - 5}\uAC74 (vhk \uBCF4\uC548 scan)`));
3198
2917
  }
3199
2918
  const { proceed } = await inquirer5.prompt([{
3200
2919
  type: "confirm",
@@ -3203,16 +2922,16 @@ async function save() {
3203
2922
  default: false
3204
2923
  }]);
3205
2924
  if (!proceed) {
3206
- console.log(chalk12.gray(t("save.cancelled")));
2925
+ console.log(chalk11.gray(t("save.cancelled")));
3207
2926
  return;
3208
2927
  }
3209
2928
  }
3210
2929
  const lines = parsePorcelainLines(gitOut(["status", "--porcelain"], gitRoot));
3211
2930
  if (lines.length === 0) {
3212
- console.log(chalk12.yellow(`\u{1F4ED} ${t("save.noChanges")}`));
2931
+ console.log(chalk11.yellow(`\u{1F4ED} ${t("save.noChanges")}`));
3213
2932
  return;
3214
2933
  }
3215
- console.log(chalk12.cyan(`
2934
+ console.log(chalk11.cyan(`
3216
2935
  \u{1F4CB} ${t("save.filesHeader", lines.length)}`));
3217
2936
  lines.forEach((line) => {
3218
2937
  const code = line.substring(0, 2);
@@ -3234,34 +2953,34 @@ async function save() {
3234
2953
  spinner.text = t("save.pushing");
3235
2954
  if (!hasGitRemote(gitRoot)) {
3236
2955
  spinner.succeed(t("save.successLocal"));
3237
- console.log(chalk12.yellow(` \u{1F4A1} ${t("save.noRemote")}`));
2956
+ console.log(chalk11.yellow(` \u{1F4A1} ${t("save.noRemote")}`));
3238
2957
  } else {
3239
2958
  try {
3240
2959
  gitRun(["push"], gitRoot);
3241
2960
  spinner.succeed(t("save.successWithPush"));
3242
2961
  } catch (pushErr) {
3243
2962
  spinner.fail(t("save.pushFailed"));
3244
- console.log(chalk12.red(getExecErrorMessage(pushErr)));
3245
- console.log(chalk12.yellow(`
2963
+ console.log(chalk11.red(getExecErrorMessage(pushErr)));
2964
+ console.log(chalk11.yellow(`
3246
2965
  \u{1F4A1} ${t("save.commitOkPushFailed")}`));
3247
2966
  process.exitCode = 1;
3248
2967
  }
3249
2968
  }
3250
2969
  if (process.exitCode !== 1) {
3251
- console.log(chalk12.green(`
2970
+ console.log(chalk11.green(`
3252
2971
  \u2705 ${t("save.done", lines.length)}`));
3253
2972
  } else {
3254
- console.log(chalk12.green(`
2973
+ console.log(chalk11.green(`
3255
2974
  \u2705 ${t("save.doneLocalOnly", lines.length)}`));
3256
2975
  }
3257
2976
  } catch (err) {
3258
2977
  spinner.fail(t("save.failed"));
3259
- console.log(chalk12.red(getExecErrorMessage(err)));
2978
+ console.log(chalk11.red(getExecErrorMessage(err)));
3260
2979
  if (didAdd) {
3261
2980
  try {
3262
2981
  const staged = gitOut(["diff", "--cached", "--stat"], gitRoot).trim();
3263
2982
  if (staged) {
3264
- console.log(chalk12.yellow(`
2983
+ console.log(chalk11.yellow(`
3265
2984
  \u{1F4A1} ${t("save.stagedAfterFail")}`));
3266
2985
  }
3267
2986
  } catch {
@@ -3273,7 +2992,7 @@ async function save() {
3273
2992
 
3274
2993
  // src/commands/undo.ts
3275
2994
  import { execFileSync as execFileSync3 } from "child_process";
3276
- import chalk13 from "chalk";
2995
+ import chalk12 from "chalk";
3277
2996
  import inquirer6 from "inquirer";
3278
2997
  function parseRecentCommits(logOutput) {
3279
2998
  return logOutput.split("\n").map((l) => l.trim()).filter(Boolean);
@@ -3297,30 +3016,30 @@ function isUndoRisky(undoCount, unpushedCount, hasRemote) {
3297
3016
  return false;
3298
3017
  }
3299
3018
  async function undo() {
3300
- console.log(chalk13.bold(`
3019
+ console.log(chalk12.bold(`
3301
3020
  \u23EA ${t("undo.title")}`));
3302
- console.log(chalk13.gray("\u2500".repeat(40)));
3021
+ console.log(chalk12.gray("\u2500".repeat(40)));
3303
3022
  let gitRoot;
3304
3023
  try {
3305
3024
  execFileSync3("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3306
3025
  gitRoot = getGitRoot();
3307
3026
  } catch {
3308
- console.log(chalk13.red(`\u274C ${t("undo.notGitRepo")}`));
3027
+ console.log(chalk12.red(`\u274C ${t("undo.notGitRepo")}`));
3309
3028
  return;
3310
3029
  }
3311
3030
  let logOutput;
3312
3031
  try {
3313
3032
  logOutput = gitOut(["log", "--oneline", "-5"], gitRoot).trim();
3314
3033
  } catch {
3315
- console.log(chalk13.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3034
+ console.log(chalk12.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3316
3035
  return;
3317
3036
  }
3318
3037
  const commits = parseRecentCommits(logOutput);
3319
3038
  if (commits.length === 0) {
3320
- console.log(chalk13.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3039
+ console.log(chalk12.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3321
3040
  return;
3322
3041
  }
3323
- console.log(chalk13.cyan(`
3042
+ console.log(chalk12.cyan(`
3324
3043
  ${t("undo.recentHeader")}`));
3325
3044
  commits.forEach((c, i) => {
3326
3045
  console.log(` ${i === 0 ? "\u{1F449}" : " "} ${c}`);
@@ -3337,7 +3056,7 @@ ${t("undo.recentHeader")}`));
3337
3056
  const undoCount = Math.min(Math.max(1, count || 1), maxUndo);
3338
3057
  const headCount = countLocalCommits(gitRoot);
3339
3058
  if (undoCount >= headCount) {
3340
- console.log(chalk13.yellow(`
3059
+ console.log(chalk12.yellow(`
3341
3060
  \u{1F4ED} ${t("undo.rootCommit")}`));
3342
3061
  return;
3343
3062
  }
@@ -3346,10 +3065,10 @@ ${t("undo.recentHeader")}`));
3346
3065
  const risky = isUndoRisky(undoCount, unpushed, remote);
3347
3066
  if (risky) {
3348
3067
  if (unpushed < 0) {
3349
- console.log(chalk13.red(`
3068
+ console.log(chalk12.red(`
3350
3069
  \u26A0\uFE0F ${t("undo.noUpstreamWarning")}`));
3351
3070
  } else {
3352
- console.log(chalk13.red(`
3071
+ console.log(chalk12.red(`
3353
3072
  \u26A0\uFE0F ${t("undo.alreadyPushed")}`));
3354
3073
  }
3355
3074
  }
@@ -3360,22 +3079,22 @@ ${t("undo.recentHeader")}`));
3360
3079
  default: false
3361
3080
  }]);
3362
3081
  if (!confirm) {
3363
- console.log(chalk13.gray(t("undo.cancelled")));
3082
+ console.log(chalk12.gray(t("undo.cancelled")));
3364
3083
  return;
3365
3084
  }
3366
3085
  try {
3367
3086
  gitRun(["reset", "--soft", `HEAD~${undoCount}`], gitRoot);
3368
- console.log(chalk13.green(`
3087
+ console.log(chalk12.green(`
3369
3088
  \u2705 ${t("undo.success")}`));
3370
- console.log(chalk13.gray(` \u{1F4A1} ${t("undo.stagedHint")}`));
3089
+ console.log(chalk12.gray(` \u{1F4A1} ${t("undo.stagedHint")}`));
3371
3090
  if (risky) {
3372
- console.log(chalk13.yellow(`
3091
+ console.log(chalk12.yellow(`
3373
3092
  \u{1F4A1} ${t("undo.forcePushHint")}`));
3374
3093
  }
3375
3094
  } catch (err) {
3376
- console.log(chalk13.red(`\u274C ${t("undo.failed")}`));
3095
+ console.log(chalk12.red(`\u274C ${t("undo.failed")}`));
3377
3096
  const msg = err instanceof Error ? err.message : String(err);
3378
- console.log(chalk13.red(msg));
3097
+ console.log(chalk12.red(msg));
3379
3098
  process.exitCode = 1;
3380
3099
  }
3381
3100
  }
@@ -3384,7 +3103,7 @@ ${t("undo.recentHeader")}`));
3384
3103
  import { execFileSync as execFileSync4 } from "child_process";
3385
3104
  import fs15 from "fs";
3386
3105
  import path14 from "path";
3387
- import chalk14 from "chalk";
3106
+ import chalk13 from "chalk";
3388
3107
 
3389
3108
  // src/lib/read-json.ts
3390
3109
  import fs14 from "fs";
@@ -3456,15 +3175,15 @@ function getSyncCounts(gitRoot) {
3456
3175
  }
3457
3176
  }
3458
3177
  async function status() {
3459
- console.log(chalk14.bold(`
3178
+ console.log(chalk13.bold(`
3460
3179
  \u{1F4CA} ${t("status.title")}`));
3461
- console.log(chalk14.gray("\u2500".repeat(40)));
3180
+ console.log(chalk13.gray("\u2500".repeat(40)));
3462
3181
  let gitRoot;
3463
3182
  try {
3464
3183
  execFileSync4("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3465
3184
  gitRoot = getGitRoot();
3466
3185
  } catch {
3467
- console.log(chalk14.red(`\u274C ${t("status.notGitRepo")}`));
3186
+ console.log(chalk13.red(`\u274C ${t("status.notGitRepo")}`));
3468
3187
  return;
3469
3188
  }
3470
3189
  let branch;
@@ -3483,36 +3202,36 @@ async function status() {
3483
3202
  commits = [];
3484
3203
  }
3485
3204
  const pkg = readProjectPackage();
3486
- console.log(chalk14.cyan(`
3487
- \u{1F33F} ${t("status.branch")}`) + chalk14.white(` ${branch}`));
3205
+ console.log(chalk13.cyan(`
3206
+ \u{1F33F} ${t("status.branch")}`) + chalk13.white(` ${branch}`));
3488
3207
  console.log(
3489
- chalk14.cyan(`\u{1F4C1} ${t("status.changes")}`) + chalk14.white(
3208
+ chalk13.cyan(`\u{1F4C1} ${t("status.changes")}`) + chalk13.white(
3490
3209
  ` staged ${counts.staged} \xB7 unstaged ${counts.unstaged} \xB7 untracked ${counts.untracked}`
3491
3210
  )
3492
3211
  );
3493
- console.log(chalk14.cyan(`
3212
+ console.log(chalk13.cyan(`
3494
3213
  \u{1F4CB} ${t("status.recentCommits")}`));
3495
3214
  if (commits.length === 0) {
3496
- console.log(chalk14.dim(` ${t("status.noCommits")}`));
3215
+ console.log(chalk13.dim(` ${t("status.noCommits")}`));
3497
3216
  } else {
3498
- commits.forEach((c) => console.log(` ${chalk14.dim("\u2022")} ${c}`));
3217
+ commits.forEach((c) => console.log(` ${chalk13.dim("\u2022")} ${c}`));
3499
3218
  }
3500
3219
  console.log(
3501
- chalk14.cyan(`
3502
- \u{1F504} ${t("status.remote")}`) + chalk14.white(` ${formatSyncLabel(sync2)}`)
3220
+ chalk13.cyan(`
3221
+ \u{1F504} ${t("status.remote")}`) + chalk13.white(` ${formatSyncLabel(sync2)}`)
3503
3222
  );
3504
- console.log(chalk14.gray("\n" + "\u2500".repeat(40)));
3223
+ console.log(chalk13.gray("\n" + "\u2500".repeat(40)));
3505
3224
  if (pkg) {
3506
- console.log(chalk14.cyan(`\u{1F4E6} ${t("status.package")}`) + chalk14.white(` ${pkg.name} v${pkg.version}`));
3225
+ console.log(chalk13.cyan(`\u{1F4E6} ${t("status.package")}`) + chalk13.white(` ${pkg.name} v${pkg.version}`));
3507
3226
  } else {
3508
- console.log(chalk14.dim(`\u{1F4E6} ${t("status.noPackage")}`));
3227
+ console.log(chalk13.dim(`\u{1F4E6} ${t("status.noPackage")}`));
3509
3228
  }
3510
3229
  console.log("");
3511
3230
  }
3512
3231
 
3513
3232
  // src/commands/diff.ts
3514
3233
  import { execFileSync as execFileSync5, execSync as execSync2 } from "child_process";
3515
- import chalk15 from "chalk";
3234
+ import chalk14 from "chalk";
3516
3235
  function gitOut2(args) {
3517
3236
  try {
3518
3237
  return execFileSync5("git", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
@@ -3552,53 +3271,53 @@ function summarizeNumstat(numstat) {
3552
3271
  return { fileCount, totalAdd, totalDel };
3553
3272
  }
3554
3273
  function printFile(f) {
3555
- const adds = f.additions > 0 ? chalk15.green(`+${f.additions}`) : "";
3556
- const dels = f.deletions > 0 ? chalk15.red(`-${f.deletions}`) : "";
3274
+ const adds = f.additions > 0 ? chalk14.green(`+${f.additions}`) : "";
3275
+ const dels = f.deletions > 0 ? chalk14.red(`-${f.deletions}`) : "";
3557
3276
  const change = [adds, dels].filter(Boolean).join(" ");
3558
3277
  console.log(` ${f.name} ${change}`);
3559
3278
  }
3560
3279
  async function diff() {
3561
- console.log(chalk15.bold(`
3280
+ console.log(chalk14.bold(`
3562
3281
  \u{1F50D} ${t("diff.title")}`));
3563
- console.log(chalk15.gray("\u2500".repeat(40)));
3282
+ console.log(chalk14.gray("\u2500".repeat(40)));
3564
3283
  try {
3565
3284
  execSync2("git rev-parse --is-inside-work-tree", { stdio: "pipe" });
3566
3285
  } catch {
3567
- console.log(chalk15.red(`\u274C ${t("diff.notGitRepo")}`));
3286
+ console.log(chalk14.red(`\u274C ${t("diff.notGitRepo")}`));
3568
3287
  return;
3569
3288
  }
3570
3289
  const unstaged = gitOut2(["diff", "--stat"]);
3571
3290
  const staged = gitOut2(["diff", "--cached", "--stat"]);
3572
3291
  const untracked = gitOut2(["ls-files", "--others", "--exclude-standard"]);
3573
3292
  if (!unstaged && !staged && !untracked) {
3574
- console.log(chalk15.green(`
3293
+ console.log(chalk14.green(`
3575
3294
  \u2705 ${t("diff.noChanges")}`));
3576
3295
  return;
3577
3296
  }
3578
3297
  if (staged) {
3579
- console.log(chalk15.cyan(`
3298
+ console.log(chalk14.cyan(`
3580
3299
  ${t("diff.stagedHeader")}`));
3581
3300
  parseDiffStat(staged).forEach((f) => printFile(f));
3582
3301
  }
3583
3302
  if (unstaged) {
3584
- console.log(chalk15.cyan(`
3303
+ console.log(chalk14.cyan(`
3585
3304
  ${t("diff.unstagedHeader")}`));
3586
3305
  parseDiffStat(unstaged).forEach((f) => printFile(f));
3587
3306
  }
3588
3307
  if (untracked) {
3589
3308
  const files = untracked.split("\n").filter(Boolean);
3590
- console.log(chalk15.cyan(`
3309
+ console.log(chalk14.cyan(`
3591
3310
  ${t("diff.untrackedHeader", files.length)}`));
3592
- files.forEach((f) => console.log(` ${chalk15.green("+")} ${f}`));
3311
+ files.forEach((f) => console.log(` ${chalk14.green("+")} ${f}`));
3593
3312
  }
3594
3313
  const numstat = gitOut2(["diff", "--numstat", "HEAD"]);
3595
3314
  if (numstat) {
3596
3315
  const { fileCount, totalAdd, totalDel } = summarizeNumstat(numstat);
3597
- console.log(chalk15.cyan(`
3316
+ console.log(chalk14.cyan(`
3598
3317
  ${t("diff.summaryHeader")}`));
3599
3318
  console.log(` ${t("diff.filesLine", fileCount)}`);
3600
- console.log(` \uCD94\uAC00: ${chalk15.green(`+${totalAdd}`)}\uC904`);
3601
- console.log(` \uC0AD\uC81C: ${chalk15.red(`-${totalDel}`)}\uC904`);
3319
+ console.log(` \uCD94\uAC00: ${chalk14.green(`+${totalAdd}`)}\uC904`);
3320
+ console.log(` \uC0AD\uC81C: ${chalk14.red(`-${totalDel}`)}\uC904`);
3602
3321
  }
3603
3322
  console.log("");
3604
3323
  }
@@ -3607,7 +3326,7 @@ ${t("diff.summaryHeader")}`));
3607
3326
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3608
3327
  import { join } from "path";
3609
3328
  import { fileURLToPath as fileURLToPath2 } from "url";
3610
- import chalk16 from "chalk";
3329
+ import chalk15 from "chalk";
3611
3330
  function resolveVhkMcpPath() {
3612
3331
  try {
3613
3332
  const pkgPath = join(process.cwd(), "package.json");
@@ -3627,8 +3346,8 @@ function resolveVhkMcpPath() {
3627
3346
  return join(process.cwd(), "node_modules", "@byh3071", "vhk", "dist", "mcp", "index.js");
3628
3347
  }
3629
3348
  async function mcpInit() {
3630
- console.log(chalk16.bold("\n\u{1F50C} " + t("mcp.initTitle")));
3631
- console.log(chalk16.gray("\u2500".repeat(40)));
3349
+ console.log(chalk15.bold("\n\u{1F50C} " + t("mcp.initTitle")));
3350
+ console.log(chalk15.gray("\u2500".repeat(40)));
3632
3351
  const cursorDir = join(process.cwd(), ".cursor");
3633
3352
  if (!existsSync(cursorDir)) {
3634
3353
  mkdirSync(cursorDir, { recursive: true });
@@ -3646,25 +3365,25 @@ async function mcpInit() {
3646
3365
  mcpServers: { ...parsed.mcpServers ?? {}, vhk: vhkEntry }
3647
3366
  };
3648
3367
  } catch {
3649
- console.log(chalk16.yellow("\u26A0\uFE0F \uAE30\uC874 .cursor/mcp.json \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uC0C8 \uD30C\uC77C\uB85C \uB36E\uC5B4\uC501\uB2C8\uB2E4."));
3368
+ console.log(chalk15.yellow("\u26A0\uFE0F \uAE30\uC874 .cursor/mcp.json \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uC0C8 \uD30C\uC77C\uB85C \uB36E\uC5B4\uC501\uB2C8\uB2E4."));
3650
3369
  config = { mcpServers: { vhk: vhkEntry } };
3651
3370
  }
3652
3371
  } else {
3653
3372
  config = { mcpServers: { vhk: vhkEntry } };
3654
3373
  }
3655
3374
  writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
3656
- console.log(chalk16.green("\n\u2705 Cursor MCP \uC124\uC815 \uC644\uB8CC!"));
3657
- console.log(chalk16.cyan("\u{1F4C1} \uC0DD\uC131\uB41C \uD30C\uC77C:"));
3375
+ console.log(chalk15.green("\n\u2705 Cursor MCP \uC124\uC815 \uC644\uB8CC!"));
3376
+ console.log(chalk15.cyan("\u{1F4C1} \uC0DD\uC131\uB41C \uD30C\uC77C:"));
3658
3377
  console.log(` ${configPath}`);
3659
- console.log(chalk16.cyan("\n\u{1F504} \uB2E4\uC74C \uB2E8\uACC4:"));
3378
+ console.log(chalk15.cyan("\n\u{1F504} \uB2E4\uC74C \uB2E8\uACC4:"));
3660
3379
  console.log(" 1. Cursor\uB97C \uC7AC\uC2DC\uC791\uD558\uC138\uC694");
3661
3380
  console.log(" 2. Cursor \uCC44\uD305\uC5D0\uC11C vhk \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
3662
- console.log(chalk16.gray('\n\u{1F4A1} \uC608: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC54C\uB824\uC918" \u2192 Cursor\uAC00 vhk status \uD638\uCD9C'));
3381
+ console.log(chalk15.gray('\n\u{1F4A1} \uC608: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC54C\uB824\uC918" \u2192 Cursor\uAC00 vhk status \uD638\uCD9C'));
3663
3382
  }
3664
3383
 
3665
3384
  // src/commands/deploy.ts
3666
3385
  import { existsSync as existsSync2 } from "fs";
3667
- import chalk17 from "chalk";
3386
+ import chalk16 from "chalk";
3668
3387
  import inquirer7 from "inquirer";
3669
3388
  var PLATFORMS = {
3670
3389
  vercel: {
@@ -3704,11 +3423,11 @@ function isCLIAvailable(cmd, checkArgs) {
3704
3423
  return safeExecFile(cmd, checkArgs).ok;
3705
3424
  }
3706
3425
  async function deploy() {
3707
- console.log(chalk17.bold("\n\u{1F680} " + t("deploy.title")));
3708
- console.log(chalk17.gray("\u2500".repeat(40)));
3426
+ console.log(chalk16.bold("\n\u{1F680} " + t("deploy.title")));
3427
+ console.log(chalk16.gray("\u2500".repeat(40)));
3709
3428
  let platform = detectPlatform();
3710
3429
  if (platform) {
3711
- console.log(chalk17.cyan(`
3430
+ console.log(chalk16.cyan(`
3712
3431
  \u{1F50D} \uAC10\uC9C0\uB41C \uD50C\uB7AB\uD3FC: ${PLATFORMS[platform].name}`));
3713
3432
  } else {
3714
3433
  const { selected } = await inquirer7.prompt([
@@ -3727,9 +3446,9 @@ async function deploy() {
3727
3446
  }
3728
3447
  const config = PLATFORMS[platform];
3729
3448
  if (!isCLIAvailable(config.command, config.checkArgs)) {
3730
- console.log(chalk17.red(`
3449
+ console.log(chalk16.red(`
3731
3450
  \u274C ${config.name} CLI\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`));
3732
- console.log(chalk17.yellow(` \u2192 ${config.installHint}`));
3451
+ console.log(chalk16.yellow(` \u2192 ${config.installHint}`));
3733
3452
  return;
3734
3453
  }
3735
3454
  const { confirm } = await inquirer7.prompt([
@@ -3741,15 +3460,15 @@ async function deploy() {
3741
3460
  }
3742
3461
  ]);
3743
3462
  if (!confirm) {
3744
- console.log(chalk17.gray("\uCDE8\uC18C\uB428"));
3463
+ console.log(chalk16.gray("\uCDE8\uC18C\uB428"));
3745
3464
  return;
3746
3465
  }
3747
- console.log(chalk17.cyan(`
3466
+ console.log(chalk16.cyan(`
3748
3467
  ${t("deploy.deploying")}
3749
3468
  `));
3750
3469
  const result = safeExecFileStream(config.command, config.commandArgs);
3751
3470
  if (result.ok) {
3752
- console.log(chalk17.green(`
3471
+ console.log(chalk16.green(`
3753
3472
  \u2705 ${t("deploy.success")}`));
3754
3473
  printNextStep({
3755
3474
  message: "\uBC30\uD3EC \uC644\uB8CC! \uC0AC\uC774\uD2B8\uB97C \uD655\uC778\uD558\uC138\uC694.",
@@ -3757,88 +3476,15 @@ ${t("deploy.deploying")}
3757
3476
  cursorHint: "\uC0C1\uD0DC \uD655\uC778\uD574\uC918"
3758
3477
  });
3759
3478
  } else {
3760
- console.log(chalk17.red(`
3479
+ console.log(chalk16.red(`
3761
3480
  \u274C ${t("deploy.failed")}`));
3762
- console.log(chalk17.red(result.err));
3763
- }
3764
- }
3765
-
3766
- // src/commands/env.ts
3767
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, appendFileSync } from "fs";
3768
- import chalk18 from "chalk";
3769
- function parseEnvKeys(content) {
3770
- return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.split("=")[0].trim()).filter(Boolean);
3771
- }
3772
- function ensureGitignore() {
3773
- const gitignorePath = ".gitignore";
3774
- if (existsSync3(gitignorePath)) {
3775
- const content = readFileSync2(gitignorePath, "utf-8");
3776
- if (!content.split("\n").some((l) => l.trim() === ".env")) {
3777
- appendFileSync(gitignorePath, "\n.env\n");
3778
- console.log(chalk18.green("\n\u{1F512} .gitignore\uC5D0 .env \uCD94\uAC00\uB428"));
3779
- }
3780
- } else {
3781
- writeFileSync2(gitignorePath, ".env\nnode_modules/\ndist/\n");
3782
- console.log(chalk18.green("\n\u{1F512} .gitignore \uC0DD\uC131 (.env \uD3EC\uD568)"));
3783
- }
3784
- }
3785
- async function env() {
3786
- console.log(chalk18.bold("\n\u{1F510} " + t("env.title")));
3787
- console.log(chalk18.gray("\u2500".repeat(40)));
3788
- if (!existsSync3(".env")) {
3789
- console.log(chalk18.yellow("\n\u26A0\uFE0F .env \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
3790
- console.log(chalk18.gray(" .env \uD30C\uC77C\uC744 \uBA3C\uC800 \uB9CC\uB4E4\uC5B4\uC8FC\uC138\uC694."));
3791
- return;
3792
- }
3793
- const envContent = readFileSync2(".env", "utf-8");
3794
- const keys = parseEnvKeys(envContent);
3795
- if (keys.length === 0) {
3796
- console.log(chalk18.yellow("\n\u{1F4ED} .env\uC5D0 \uD658\uACBD\uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
3797
- return;
3481
+ console.log(chalk16.red(result.err));
3798
3482
  }
3799
- const exampleContent = keys.map((k) => `${k}=`).join("\n") + "\n";
3800
- writeFileSync2(".env.example", exampleContent, "utf-8");
3801
- console.log(chalk18.green(`
3802
- \u2705 .env.example \uC0DD\uC131 (${keys.length}\uAC1C \uD0A4)`));
3803
- keys.forEach((k) => console.log(chalk18.gray(` ${k}`)));
3804
- ensureGitignore();
3805
- printNextStep({
3806
- message: ".env.example \uC0DD\uC131 \uC644\uB8CC!",
3807
- command: "vhk env-check",
3808
- cursorHint: "\uD658\uACBD\uBCC0\uC218 \uC810\uAC80\uD574\uC918"
3809
- });
3810
- }
3811
- async function envCheck() {
3812
- console.log(chalk18.bold("\n\u{1F50D} " + t("env.checkTitle")));
3813
- console.log(chalk18.gray("\u2500".repeat(40)));
3814
- if (!existsSync3(".env.example")) {
3815
- console.log(chalk18.yellow("\n\u26A0\uFE0F .env.example\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 vhk env\uB97C \uC2E4\uD589\uD558\uC138\uC694."));
3816
- return;
3817
- }
3818
- const requiredKeys = parseEnvKeys(readFileSync2(".env.example", "utf-8"));
3819
- const currentKeys = existsSync3(".env") ? parseEnvKeys(readFileSync2(".env", "utf-8")) : [];
3820
- const missing = requiredKeys.filter((k) => !currentKeys.includes(k));
3821
- const extra = currentKeys.filter((k) => !requiredKeys.includes(k));
3822
- console.log(chalk18.cyan(`
3823
- \u{1F4CB} \uD544\uC218 \uD658\uACBD\uBCC0\uC218: ${requiredKeys.length}\uAC1C`));
3824
- if (missing.length === 0) {
3825
- console.log(chalk18.green("\n\u2705 \uBAA8\uB4E0 \uD544\uC218 \uD658\uACBD\uBCC0\uC218\uAC00 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4!"));
3826
- } else {
3827
- console.log(chalk18.red(`
3828
- \u274C \uB204\uB77D\uB41C \uD658\uACBD\uBCC0\uC218 (${missing.length}\uAC1C):`));
3829
- missing.forEach((k) => console.log(chalk18.red(` \u2022 ${k}`)));
3830
- }
3831
- if (extra.length > 0) {
3832
- console.log(chalk18.yellow(`
3833
- \u{1F4A1} .env.example\uC5D0 \uC5C6\uB294 \uCD94\uAC00 \uBCC0\uC218 (${extra.length}\uAC1C):`));
3834
- extra.forEach((k) => console.log(chalk18.yellow(` \u2022 ${k}`)));
3835
- }
3836
- ensureGitignore();
3837
3483
  }
3838
3484
 
3839
3485
  // src/commands/publish.ts
3840
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
3841
- import chalk19 from "chalk";
3486
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
3487
+ import chalk17 from "chalk";
3842
3488
  import inquirer8 from "inquirer";
3843
3489
  import ora2 from "ora";
3844
3490
  function bumpVersion(current, type) {
@@ -3853,21 +3499,21 @@ function bumpVersion(current, type) {
3853
3499
  }
3854
3500
  }
3855
3501
  async function publish() {
3856
- console.log(chalk19.bold("\n\u{1F4E6} " + t("publish.title")));
3857
- console.log(chalk19.gray("\u2500".repeat(40)));
3858
- if (!existsSync4("package.json")) {
3859
- console.log(chalk19.red("\u274C package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
3502
+ console.log(chalk17.bold("\n\u{1F4E6} " + t("publish.title")));
3503
+ console.log(chalk17.gray("\u2500".repeat(40)));
3504
+ if (!existsSync3("package.json")) {
3505
+ console.log(chalk17.red("\u274C package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
3860
3506
  return;
3861
3507
  }
3862
3508
  let pkg;
3863
3509
  try {
3864
- pkg = JSON.parse(readFileSync3("package.json", "utf-8"));
3510
+ pkg = JSON.parse(readFileSync2("package.json", "utf-8"));
3865
3511
  } catch {
3866
- console.log(chalk19.red("\u274C package.json \uD30C\uC2F1 \uC2E4\uD328"));
3512
+ console.log(chalk17.red("\u274C package.json \uD30C\uC2F1 \uC2E4\uD328"));
3867
3513
  return;
3868
3514
  }
3869
3515
  const currentVersion = pkg.version || "0.0.0";
3870
- console.log(chalk19.cyan(`
3516
+ console.log(chalk17.cyan(`
3871
3517
  \u{1F4CC} \uD604\uC7AC \uBC84\uC804: v${currentVersion}`));
3872
3518
  const { bumpType } = await inquirer8.prompt([
3873
3519
  {
@@ -3882,18 +3528,18 @@ async function publish() {
3882
3528
  }
3883
3529
  ]);
3884
3530
  const newVersion = bumpVersion(currentVersion, bumpType);
3885
- console.log(chalk19.cyan(`
3531
+ console.log(chalk17.cyan(`
3886
3532
  \u{1F195} \uC0C8 \uBC84\uC804: v${newVersion}`));
3887
3533
  pkg.version = newVersion;
3888
- writeFileSync3("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3889
- console.log(chalk19.green("\u2705 package.json \uBC84\uC804 \uC5C5\uB370\uC774\uD2B8"));
3534
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3535
+ console.log(chalk17.green("\u2705 package.json \uBC84\uC804 \uC5C5\uB370\uC774\uD2B8"));
3890
3536
  const buildSpinner = ora2(t("publish.building")).start();
3891
3537
  const buildResult = safeExecFile("pnpm", ["build"]);
3892
3538
  if (!buildResult.ok) {
3893
3539
  buildSpinner.fail(t("publish.buildFailed"));
3894
- console.log(chalk19.red(buildResult.err.slice(0, 500)));
3540
+ console.log(chalk17.red(buildResult.err.slice(0, 500)));
3895
3541
  pkg.version = currentVersion;
3896
- writeFileSync3("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3542
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3897
3543
  return;
3898
3544
  }
3899
3545
  buildSpinner.succeed(t("publish.buildSuccess"));
@@ -3901,9 +3547,9 @@ async function publish() {
3901
3547
  const testResult = safeExecFile("pnpm", ["test", "--run"]);
3902
3548
  if (!testResult.ok) {
3903
3549
  testSpinner.fail(t("publish.testFailed"));
3904
- console.log(chalk19.red(testResult.err.slice(0, 500)));
3550
+ console.log(chalk17.red(testResult.err.slice(0, 500)));
3905
3551
  pkg.version = currentVersion;
3906
- writeFileSync3("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3552
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3907
3553
  return;
3908
3554
  }
3909
3555
  testSpinner.succeed(t("publish.testSuccess"));
@@ -3917,18 +3563,18 @@ async function publish() {
3917
3563
  ]);
3918
3564
  if (!confirm) {
3919
3565
  pkg.version = currentVersion;
3920
- writeFileSync3("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3921
- console.log(chalk19.gray("\uCDE8\uC18C\uB428. \uBC84\uC804\uC774 \uC6D0\uB798\uB300\uB85C \uBCF5\uAD6C\uB429\uB2C8\uB2E4."));
3566
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3567
+ console.log(chalk17.gray("\uCDE8\uC18C\uB428. \uBC84\uC804\uC774 \uC6D0\uB798\uB300\uB85C \uBCF5\uAD6C\uB429\uB2C8\uB2E4."));
3922
3568
  return;
3923
3569
  }
3924
3570
  const pubSpinner = ora2(t("publish.publishing")).start();
3925
3571
  const pubResult = safeExecFile("npm", ["publish", "--access", "public"]);
3926
3572
  if (!pubResult.ok) {
3927
3573
  pubSpinner.fail(t("publish.publishFailed"));
3928
- console.log(chalk19.red(pubResult.err.slice(0, 500)));
3574
+ console.log(chalk17.red(pubResult.err.slice(0, 500)));
3929
3575
  pkg.version = currentVersion;
3930
- writeFileSync3("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3931
- console.log(chalk19.gray(`\u{1F4E6} package.json \uBC84\uC804\uC744 v${currentVersion}\uB85C \uBCF5\uAD6C\uD588\uC2B5\uB2C8\uB2E4.`));
3576
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3577
+ console.log(chalk17.gray(`\u{1F4E6} package.json \uBC84\uC804\uC744 v${currentVersion}\uB85C \uBCF5\uAD6C\uD588\uC2B5\uB2C8\uB2E4.`));
3932
3578
  return;
3933
3579
  }
3934
3580
  pubSpinner.succeed(t("publish.publishSuccess"));
@@ -3940,15 +3586,15 @@ async function publish() {
3940
3586
  const pushResult = safeExecFile("git", ["push"]);
3941
3587
  const pushTagsResult = safeExecFile("git", ["push", "--tags"]);
3942
3588
  if (pushResult.ok && pushTagsResult.ok) {
3943
- console.log(chalk19.green(`
3589
+ console.log(chalk17.green(`
3944
3590
  \u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131 + push \uC644\uB8CC`));
3945
3591
  } else {
3946
- console.log(chalk19.yellow(`
3592
+ console.log(chalk17.yellow(`
3947
3593
  \u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131\uB428 (push\uB294 \uC218\uB3D9\uC73C\uB85C)`));
3948
3594
  }
3949
3595
  }
3950
3596
  }
3951
- console.log(chalk19.green.bold(`
3597
+ console.log(chalk17.green.bold(`
3952
3598
  \u{1F389} v${newVersion} \uBC30\uD3EC \uC644\uB8CC!`));
3953
3599
  printNextStep({
3954
3600
  message: "npm \uBC30\uD3EC \uC644\uB8CC!",
@@ -3957,6 +3603,329 @@ async function publish() {
3957
3603
  });
3958
3604
  }
3959
3605
 
3606
+ // src/commands/design.ts
3607
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
3608
+ import chalk18 from "chalk";
3609
+ import inquirer9 from "inquirer";
3610
+ var PALETTES = [
3611
+ {
3612
+ name: "Minimal",
3613
+ colors: {
3614
+ primary: "#1a1a1a",
3615
+ secondary: "#6b7280",
3616
+ accent: "#3b82f6",
3617
+ background: "#ffffff",
3618
+ surface: "#f9fafb",
3619
+ text: "#111827",
3620
+ muted: "#9ca3af"
3621
+ }
3622
+ },
3623
+ {
3624
+ name: "Vibrant",
3625
+ colors: {
3626
+ primary: "#7c3aed",
3627
+ secondary: "#ec4899",
3628
+ accent: "#f59e0b",
3629
+ background: "#ffffff",
3630
+ surface: "#faf5ff",
3631
+ text: "#1e1b4b",
3632
+ muted: "#8b5cf6"
3633
+ }
3634
+ },
3635
+ {
3636
+ name: "Corporate",
3637
+ colors: {
3638
+ primary: "#1e40af",
3639
+ secondary: "#0f766e",
3640
+ accent: "#ca8a04",
3641
+ background: "#ffffff",
3642
+ surface: "#f0f9ff",
3643
+ text: "#0f172a",
3644
+ muted: "#64748b"
3645
+ }
3646
+ },
3647
+ {
3648
+ name: "Pastel",
3649
+ colors: {
3650
+ primary: "#a78bfa",
3651
+ secondary: "#f9a8d4",
3652
+ accent: "#fcd34d",
3653
+ background: "#fffbeb",
3654
+ surface: "#fef3c7",
3655
+ text: "#44403c",
3656
+ muted: "#a8a29e"
3657
+ }
3658
+ }
3659
+ ];
3660
+ function hasTailwind() {
3661
+ return existsSync4("tailwind.config.js") || existsSync4("tailwind.config.ts") || existsSync4("tailwind.config.mjs") || existsSync4("tailwind.config.cjs");
3662
+ }
3663
+ function generateCSSTokens(palette) {
3664
+ const lines = Object.entries(palette.colors).map(([key, value]) => ` --color-${key}: ${value};`).join("\n");
3665
+ return `:root {
3666
+ ${lines}
3667
+ }
3668
+ `;
3669
+ }
3670
+ function generateTailwindExtend(palette) {
3671
+ const entries = Object.entries(palette.colors).map(([key, value]) => ` '${key}': '${value}',`).join("\n");
3672
+ return `// vhk design \u2014 Tailwind config \uD655\uC7A5\uC6A9 \uCEEC\uB7EC \uD1A0\uD070
3673
+ // tailwind.config\uC758 theme.extend.colors\uC5D0 spread \uD558\uC138\uC694.
3674
+ const vhkColors = {
3675
+ ${entries}
3676
+ }
3677
+
3678
+ export default vhkColors
3679
+ `;
3680
+ }
3681
+ async function design() {
3682
+ console.log(chalk18.bold("\n\u{1F3A8} " + t("design.title")));
3683
+ console.log(chalk18.gray("\u2500".repeat(40)));
3684
+ const { paletteIndex } = await inquirer9.prompt([
3685
+ {
3686
+ type: "list",
3687
+ name: "paletteIndex",
3688
+ message: t("design.selectPalette"),
3689
+ choices: PALETTES.map((p, i) => ({
3690
+ name: `${p.name} \u2014 primary ${p.colors.primary}`,
3691
+ value: i
3692
+ }))
3693
+ }
3694
+ ]);
3695
+ const palette = PALETTES[paletteIndex];
3696
+ console.log(chalk18.cyan(`
3697
+ \u{1F3A8} \uC120\uD0DD\uB41C \uD314\uB808\uD2B8: ${palette.name}`));
3698
+ const targetPath = hasTailwind() ? "src/styles/vhk-colors.ts" : "src/styles/tokens.css";
3699
+ const content = hasTailwind() ? generateTailwindExtend(palette) : generateCSSTokens(palette);
3700
+ if (existsSync4(targetPath)) {
3701
+ const { overwrite } = await inquirer9.prompt([{
3702
+ type: "confirm",
3703
+ name: "overwrite",
3704
+ message: `${targetPath} \uC774\uBBF8 \uC788\uC5B4\uC694. \uB36E\uC5B4\uC4F8\uAE4C\uC694?`,
3705
+ default: false
3706
+ }]);
3707
+ if (!overwrite) {
3708
+ console.log(chalk18.yellow("\n\u23ED\uFE0F \uC0DD\uC131 \uCDE8\uC18C \u2014 \uAE30\uC874 \uD30C\uC77C \uC720\uC9C0."));
3709
+ return;
3710
+ }
3711
+ }
3712
+ mkdirSync2("src/styles", { recursive: true });
3713
+ writeFileSync3(targetPath, content, "utf-8");
3714
+ if (hasTailwind()) {
3715
+ console.log(chalk18.green("\n\u2705 src/styles/vhk-colors.ts \uC0DD\uC131"));
3716
+ console.log(chalk18.gray(" tailwind.config\uC758 extend.colors\uC5D0 import \uD574\uC11C \uC0AC\uC6A9\uD558\uC138\uC694."));
3717
+ } else {
3718
+ console.log(chalk18.green("\n\u2705 src/styles/tokens.css \uC0DD\uC131"));
3719
+ console.log(chalk18.gray(" HTML\uC5D0 <link>\uB85C \uCD94\uAC00\uD558\uAC70\uB098 CSS\uC5D0\uC11C @import \uD558\uC138\uC694."));
3720
+ }
3721
+ console.log(chalk18.bold("\n\u{1F308} \uCEEC\uB7EC \uBBF8\uB9AC\uBCF4\uAE30:"));
3722
+ for (const [key, value] of Object.entries(palette.colors)) {
3723
+ console.log(` ${key.padEnd(12)} ${value}`);
3724
+ }
3725
+ printNextStep({
3726
+ message: "\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131 \uC644\uB8CC!",
3727
+ command: "vhk theme",
3728
+ cursorHint: "\uD14C\uB9C8 \uC124\uC815\uD574\uC918"
3729
+ });
3730
+ }
3731
+ async function designPalette() {
3732
+ await design();
3733
+ }
3734
+
3735
+ // src/commands/theme.ts
3736
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
3737
+ import chalk19 from "chalk";
3738
+ import inquirer10 from "inquirer";
3739
+ function generateDarkCSS() {
3740
+ return `/* vhk theme \u2014 \uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC CSS \uBCC0\uC218 */
3741
+
3742
+ @media (prefers-color-scheme: dark) {
3743
+ :root {
3744
+ --color-background: #0f172a;
3745
+ --color-surface: #1e293b;
3746
+ --color-text: #f1f5f9;
3747
+ --color-muted: #64748b;
3748
+ }
3749
+ }
3750
+
3751
+ [data-theme="dark"] {
3752
+ --color-background: #0f172a;
3753
+ --color-surface: #1e293b;
3754
+ --color-text: #f1f5f9;
3755
+ --color-muted: #64748b;
3756
+ }
3757
+
3758
+ [data-theme="light"] {
3759
+ --color-background: #ffffff;
3760
+ --color-surface: #f9fafb;
3761
+ --color-text: #111827;
3762
+ --color-muted: #9ca3af;
3763
+ }
3764
+ `;
3765
+ }
3766
+ function generateToggleUtil() {
3767
+ return `// vhk theme \u2014 \uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC \uD1A0\uAE00 \uC720\uD2F8\uB9AC\uD2F0
3768
+
3769
+ export function getTheme(): 'light' | 'dark' {
3770
+ if (typeof window === 'undefined') return 'light'
3771
+ const stored = localStorage.getItem('vhk-theme') as 'light' | 'dark' | null
3772
+ if (stored === 'light' || stored === 'dark') return stored
3773
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
3774
+ }
3775
+
3776
+ export function setTheme(theme: 'light' | 'dark'): void {
3777
+ if (typeof document === 'undefined') return
3778
+ document.documentElement.setAttribute('data-theme', theme)
3779
+ localStorage.setItem('vhk-theme', theme)
3780
+ }
3781
+
3782
+ export function toggleTheme(): 'light' | 'dark' {
3783
+ const next = getTheme() === 'light' ? 'dark' : 'light'
3784
+ setTheme(next)
3785
+ return next
3786
+ }
3787
+
3788
+ export function initTheme(): void {
3789
+ setTheme(getTheme())
3790
+ }
3791
+ `;
3792
+ }
3793
+ async function theme() {
3794
+ console.log(chalk19.bold("\n\u{1F319} " + t("theme.title")));
3795
+ console.log(chalk19.gray("\u2500".repeat(40)));
3796
+ const cssPath = "src/styles/theme.css";
3797
+ const togglePath = "src/lib/theme-toggle.ts";
3798
+ const conflicts = [cssPath, togglePath].filter((p) => existsSync5(p));
3799
+ if (conflicts.length > 0) {
3800
+ const { overwrite } = await inquirer10.prompt([{
3801
+ type: "confirm",
3802
+ name: "overwrite",
3803
+ message: `\uB2E4\uC74C \uD30C\uC77C\uC774 \uC774\uBBF8 \uC788\uC5B4\uC694. \uB36E\uC5B4\uC4F8\uAE4C\uC694?
3804
+ ${conflicts.join("\n ")}`,
3805
+ default: false
3806
+ }]);
3807
+ if (!overwrite) {
3808
+ console.log(chalk19.yellow("\n\u23ED\uFE0F \uC0DD\uC131 \uCDE8\uC18C \u2014 \uAE30\uC874 \uD30C\uC77C \uC720\uC9C0."));
3809
+ return;
3810
+ }
3811
+ }
3812
+ mkdirSync3("src/styles", { recursive: true });
3813
+ mkdirSync3("src/lib", { recursive: true });
3814
+ writeFileSync4(cssPath, generateDarkCSS(), "utf-8");
3815
+ console.log(chalk19.green("\n\u2705 src/styles/theme.css \uC0DD\uC131 (\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC)"));
3816
+ writeFileSync4(togglePath, generateToggleUtil(), "utf-8");
3817
+ console.log(chalk19.green("\u2705 src/lib/theme-toggle.ts \uC0DD\uC131 (\uD1A0\uAE00 \uC720\uD2F8\uB9AC\uD2F0)"));
3818
+ console.log(chalk19.bold("\n\u{1F4D6} \uC0AC\uC6A9\uBC95:"));
3819
+ console.log(chalk19.gray(" 1. theme.css\uB97C \uAE00\uB85C\uBC8C \uC2A4\uD0C0\uC77C\uC5D0 \uCD94\uAC00"));
3820
+ console.log(chalk19.gray(' 2. import { initTheme, toggleTheme } from "./lib/theme-toggle"'));
3821
+ console.log(chalk19.gray(" 3. \uC571 \uC9C4\uC785\uC810\uC5D0\uC11C initTheme() \uD638\uCD9C"));
3822
+ console.log(chalk19.gray(" 4. \uD1A0\uAE00 \uBC84\uD2BC\uC5D0\uC11C toggleTheme() \uD638\uCD9C"));
3823
+ printNextStep({
3824
+ message: "\uD14C\uB9C8 \uC124\uC815 \uC644\uB8CC!",
3825
+ command: "vhk ref list",
3826
+ cursorHint: "\uB808\uD37C\uB7F0\uC2A4 \uD655\uC778\uD574\uC918"
3827
+ });
3828
+ }
3829
+
3830
+ // src/commands/ref.ts
3831
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync5 } from "fs";
3832
+ import chalk20 from "chalk";
3833
+ var REFS_PATH = ".vhk/refs.json";
3834
+ function loadRefs() {
3835
+ if (!existsSync6(REFS_PATH)) return [];
3836
+ try {
3837
+ const raw = readFileSync3(REFS_PATH, "utf-8");
3838
+ const parsed = JSON.parse(raw);
3839
+ return Array.isArray(parsed) ? parsed : [];
3840
+ } catch {
3841
+ return [];
3842
+ }
3843
+ }
3844
+ function saveRefs(refs) {
3845
+ mkdirSync4(".vhk", { recursive: true });
3846
+ writeFileSync5(REFS_PATH, JSON.stringify(refs, null, 2) + "\n", "utf-8");
3847
+ }
3848
+ async function refAdd(url, memo = "") {
3849
+ console.log(chalk20.bold("\n\u{1F517} " + t("ref.addTitle")));
3850
+ console.log(chalk20.gray("\u2500".repeat(40)));
3851
+ if (!url) {
3852
+ console.log(chalk20.red("\u274C URL\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694."));
3853
+ console.log(chalk20.gray(' \uC608: vhk ref add https://example.com --memo "\uCC38\uACE0 \uC0AC\uC774\uD2B8"'));
3854
+ return;
3855
+ }
3856
+ const refs = loadRefs();
3857
+ if (refs.some((r) => r.url === url)) {
3858
+ console.log(chalk20.yellow("\u26A0\uFE0F \uC774\uBBF8 \uC800\uC7A5\uB41C URL\uC785\uB2C8\uB2E4."));
3859
+ return;
3860
+ }
3861
+ refs.push({ url, memo, addedAt: (/* @__PURE__ */ new Date()).toISOString() });
3862
+ saveRefs(refs);
3863
+ console.log(chalk20.green(`
3864
+ \u2705 \uB808\uD37C\uB7F0\uC2A4 \uCD94\uAC00\uB428 (#${refs.length})`));
3865
+ console.log(chalk20.cyan(` ${url}`));
3866
+ if (memo) console.log(chalk20.gray(` \u{1F4DD} ${memo}`));
3867
+ printNextStep({
3868
+ message: "\uB808\uD37C\uB7F0\uC2A4 \uC800\uC7A5 \uC644\uB8CC!",
3869
+ command: "vhk ref list",
3870
+ cursorHint: "\uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D \uBCF4\uC5EC\uC918"
3871
+ });
3872
+ }
3873
+ async function refList() {
3874
+ console.log(chalk20.bold("\n\u{1F4DA} " + t("ref.listTitle")));
3875
+ console.log(chalk20.gray("\u2500".repeat(40)));
3876
+ const refs = loadRefs();
3877
+ if (refs.length === 0) {
3878
+ console.log(chalk20.yellow("\n\u{1F4ED} \uC800\uC7A5\uB41C \uB808\uD37C\uB7F0\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
3879
+ console.log(chalk20.gray(' vhk ref add <url> --memo "\uBA54\uBAA8"\uB85C \uCD94\uAC00\uD558\uC138\uC694.'));
3880
+ return;
3881
+ }
3882
+ console.log(chalk20.cyan(`
3883
+ \uCD1D ${refs.length}\uAC1C\uC758 \uB808\uD37C\uB7F0\uC2A4:
3884
+ `));
3885
+ refs.forEach((ref, index) => {
3886
+ const date = new Date(ref.addedAt).toLocaleDateString("ko-KR");
3887
+ console.log(chalk20.white(` [${index + 1}] ${ref.url}`));
3888
+ if (ref.memo) console.log(chalk20.gray(` \u{1F4DD} ${ref.memo}`));
3889
+ console.log(chalk20.gray(` \u{1F4C5} ${date}`));
3890
+ console.log("");
3891
+ });
3892
+ }
3893
+ async function refOpen(indexStr) {
3894
+ const refs = loadRefs();
3895
+ const idx = parseInt(indexStr, 10) - 1;
3896
+ if (Number.isNaN(idx) || idx < 0 || idx >= refs.length) {
3897
+ console.log(chalk20.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uBC88\uD638\uC785\uB2C8\uB2E4. (1~${refs.length || 0})`));
3898
+ return;
3899
+ }
3900
+ const ref = refs[idx];
3901
+ let parsed;
3902
+ try {
3903
+ parsed = new URL(ref.url);
3904
+ } catch {
3905
+ console.log(chalk20.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 URL: ${ref.url}`));
3906
+ return;
3907
+ }
3908
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
3909
+ console.log(chalk20.red(`\u274C http(s) URL\uB9CC \uC5F4 \uC218 \uC788\uC2B5\uB2C8\uB2E4 (${parsed.protocol})`));
3910
+ return;
3911
+ }
3912
+ console.log(chalk20.cyan(`
3913
+ \u{1F310} \uC5F4\uAE30: ${ref.url}`));
3914
+ let result;
3915
+ if (process.platform === "darwin") {
3916
+ result = safeExecFile("open", [ref.url]);
3917
+ } else if (process.platform === "win32") {
3918
+ result = safeExecFile("cmd.exe", ["/c", "start", "", ref.url]);
3919
+ } else {
3920
+ result = safeExecFile("xdg-open", [ref.url]);
3921
+ }
3922
+ if (result.ok) {
3923
+ console.log(chalk20.green("\u2705 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4."));
3924
+ } else {
3925
+ console.log(chalk20.yellow("\u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. URL\uC744 \uC9C1\uC811 \uBC29\uBB38\uD574\uC8FC\uC138\uC694."));
3926
+ }
3927
+ }
3928
+
3960
3929
  // src/lib/nlp-run.ts
3961
3930
  async function dispatchNlpRoute(route, input) {
3962
3931
  switch (route.command) {
@@ -3997,28 +3966,36 @@ async function dispatchNlpRoute(route, input) {
3997
3966
  return envCheck();
3998
3967
  case "publish":
3999
3968
  return publish();
3969
+ case "design":
3970
+ return design();
3971
+ case "design-palette":
3972
+ return designPalette();
3973
+ case "theme":
3974
+ return theme();
3975
+ case "ref":
3976
+ return refList();
4000
3977
  }
4001
3978
  }
4002
3979
  async function runNaturalLanguageRoute(input) {
4003
3980
  const route = routeNaturalLanguage(input);
4004
3981
  if (!route) {
4005
- console.log(chalk20.yellow(`
3982
+ console.log(chalk21.yellow(`
4006
3983
  \u2753 "${input}" \u2014 ${ko.nlp.notMatched}
4007
3984
  `));
4008
3985
  return;
4009
3986
  }
4010
3987
  console.log("");
4011
- console.log(chalk20.cyan(` \u{1F4AC} "${input}"`));
4012
- console.log(chalk20.cyan(` \u2192 ${route.explanation}`));
3988
+ console.log(chalk21.cyan(` \u{1F4AC} "${input}"`));
3989
+ console.log(chalk21.cyan(` \u2192 ${route.explanation}`));
4013
3990
  if (route.confidence === "low") {
4014
- const { confirm } = await inquirer9.prompt([{
3991
+ const { confirm } = await inquirer11.prompt([{
4015
3992
  type: "confirm",
4016
3993
  name: "confirm",
4017
3994
  message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
4018
3995
  default: true
4019
3996
  }]);
4020
3997
  if (!confirm) {
4021
- console.log(chalk20.dim(` ${ko.nlp.menuHint}`));
3998
+ console.log(chalk21.dim(` ${ko.nlp.menuHint}`));
4022
3999
  return;
4023
4000
  }
4024
4001
  }
@@ -4045,9 +4022,13 @@ var KO_ALIASES = {
4045
4022
  deploy: "\uBC30\uD3EC",
4046
4023
  env: "\uD658\uACBD\uBCC0\uC218",
4047
4024
  "env-check": "\uD658\uACBD\uBCC0\uC218\uC810\uAC80",
4048
- publish: "\uCD9C\uC2DC"
4025
+ publish: "\uCD9C\uC2DC",
4026
+ design: "\uB514\uC790\uC778",
4027
+ "design-palette": "\uD314\uB808\uD2B8",
4028
+ theme: "\uD14C\uB9C8",
4029
+ ref: "\uB808\uD37C\uB7F0\uC2A4"
4049
4030
  };
4050
- program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.7.0");
4031
+ program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.8.0");
4051
4032
  program.configureHelp({
4052
4033
  formatHelp(cmd, helper) {
4053
4034
  if (cmd.parent) {
@@ -4108,6 +4089,27 @@ program.command("env-check").alias("\uD658\uACBD\uBCC0\uC218\uC810\uAC80").descr
4108
4089
  program.command("publish").alias("\uCD9C\uC2DC").description("npm \uBC30\uD3EC (\uBC84\uC804 \uBC94\uD504 \u2192 \uBE4C\uB4DC \u2192 \uD14C\uC2A4\uD2B8 \u2192 publish)").action(async () => {
4109
4090
  await publish();
4110
4091
  });
4092
+ program.command("design").alias("\uB514\uC790\uC778").description("\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131 (Tailwind config \uB610\uB294 CSS \uBCC0\uC218)").action(async () => {
4093
+ await design();
4094
+ });
4095
+ program.command("design-palette").alias("\uD314\uB808\uD2B8").description("\uCEEC\uB7EC \uD314\uB808\uD2B8 \uD504\uB9AC\uC14B \uC120\uD0DD + \uC801\uC6A9").action(async () => {
4096
+ await designPalette();
4097
+ });
4098
+ program.command("theme").alias("\uD14C\uB9C8").description("\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC CSS + \uD1A0\uAE00 \uC720\uD2F8\uB9AC\uD2F0 \uC0DD\uC131").action(async () => {
4099
+ await theme();
4100
+ });
4101
+ var refCmd = program.command("ref").alias("\uB808\uD37C\uB7F0\uC2A4").description("\uB808\uD37C\uB7F0\uC2A4 URL \uAD00\uB9AC (add / list / open)").action(async () => {
4102
+ await refList();
4103
+ });
4104
+ refCmd.command("add <url>").option("--memo <memo>", "\uBA54\uBAA8 \uCD94\uAC00").description("\uB808\uD37C\uB7F0\uC2A4 URL \uCD94\uAC00").action(async (url, opts) => {
4105
+ await refAdd(url, opts.memo);
4106
+ });
4107
+ refCmd.command("list").alias("\uBAA9\uB85D").description("\uC800\uC7A5\uB41C \uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D").action(async () => {
4108
+ await refList();
4109
+ });
4110
+ refCmd.command("open <index>").alias("\uC5F4\uAE30").description("\uB808\uD37C\uB7F0\uC2A4\uB97C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uAE30").action(async (index) => {
4111
+ await refOpen(index);
4112
+ });
4111
4113
  program.on("command:*", async (operands) => {
4112
4114
  const unknown = operands[0] ?? "";
4113
4115
  const rest = operands.slice(1);
@@ -4116,7 +4118,7 @@ program.on("command:*", async (operands) => {
4116
4118
  });
4117
4119
  program.action(async () => {
4118
4120
  console.log("\n\u{1F3AF} VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58\n");
4119
- const { choice } = await inquirer10.prompt([{
4121
+ const { choice } = await inquirer12.prompt([{
4120
4122
  type: "list",
4121
4123
  name: "choice",
4122
4124
  message: "\uBB58 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",