@byh3071/vhk 0.9.1 โ 1.0.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/README.md +52 -3
- package/dist/{chunk-UPXCLOBF.js โ chunk-7NGBIIA3.js} +11 -0
- package/dist/index.js +457 -28
- package/dist/mcp/index.js +1 -1
- package/package.json +65 -65
package/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: vhk-readme
|
|
3
3
|
date: 2026-05-24
|
|
4
|
-
tags: [vhk, cli, readme,
|
|
4
|
+
tags: [vhk, cli, readme, v1.0.0, ga]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# ๐ง VHK โ Vibe Harness Kit
|
|
8
8
|
|
|
9
|
-
>
|
|
9
|
+
> ๐ **v1.0.0 GA** โ ๋ฐ์ด๋ธ์ฝ๋์ ์ฌ์ธ์ CLI. ๊ณต๊ฐ API ์์ ์ฑ ๋ณด์ฅ.
|
|
10
|
+
>
|
|
11
|
+
> AI ์ฝ๋ฉ ์์ด์ ํธ๋ฅผ ๋ถ๋ฆฌ๋ ์ฌ๋์ ์ํ **ํ๊ตญ์ด ํ์ฌ์ดํด CLI** (v1.0.0)
|
|
10
12
|
>
|
|
11
13
|
> ๐ฝ๏ธ **VHK๋ VHK๋ก ๋ถํธ์คํธ๋ฉ๋จ** โ ์ด ๋ ํฌ์ `docs/`, `CLAUDE.md`, `.cursorrules`๋ `vhk init`์ด ๋ง๋ค์์ต๋๋ค.
|
|
12
14
|
|
|
@@ -100,9 +102,13 @@ vhk ๊ธฐํ ๋๋ฌ๊ณ ๋ฐ๋ก ์์
|
|
|
100
102
|
| `vhk theme` | `ํ
๋ง` | ๋คํฌ/๋ผ์ดํธ ๋ชจ๋ CSS + ํ ๊ธ ์ ํธ๋ฆฌํฐ ์์ฑ |
|
|
101
103
|
| `vhk ref` | `๋ ํผ๋ฐ์ค` | ๋ ํผ๋ฐ์ค URL ๊ด๋ฆฌ (`add` / `list` / `open`) |
|
|
102
104
|
| `vhk harness` | `ํ๋ค์ค` | ํตํฉ ํ์ง ์ ๊ฒ (lint + type-check + test + build ์์ฐจ ์คํ + ๋ฆฌํฌํธ) |
|
|
103
|
-
| `vhk audit` | `๊ฐ์ฌ` | npm ๋ณด์ ์ทจ์ฝ์ ๊ฐ์ฌ (`--fix`๋ก ์๋
|
|
105
|
+
| `vhk audit` | `๊ฐ์ฌ` | npm/pnpm/yarn ๋ณด์ ์ทจ์ฝ์ ๊ฐ์ฌ (`--fix`๋ก ์๋ ์์ , npm๋ง) |
|
|
104
106
|
| `vhk migrate [target]` | `์ ํ` | ํจํค์ง ๋งค๋์ ์ ํ (`npm` / `yarn` / `pnpm`, lockfile + node_modules ์ฌ๊ตฌ์ฑ) |
|
|
105
107
|
| `vhk update` | `์
๋ฐ์ดํธ` | VHK CLI ์ต์ ๋ฒ์ ์ผ๋ก ์
ํ ์
๋ฐ์ดํธ |
|
|
108
|
+
| `vhk context` | `๋งฅ๋ฝ` | ํ๋ก์ ํธ ํธ๋ฆฌยท์คํยทCLI ๋ช
๋ น ๋ชฉ๋ก์ `.vhk/context.md`๋ก ์๋ ์์ฑ (AI ์ด์์คํดํธ์ฉ) |
|
|
109
|
+
| `vhk context-show` | `๋งฅ๋ฝ๋ณด๊ธฐ` | ํ์ฌ ์ปจํ
์คํธ ํ์ผ ๋ด์ฉ ์ถ๋ ฅ |
|
|
110
|
+
| `vhk memory` | `๊ธฐ์ต` | ๊ฒฐ์ ์ฌํญ ๊ธฐ์ต ๊ด๋ฆฌ (`add` / `list` / `remove`, `.vhk/memory.json` ๊ธฐ๋ฐ, ํ๊ทธ ์ง์) |
|
|
111
|
+
| `vhk brief` | `๋ธ๋ฆฌํ` | ํ๋ก์ ํธ ์ ๋ณด + git ์ํ + ๊ฒฐ์ ์ฌํญ + ๋ ํผ๋ฐ์ค ํตํฉ ๋ณด๊ณ ์ `.vhk/brief.md` |
|
|
106
112
|
|
|
107
113
|
### init ์ต์
|
|
108
114
|
|
|
@@ -137,6 +143,45 @@ MCP ์๋ฒ๋ฅผ ์๋์ผ๋ก ๋์ฐ๋ ค๋ฉด:
|
|
|
137
143
|
vhk mcp # stdio ์๋ฒ ์์ (Cursor๊ฐ ์๋์ผ๋ก ํธ์ถ)
|
|
138
144
|
```
|
|
139
145
|
|
|
146
|
+
## v1.0.0 GA ํ์ด๋ผ์ดํธ ๐
|
|
147
|
+
|
|
148
|
+
> **๊ณต๊ฐ API ์์ ์ฑ ์ฝ์**. ๋ช
๋ น์ด ์ด๋ฆ, CLI ์ธ์, `.vhk/` ํ์ผ ํฌ๋งท์ v2.0๊น์ง breaking change ์์.
|
|
149
|
+
|
|
150
|
+
| ๊ธฐ๋ฅ | ์ค๋ช
|
|
|
151
|
+
|------|------|
|
|
152
|
+
| **context** | ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ ํธ๋ฆฌ(3-depth) + ๊ธฐ์ ์คํ(Next/Nuxt/Vue/Svelte/TS/Tailwind/tsup/Vite/...) ์๋ ๊ฐ์ง + 29๊ฐ+ VHK ๋ช
๋ น์ด ๋ชฉ๋ก์ `.vhk/context.md` ๋งํฌ๋ค์ด์ผ๋ก ์์ฑ. AI ์ด์์คํดํธ๊ฐ ํ๋ก์ ํธ ๋งฅ๋ฝ์ ์ฆ์ ํ์
|
|
|
153
|
+
| **memory** | `.vhk/memory.json` ๊ฒฐ์ ์ฌํญ ๊ธฐ์ต ๊ด๋ฆฌ. `add <content> --tags X,Y` / `list` / `remove <๋ฒํธ>`. NL์ list๋ง (add/remove๋ ์ธ์ ํ์ โ commander ์ ์ฉ) |
|
|
154
|
+
| **brief** | ํ๋ก์ ํธ ์ ๋ณด + git ์ํ(๋ธ๋์นยท๋ง์ง๋ง ์ปค๋ฐยท๋ฏธ์ปค๋ฐ ๋ณ๊ฒฝ) + ์ต๊ทผ ๊ฒฐ์ ์ฌํญ + ๋ ํผ๋ฐ์ค๋ฅผ ํ ํ๋ฉด์ + `.vhk/brief.md` ์ ์ฅ. `safeExecFile` ๊ธฐ๋ฐ (Windows .cmd shim ์์ ) |
|
|
155
|
+
| **์์ฐ์ด ํ์ฅ** | `"๋งฅ๋ฝ ๋ง๋ค์ด์ค"` โ context ยท `"์ปจํ
์คํธ ๋ณด์ฌ์ค"` โ context-show ยท `"๊ธฐ์ต ๋ชฉ๋ก"` โ memory ยท `"ํ๋ก์ ํธ ๋ธ๋ฆฌํ ๋ง๋ค์ด์ค"` / `"์ํ ์์ฝ"` โ brief |
|
|
156
|
+
|
|
157
|
+
```powershell
|
|
158
|
+
vhk context # .vhk/context.md (ํธ๋ฆฌ + ์คํ + ๋ช
๋ น ๋ชฉ๋ก)
|
|
159
|
+
vhk memory add "API๋ tRPC ์ฌ์ฉ" --tags decision,arch
|
|
160
|
+
vhk memory list
|
|
161
|
+
vhk brief # ์ฝ์ ์ถ๋ ฅ + .vhk/brief.md
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Cursor ๊ถ์ฅ ์ํ์ค (v1.0 GA)
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
vhk init # ํ๋ก์ ํธ ์
์
|
|
168
|
+
vhk design + theme # ๋์์ธ ์์คํ
|
|
169
|
+
vhk context # AI ๋งฅ๋ฝ ํ์ผ ์์ฑ
|
|
170
|
+
... ๊ฐ๋ฐ ...
|
|
171
|
+
vhk memory add "<๊ฒฐ์ >" # ๊ฒฐ์ ๋์
|
|
172
|
+
vhk brief # ์ธ์
์ข
๋ฃ ์ ์ํ ๋ณด๊ณ ์
|
|
173
|
+
๋ค์ ์ธ์
์์: "์ปจํ
์คํธ ๋ณด์ฌ์ค" โ ์ด์ ๋งฅ๋ฝ ๋ณต์
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### v1.0.0 GA ์ ์ฑ
|
|
177
|
+
|
|
178
|
+
- **๊ณต๊ฐ API ์์ ์ฑ**: ๋ช
๋ น์ด ์ด๋ฆ, CLI ์ธ์, `.vhk/` ํ์ผ ํฌ๋งท์ v2.0๊น์ง breaking change ์์
|
|
179
|
+
- **deprecation ์ ์ฐจ**: ๋ช
๋ น์ด/์ต์
์ ๊ฑฐ ์ 1๊ฐ ๋ง์ด๋ ๋ฒ์ (1.x.0)์์ deprecation ๊ฒฝ๊ณ
|
|
180
|
+
- **i18n ํค**: `ko.ts`์ `t()` ํค ์ด๋ฆ์ ์์ . ์ ๊ท ํค ๋์ , ๊ธฐ์กด ํค ๋ฏธ์ ๊ฑฐ
|
|
181
|
+
- **MCP ์๋ฒ ๋๊ตฌ**: 8๊ฐ ๋๊ตฌ(save/undo/status/diff/ship/doctor/check/recap) ์ธํฐํ์ด์ค ์์
|
|
182
|
+
|
|
183
|
+
> **`vhk memory` vs Claude Code `auto memory`** โ `vhk memory`๋ **ํ๋ก์ ํธ ๋จ์** ๊ฒฐ์ ์ฌํญ(`.vhk/memory.json`, ํ ๊ณต์ ). Claude Code์ `auto memory`๋ **์ฌ์ฉ์ ๋จ์** (`~/.claude/projects/.../memory/`, ๊ฐ์ธ ์ปจํ
์คํธ). ๋์ ๋ณ๊ฐ.
|
|
184
|
+
|
|
140
185
|
## v0.9.0 ํ์ด๋ผ์ดํธ
|
|
141
186
|
|
|
142
187
|
| ๊ธฐ๋ฅ | ์ค๋ช
|
|
|
@@ -250,6 +295,10 @@ vhk ref open 1 # 1๋ฒ ๋ ํผ๋ฐ์ค๋ฅผ ๋ธ๋ผ์ฐ์ ๋ก ์ด๊ธฐ
|
|
|
250
295
|
| ๋ณด์ ๊ฐ์ฌ ํด์ค / ์ทจ์ฝ์ ํ์ธ | `vhk audit` |
|
|
251
296
|
| ํจํค์ง ๋งค๋์ ์ ํ | `vhk migrate` |
|
|
252
297
|
| vhk ์
๋ฐ์ดํธ ํด์ค | `vhk update` |
|
|
298
|
+
| ๋งฅ๋ฝ ๋ง๋ค์ด์ค / ์ปจํ
์คํธ ์์ฑ | `vhk context` |
|
|
299
|
+
| ์ปจํ
์คํธ ๋ณด์ฌ์ค / ๋งฅ๋ฝ ๋ณด์ฌ์ค | `vhk context-show` |
|
|
300
|
+
| ๊ธฐ์ต ๋ชฉ๋ก / ๊ฒฐ์ ์ฌํญ ํ์ธ | `vhk memory` (list) |
|
|
301
|
+
| ํ๋ก์ ํธ ๋ธ๋ฆฌํ / ์ํ ์์ฝ | `vhk brief` |
|
|
253
302
|
|
|
254
303
|
## ํน์ง
|
|
255
304
|
|
|
@@ -283,6 +283,10 @@ var ko = {
|
|
|
283
283
|
addTitle: "\uB808\uD37C\uB7F0\uC2A4 \uCD94\uAC00",
|
|
284
284
|
listTitle: "\uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D"
|
|
285
285
|
},
|
|
286
|
+
memory: {
|
|
287
|
+
addTitle: "\uAE30\uC5B5 \uCD94\uAC00",
|
|
288
|
+
listTitle: "\uAE30\uC5B5 \uBAA9\uB85D"
|
|
289
|
+
},
|
|
286
290
|
mcp: {
|
|
287
291
|
initTitle: "Cursor MCP \uC5F0\uB3D9 \uC124\uC815",
|
|
288
292
|
serverStarted: "VHK MCP \uC11C\uBC84 \uC2DC\uC791\uB428"
|
|
@@ -323,6 +327,13 @@ var ko = {
|
|
|
323
327
|
},
|
|
324
328
|
update: {
|
|
325
329
|
title: "VHK CLI \uC5C5\uB370\uC774\uD2B8"
|
|
330
|
+
},
|
|
331
|
+
context: {
|
|
332
|
+
title: "\uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8 \uC0DD\uC131",
|
|
333
|
+
showTitle: "\uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C"
|
|
334
|
+
},
|
|
335
|
+
brief: {
|
|
336
|
+
title: "\uD504\uB85C\uC81D\uD2B8 \uBE0C\uB9AC\uD551"
|
|
326
337
|
}
|
|
327
338
|
};
|
|
328
339
|
function lookup(path) {
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
safeExecFileStream,
|
|
11
11
|
startMcpServer,
|
|
12
12
|
t
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7NGBIIA3.js";
|
|
14
14
|
|
|
15
15
|
// node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js
|
|
16
16
|
var require_ignore = __commonJS({
|
|
@@ -473,7 +473,7 @@ var require_ignore = __commonJS({
|
|
|
473
473
|
// src/index.ts
|
|
474
474
|
import { Command, Help } from "commander";
|
|
475
475
|
import inquirer14 from "inquirer";
|
|
476
|
-
import
|
|
476
|
+
import fs15 from "fs";
|
|
477
477
|
import path15 from "path";
|
|
478
478
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
479
479
|
|
|
@@ -511,7 +511,7 @@ var RULES = [
|
|
|
511
511
|
command: "init",
|
|
512
512
|
explanation: "\uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791 (vhk \uC2DC\uC791)",
|
|
513
513
|
confidence: "high",
|
|
514
|
-
test: (t2) => (/ํ๋ก์ ํธ.*(๋ง๋ค|์์)|ํด๋.*๋ง๋ค|๋ง๋ค๊ณ \s*์ถ|ํ๋ค์ค|์ด๊ธฐํ/.test(t2) || /^์์$/.test(t2)) && !/๋์์ธ|design|ํ๋ ํธ|palette|ํ
๋ง|theme|๋ ํผ๋ฐ์ค|reference|๋คํฌ\s*๋ชจ๋|๋ผ์ดํธ\s*๋ชจ๋|์์\s
|
|
514
|
+
test: (t2) => (/ํ๋ก์ ํธ.*(๋ง๋ค|์์)|ํด๋.*๋ง๋ค|๋ง๋ค๊ณ \s*์ถ|ํ๋ค์ค|์ด๊ธฐํ/.test(t2) || /^์์$/.test(t2)) && !/๋์์ธ|design|ํ๋ ํธ|palette|ํ
๋ง|theme|๋ ํผ๋ฐ์ค|reference|๋คํฌ\s*๋ชจ๋|๋ผ์ดํธ\s*๋ชจ๋|์์\s*๋ชจ๋|๋ธ๋ฆฌํ|brief|์ปจํ
์คํธ|context|๋งฅ๋ฝ|๊ธฐ์ต|memory/.test(t2)
|
|
515
515
|
},
|
|
516
516
|
{
|
|
517
517
|
command: "mcp-init",
|
|
@@ -567,6 +567,30 @@ var RULES = [
|
|
|
567
567
|
confidence: "high",
|
|
568
568
|
test: (t2) => /์
๋ฐ์ดํธ|update|๋ฒ์ \s*์
|์ต์ \s*๋ฒ์ |์
ํ\s*์
๋ฐ์ดํธ|vhk.*์ต์ |vhk.*์
๋ฐ์ดํธ/.test(t2)
|
|
569
569
|
},
|
|
570
|
+
{
|
|
571
|
+
command: "context-show",
|
|
572
|
+
explanation: "\uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C \uBCF4\uAE30 (vhk context-show)",
|
|
573
|
+
confidence: "high",
|
|
574
|
+
test: (t2) => /๋งฅ๋ฝ\s*(๋ณด|ํ์ธ|๋ณด์ฌ)|์ปจํ
์คํธ\s*(๋ณด|ํ์ธ|๋ณด์ฌ)|context\s*show/.test(t2)
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
command: "context",
|
|
578
|
+
explanation: "\uD504\uB85C\uC81D\uD2B8 \uB9E5\uB77D \uC0DD\uC131 (vhk context)",
|
|
579
|
+
confidence: "high",
|
|
580
|
+
test: (t2) => /(^๋งฅ๋ฝ$|^์ปจํ
์คํธ$|^context$|๋งฅ๋ฝ\s*(๋ง๋ค|์์ฑ|๊ฐฑ์ |์
๋ฐ์ดํธ)|์ปจํ
์คํธ\s*(๋ง๋ค|์์ฑ|๊ฐฑ์ |์
๋ฐ์ดํธ)|ํ๋ก์ ํธ\s*๋งฅ๋ฝ|ํ๋ก์ ํธ\s*์ ๋ณด\s*์์ฑ)/.test(t2) && !/๋ณด|ํ์ธ|๋ณด์ฌ|show/.test(t2)
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
command: "memory",
|
|
584
|
+
explanation: "\uAE30\uC5B5 \uBAA9\uB85D \uC870\uD68C (vhk memory list)",
|
|
585
|
+
confidence: "high",
|
|
586
|
+
test: (t2) => /^๊ธฐ์ต$|๊ธฐ์ต\s*(๋ชฉ๋ก|๋ณด|ํ์ธ|๋ญ)|memory.*list|๊ฒฐ์ ์ฌํญ\s*(๋ชฉ๋ก|ํ์ธ|๋ณด์ฌ)/.test(t2) && !/(์ถ๊ฐ|add|์ญ์ |remove|์ ์ฅ|๊ธฐ๋กํด)/.test(t2)
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
command: "brief",
|
|
590
|
+
explanation: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC694\uC57D (vhk brief)",
|
|
591
|
+
confidence: "high",
|
|
592
|
+
test: (t2) => /๋ธ๋ฆฌํ|brief|์ํ\s*์์ฝ|ํ๋ก์ ํธ\s*์์ฝ|์์ฝ\s*(๋ณด๊ณ |๋ฆฌํฌํธ|๋ณด์ฌ|๋ง๋ค)|๋ณด๊ณ ์\s*(๋ง๋ค|์์ฑ|๋ณด์ฌ)/.test(t2)
|
|
593
|
+
},
|
|
570
594
|
{
|
|
571
595
|
command: "secure",
|
|
572
596
|
explanation: "\uBCF4\uC548 \uC2A4\uCE94 (vhk \uBCF4\uC548)",
|
|
@@ -741,6 +765,14 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
|
|
|
741
765
|
"\uC804\uD658",
|
|
742
766
|
"update",
|
|
743
767
|
"\uC5C5\uB370\uC774\uD2B8",
|
|
768
|
+
"context",
|
|
769
|
+
"\uB9E5\uB77D",
|
|
770
|
+
"context-show",
|
|
771
|
+
"\uB9E5\uB77D\uBCF4\uAE30",
|
|
772
|
+
"memory",
|
|
773
|
+
"\uAE30\uC5B5",
|
|
774
|
+
"brief",
|
|
775
|
+
"\uBE0C\uB9AC\uD551",
|
|
744
776
|
"help"
|
|
745
777
|
]);
|
|
746
778
|
function isOptionToken(token) {
|
|
@@ -764,7 +796,7 @@ function detectNaturalLanguageInput(argv) {
|
|
|
764
796
|
}
|
|
765
797
|
|
|
766
798
|
// src/lib/nlp-run.ts
|
|
767
|
-
import
|
|
799
|
+
import chalk28 from "chalk";
|
|
768
800
|
import inquirer13 from "inquirer";
|
|
769
801
|
|
|
770
802
|
// src/commands/gate.ts
|
|
@@ -1690,7 +1722,7 @@ function nextAdrNumber(adrDir) {
|
|
|
1690
1722
|
function slugify(title) {
|
|
1691
1723
|
return title.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9๊ฐ-ํฃ-]/g, "").slice(0, 40) || "decision";
|
|
1692
1724
|
}
|
|
1693
|
-
function createAdrFile(cwd, title,
|
|
1725
|
+
function createAdrFile(cwd, title, context2, decision, consequences) {
|
|
1694
1726
|
const adrDir = path5.join(cwd, "docs", "adr");
|
|
1695
1727
|
if (!fs4.existsSync(adrDir)) fs4.mkdirSync(adrDir, { recursive: true });
|
|
1696
1728
|
const num = nextAdrNumber(adrDir);
|
|
@@ -1708,7 +1740,7 @@ function createAdrFile(cwd, title, context, decision, consequences) {
|
|
|
1708
1740
|
`# ADR-${String(num).padStart(3, "0")}: ${title}`,
|
|
1709
1741
|
"",
|
|
1710
1742
|
"## \uB9E5\uB77D (Context)",
|
|
1711
|
-
|
|
1743
|
+
context2,
|
|
1712
1744
|
"",
|
|
1713
1745
|
"## \uACB0\uC815 (Decision)",
|
|
1714
1746
|
decision,
|
|
@@ -3136,17 +3168,17 @@ ${t("undo.recentHeader")}`));
|
|
|
3136
3168
|
|
|
3137
3169
|
// src/commands/status.ts
|
|
3138
3170
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
3139
|
-
import
|
|
3171
|
+
import fs14 from "fs";
|
|
3140
3172
|
import path14 from "path";
|
|
3141
3173
|
import chalk13 from "chalk";
|
|
3142
3174
|
|
|
3143
3175
|
// src/lib/read-json.ts
|
|
3144
|
-
import
|
|
3176
|
+
import { readFileSync } from "fs";
|
|
3145
3177
|
function stripBom(text) {
|
|
3146
3178
|
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
3147
3179
|
}
|
|
3148
3180
|
function readJsonFile(filePath) {
|
|
3149
|
-
const raw = stripBom(
|
|
3181
|
+
const raw = stripBom(readFileSync(filePath, "utf-8"));
|
|
3150
3182
|
return JSON.parse(raw);
|
|
3151
3183
|
}
|
|
3152
3184
|
|
|
@@ -3189,7 +3221,7 @@ function parseRecentCommitLines(logOutput) {
|
|
|
3189
3221
|
}
|
|
3190
3222
|
function readProjectPackage(cwd = process.cwd()) {
|
|
3191
3223
|
const pkgPath = path14.join(cwd, "package.json");
|
|
3192
|
-
if (!
|
|
3224
|
+
if (!fs14.existsSync(pkgPath)) return null;
|
|
3193
3225
|
try {
|
|
3194
3226
|
const pkg = readJsonFile(pkgPath);
|
|
3195
3227
|
if (!pkg.name && !pkg.version) return null;
|
|
@@ -3358,7 +3390,7 @@ ${t("diff.summaryHeader")}`));
|
|
|
3358
3390
|
}
|
|
3359
3391
|
|
|
3360
3392
|
// src/commands/mcp-init.ts
|
|
3361
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3393
|
+
import { existsSync, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
3362
3394
|
import { join } from "path";
|
|
3363
3395
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3364
3396
|
import chalk15 from "chalk";
|
|
@@ -3366,7 +3398,7 @@ function resolveVhkMcpPath() {
|
|
|
3366
3398
|
try {
|
|
3367
3399
|
const pkgPath = join(process.cwd(), "package.json");
|
|
3368
3400
|
if (existsSync(pkgPath)) {
|
|
3369
|
-
const pkg = JSON.parse(
|
|
3401
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
3370
3402
|
if (pkg.name === "@byh3071/vhk") {
|
|
3371
3403
|
return join(process.cwd(), "dist", "mcp", "index.js");
|
|
3372
3404
|
}
|
|
@@ -3395,7 +3427,7 @@ async function mcpInit() {
|
|
|
3395
3427
|
let config;
|
|
3396
3428
|
if (existsSync(configPath)) {
|
|
3397
3429
|
try {
|
|
3398
|
-
const parsed = JSON.parse(
|
|
3430
|
+
const parsed = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
3399
3431
|
config = {
|
|
3400
3432
|
mcpServers: { ...parsed.mcpServers ?? {}, vhk: vhkEntry }
|
|
3401
3433
|
};
|
|
@@ -3518,7 +3550,7 @@ ${t("deploy.deploying")}
|
|
|
3518
3550
|
}
|
|
3519
3551
|
|
|
3520
3552
|
// src/commands/publish.ts
|
|
3521
|
-
import { existsSync as existsSync3, readFileSync as
|
|
3553
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
3522
3554
|
import chalk17 from "chalk";
|
|
3523
3555
|
import inquirer8 from "inquirer";
|
|
3524
3556
|
import ora2 from "ora";
|
|
@@ -3542,7 +3574,7 @@ async function publish() {
|
|
|
3542
3574
|
}
|
|
3543
3575
|
let pkg;
|
|
3544
3576
|
try {
|
|
3545
|
-
pkg = JSON.parse(
|
|
3577
|
+
pkg = JSON.parse(readFileSync3("package.json", "utf-8"));
|
|
3546
3578
|
} catch {
|
|
3547
3579
|
console.log(chalk17.red("\u274C package.json \uD30C\uC2F1 \uC2E4\uD328"));
|
|
3548
3580
|
return;
|
|
@@ -3867,13 +3899,13 @@ async function theme() {
|
|
|
3867
3899
|
}
|
|
3868
3900
|
|
|
3869
3901
|
// src/commands/ref.ts
|
|
3870
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as
|
|
3902
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
3871
3903
|
import chalk20 from "chalk";
|
|
3872
3904
|
var REFS_PATH = ".vhk/refs.json";
|
|
3873
3905
|
function loadRefs() {
|
|
3874
3906
|
if (!existsSync6(REFS_PATH)) return [];
|
|
3875
3907
|
try {
|
|
3876
|
-
const raw =
|
|
3908
|
+
const raw = readFileSync4(REFS_PATH, "utf-8");
|
|
3877
3909
|
const parsed = JSON.parse(raw);
|
|
3878
3910
|
return Array.isArray(parsed) ? parsed : [];
|
|
3879
3911
|
} catch {
|
|
@@ -3966,7 +3998,7 @@ async function refOpen(indexStr) {
|
|
|
3966
3998
|
}
|
|
3967
3999
|
|
|
3968
4000
|
// src/commands/harness.ts
|
|
3969
|
-
import { existsSync as existsSync7, readFileSync as
|
|
4001
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
3970
4002
|
import chalk21 from "chalk";
|
|
3971
4003
|
import ora3 from "ora";
|
|
3972
4004
|
function detectPM() {
|
|
@@ -3981,7 +4013,7 @@ function detectChecks() {
|
|
|
3981
4013
|
const checks = [];
|
|
3982
4014
|
let pkg = {};
|
|
3983
4015
|
try {
|
|
3984
|
-
pkg = JSON.parse(
|
|
4016
|
+
pkg = JSON.parse(readFileSync5("package.json", "utf-8"));
|
|
3985
4017
|
} catch {
|
|
3986
4018
|
return checks;
|
|
3987
4019
|
}
|
|
@@ -4251,7 +4283,7 @@ async function migrate(target) {
|
|
|
4251
4283
|
|
|
4252
4284
|
// src/commands/update.ts
|
|
4253
4285
|
import { execSync as execSync3 } from "child_process";
|
|
4254
|
-
import { existsSync as existsSync10, readFileSync as
|
|
4286
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
|
|
4255
4287
|
import { dirname, join as join2 } from "path";
|
|
4256
4288
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4257
4289
|
import chalk24 from "chalk";
|
|
@@ -4262,7 +4294,7 @@ function getCurrentVersion() {
|
|
|
4262
4294
|
for (const pkgPath of [join2(dir, "../package.json"), join2(dir, "../../package.json")]) {
|
|
4263
4295
|
try {
|
|
4264
4296
|
if (existsSync10(pkgPath)) {
|
|
4265
|
-
const pkg = JSON.parse(
|
|
4297
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
|
|
4266
4298
|
if (pkg.version) return pkg.version;
|
|
4267
4299
|
}
|
|
4268
4300
|
} catch {
|
|
@@ -4326,6 +4358,369 @@ async function update() {
|
|
|
4326
4358
|
}
|
|
4327
4359
|
}
|
|
4328
4360
|
|
|
4361
|
+
// src/commands/context.ts
|
|
4362
|
+
import {
|
|
4363
|
+
existsSync as existsSync11,
|
|
4364
|
+
mkdirSync as mkdirSync5,
|
|
4365
|
+
readFileSync as readFileSync7,
|
|
4366
|
+
readdirSync,
|
|
4367
|
+
statSync,
|
|
4368
|
+
writeFileSync as writeFileSync6
|
|
4369
|
+
} from "fs";
|
|
4370
|
+
import { join as join3 } from "path";
|
|
4371
|
+
import chalk25 from "chalk";
|
|
4372
|
+
var CONTEXT_PATH = ".vhk/context.md";
|
|
4373
|
+
var IGNORE_DIRS2 = /* @__PURE__ */ new Set([
|
|
4374
|
+
"node_modules",
|
|
4375
|
+
".git",
|
|
4376
|
+
"dist",
|
|
4377
|
+
".next",
|
|
4378
|
+
".nuxt",
|
|
4379
|
+
".output",
|
|
4380
|
+
"coverage",
|
|
4381
|
+
".cache",
|
|
4382
|
+
".turbo",
|
|
4383
|
+
".vhk"
|
|
4384
|
+
]);
|
|
4385
|
+
function buildTree(dir, prefix = "", maxDepth = 3, depth = 0) {
|
|
4386
|
+
if (depth >= maxDepth) return [];
|
|
4387
|
+
const lines = [];
|
|
4388
|
+
try {
|
|
4389
|
+
const entries = readdirSync(dir);
|
|
4390
|
+
const filtered = entries.filter(
|
|
4391
|
+
(e) => (!e.startsWith(".") || e === ".env.example") && !IGNORE_DIRS2.has(e)
|
|
4392
|
+
);
|
|
4393
|
+
filtered.forEach((entry, index) => {
|
|
4394
|
+
const isLast = index === filtered.length - 1;
|
|
4395
|
+
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
4396
|
+
const fullPath = join3(dir, entry);
|
|
4397
|
+
const stat = statSync(fullPath);
|
|
4398
|
+
const isDir = stat.isDirectory();
|
|
4399
|
+
lines.push(`${prefix}${connector}${entry}${isDir ? "/" : ""}`);
|
|
4400
|
+
if (isDir) {
|
|
4401
|
+
const nextPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
4402
|
+
lines.push(...buildTree(fullPath, nextPrefix, maxDepth, depth + 1));
|
|
4403
|
+
}
|
|
4404
|
+
});
|
|
4405
|
+
} catch {
|
|
4406
|
+
}
|
|
4407
|
+
return lines;
|
|
4408
|
+
}
|
|
4409
|
+
function extractTechStack() {
|
|
4410
|
+
const stack = {};
|
|
4411
|
+
try {
|
|
4412
|
+
const pkg = readJsonFile("package.json");
|
|
4413
|
+
const all = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
4414
|
+
if (all.next) stack["\uD504\uB808\uC784\uC6CC\uD06C"] = `Next.js ${all.next}`;
|
|
4415
|
+
else if (all.nuxt) stack["\uD504\uB808\uC784\uC6CC\uD06C"] = `Nuxt ${all.nuxt}`;
|
|
4416
|
+
else if (all.react) stack["\uD504\uB808\uC784\uC6CC\uD06C"] = `React ${all.react}`;
|
|
4417
|
+
else if (all.vue) stack["\uD504\uB808\uC784\uC6CC\uD06C"] = `Vue ${all.vue}`;
|
|
4418
|
+
else if (all.svelte) stack["\uD504\uB808\uC784\uC6CC\uD06C"] = `Svelte ${all.svelte}`;
|
|
4419
|
+
if (all.typescript) stack["\uC5B8\uC5B4"] = `TypeScript ${all.typescript}`;
|
|
4420
|
+
if (all.tailwindcss) stack["\uC2A4\uD0C0\uC77C"] = `Tailwind CSS ${all.tailwindcss}`;
|
|
4421
|
+
if (all.tsup) stack["\uBE4C\uB4DC"] = "tsup";
|
|
4422
|
+
else if (all.vite) stack["\uBE4C\uB4DC"] = `Vite ${all.vite}`;
|
|
4423
|
+
else if (all.webpack) stack["\uBE4C\uB4DC"] = "webpack";
|
|
4424
|
+
if (all.vitest) stack["\uD14C\uC2A4\uD2B8"] = "vitest";
|
|
4425
|
+
else if (all.jest) stack["\uD14C\uC2A4\uD2B8"] = "jest";
|
|
4426
|
+
if (all.commander) stack["CLI"] = "commander";
|
|
4427
|
+
if (all.inquirer) stack["\uC778\uD130\uB799\uD2F0\uBE0C"] = "inquirer";
|
|
4428
|
+
if (existsSync11("pnpm-lock.yaml")) stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "pnpm";
|
|
4429
|
+
else if (existsSync11("yarn.lock")) stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "yarn";
|
|
4430
|
+
else stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "npm";
|
|
4431
|
+
if (pkg.name) stack["\uD328\uD0A4\uC9C0 \uC774\uB984"] = pkg.name;
|
|
4432
|
+
if (pkg.version) stack["\uBC84\uC804"] = pkg.version;
|
|
4433
|
+
} catch {
|
|
4434
|
+
}
|
|
4435
|
+
return stack;
|
|
4436
|
+
}
|
|
4437
|
+
function getVhkCommands() {
|
|
4438
|
+
return [
|
|
4439
|
+
"gate \u2014 \uC544\uC774\uB514\uC5B4 \uAC80\uC99D",
|
|
4440
|
+
"init \u2014 \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654",
|
|
4441
|
+
"recap \u2014 \uC138\uC158 \uC694\uC57D \uC800\uC7A5",
|
|
4442
|
+
"sync \u2014 \uADDC\uCE59 \uD30C\uC77C \uB3D9\uAE30\uD654",
|
|
4443
|
+
"check \u2014 \uADDC\uCE59 \uC810\uAC80",
|
|
4444
|
+
"secure \u2014 \uBCF4\uC548 \uC2A4\uCE94",
|
|
4445
|
+
"ship \u2014 \uBC30\uD3EC \uCCB4\uD06C + \uD68C\uACE0",
|
|
4446
|
+
"doctor \u2014 \uD658\uACBD \uC9C4\uB2E8",
|
|
4447
|
+
"save \u2014 git \uC800\uC7A5 (add+commit+push)",
|
|
4448
|
+
"undo \u2014 \uCD5C\uADFC \uCEE4\uBC0B \uB418\uB3CC\uB9AC\uAE30",
|
|
4449
|
+
"status \u2014 git \uC0C1\uD0DC \uD655\uC778",
|
|
4450
|
+
"diff \u2014 git \uBCC0\uACBD \uC0AC\uD56D \uC694\uC57D",
|
|
4451
|
+
"deploy \u2014 \uD504\uB85C\uB355\uC158 \uBC30\uD3EC",
|
|
4452
|
+
"env \u2014 \uD658\uACBD\uBCC0\uC218 \uAD00\uB9AC",
|
|
4453
|
+
"publish \u2014 npm \uBC30\uD3EC \uC790\uB3D9\uD654",
|
|
4454
|
+
"design \u2014 \uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131",
|
|
4455
|
+
"design-palette \u2014 \uCEEC\uB7EC \uD314\uB808\uD2B8 \uC120\uD0DD",
|
|
4456
|
+
"theme \u2014 \uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC",
|
|
4457
|
+
"ref add|list|open \u2014 \uB808\uD37C\uB7F0\uC2A4 URL \uAD00\uB9AC",
|
|
4458
|
+
"harness \u2014 \uD1B5\uD569 \uD488\uC9C8 \uC810\uAC80",
|
|
4459
|
+
"audit \u2014 \uBCF4\uC548 \uCDE8\uC57D\uC810 \uAC10\uC0AC",
|
|
4460
|
+
"migrate \u2014 \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800 \uC804\uD658",
|
|
4461
|
+
"update \u2014 VHK CLI \uC140\uD504 \uC5C5\uB370\uC774\uD2B8",
|
|
4462
|
+
"context \u2014 \uD504\uB85C\uC81D\uD2B8 \uB9E5\uB77D \uC0DD\uC131",
|
|
4463
|
+
"context-show \u2014 \uB9E5\uB77D \uD30C\uC77C \uBCF4\uAE30",
|
|
4464
|
+
"memory add|list|remove \u2014 \uACB0\uC815\uC0AC\uD56D \uAE30\uC5B5",
|
|
4465
|
+
"brief \u2014 \uD504\uB85C\uC81D\uD2B8 \uC694\uC57D \uBCF4\uACE0\uC11C",
|
|
4466
|
+
"mcp \u2014 MCP \uC11C\uBC84 \uC2DC\uC791",
|
|
4467
|
+
"mcp-init \u2014 Cursor MCP \uC124\uC815"
|
|
4468
|
+
];
|
|
4469
|
+
}
|
|
4470
|
+
async function context() {
|
|
4471
|
+
console.log(chalk25.bold("\n\u{1F9E0} " + t("context.title")));
|
|
4472
|
+
console.log(chalk25.gray("\u2500".repeat(40)));
|
|
4473
|
+
const stack = extractTechStack();
|
|
4474
|
+
const tree = buildTree(".").join("\n");
|
|
4475
|
+
const commands = getVhkCommands();
|
|
4476
|
+
const lines = [];
|
|
4477
|
+
lines.push("# \uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8");
|
|
4478
|
+
lines.push("");
|
|
4479
|
+
lines.push("> \uC774 \uD30C\uC77C\uC740 `vhk context`\uB85C \uC790\uB3D9 \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
4480
|
+
lines.push("> AI \uC5B4\uC2DC\uC2A4\uD134\uD2B8\uC5D0\uAC8C \uD504\uB85C\uC81D\uD2B8 \uB9E5\uB77D\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4.");
|
|
4481
|
+
lines.push("");
|
|
4482
|
+
lines.push("## \uAE30\uC220 \uC2A4\uD0DD");
|
|
4483
|
+
lines.push("");
|
|
4484
|
+
for (const [key, value] of Object.entries(stack)) {
|
|
4485
|
+
lines.push(`- **${key}**: ${value}`);
|
|
4486
|
+
}
|
|
4487
|
+
lines.push("");
|
|
4488
|
+
lines.push("## \uB514\uB809\uD1A0\uB9AC \uAD6C\uC870");
|
|
4489
|
+
lines.push("");
|
|
4490
|
+
lines.push("```");
|
|
4491
|
+
lines.push(tree);
|
|
4492
|
+
lines.push("```");
|
|
4493
|
+
lines.push("");
|
|
4494
|
+
lines.push("## VHK CLI \uBA85\uB839\uC5B4");
|
|
4495
|
+
lines.push("");
|
|
4496
|
+
for (const cmd of commands) {
|
|
4497
|
+
lines.push(`- \`vhk ${cmd}\``);
|
|
4498
|
+
}
|
|
4499
|
+
lines.push("");
|
|
4500
|
+
if (existsSync11(".vhk/memory.json")) {
|
|
4501
|
+
try {
|
|
4502
|
+
const memories = readJsonFile(
|
|
4503
|
+
".vhk/memory.json"
|
|
4504
|
+
);
|
|
4505
|
+
if (Array.isArray(memories) && memories.length > 0) {
|
|
4506
|
+
lines.push("## \uC800\uC7A5\uB41C \uACB0\uC815\uC0AC\uD56D");
|
|
4507
|
+
lines.push("");
|
|
4508
|
+
for (const m of memories) {
|
|
4509
|
+
const date = new Date(m.addedAt).toLocaleDateString("ko-KR");
|
|
4510
|
+
lines.push(`- ${m.content} _(${date})_`);
|
|
4511
|
+
}
|
|
4512
|
+
lines.push("");
|
|
4513
|
+
}
|
|
4514
|
+
} catch {
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
lines.push("---");
|
|
4518
|
+
lines.push("");
|
|
4519
|
+
lines.push(`_\uC0DD\uC131: ${(/* @__PURE__ */ new Date()).toLocaleString("ko-KR")}_`);
|
|
4520
|
+
lines.push("");
|
|
4521
|
+
mkdirSync5(".vhk", { recursive: true });
|
|
4522
|
+
writeFileSync6(CONTEXT_PATH, lines.join("\n"), "utf-8");
|
|
4523
|
+
console.log(chalk25.green(`
|
|
4524
|
+
\u2705 ${CONTEXT_PATH} \uC0DD\uC131 \uC644\uB8CC!`));
|
|
4525
|
+
console.log(chalk25.gray(` \uAE30\uC220 \uC2A4\uD0DD ${Object.keys(stack).length}\uAC1C \uAC10\uC9C0`));
|
|
4526
|
+
console.log(chalk25.gray(" AI \uC5B4\uC2DC\uC2A4\uD134\uD2B8\uC5D0\uAC8C \uC774 \uD30C\uC77C\uC744 \uCC38\uC870\uD558\uAC8C \uD558\uC138\uC694."));
|
|
4527
|
+
printNextStep({
|
|
4528
|
+
message: "\uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC!",
|
|
4529
|
+
command: "vhk context-show",
|
|
4530
|
+
cursorHint: "\uCEE8\uD14D\uC2A4\uD2B8 \uBCF4\uC5EC\uC918"
|
|
4531
|
+
});
|
|
4532
|
+
}
|
|
4533
|
+
async function contextShow() {
|
|
4534
|
+
console.log(chalk25.bold("\n\u{1F4C4} " + t("context.showTitle")));
|
|
4535
|
+
console.log(chalk25.gray("\u2500".repeat(40)));
|
|
4536
|
+
if (!existsSync11(CONTEXT_PATH)) {
|
|
4537
|
+
console.log(chalk25.yellow("\n\u26A0\uFE0F \uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
4538
|
+
console.log(chalk25.gray(" vhk context\uB97C \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694."));
|
|
4539
|
+
return;
|
|
4540
|
+
}
|
|
4541
|
+
const content = readFileSync7(CONTEXT_PATH, "utf-8");
|
|
4542
|
+
console.log("\n" + content);
|
|
4543
|
+
}
|
|
4544
|
+
|
|
4545
|
+
// src/commands/memory.ts
|
|
4546
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
4547
|
+
import chalk26 from "chalk";
|
|
4548
|
+
var MEMORY_PATH = ".vhk/memory.json";
|
|
4549
|
+
function loadMemories() {
|
|
4550
|
+
if (!existsSync12(MEMORY_PATH)) return [];
|
|
4551
|
+
try {
|
|
4552
|
+
const parsed = readJsonFile(MEMORY_PATH);
|
|
4553
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
4554
|
+
} catch {
|
|
4555
|
+
return [];
|
|
4556
|
+
}
|
|
4557
|
+
}
|
|
4558
|
+
function saveMemories(memories) {
|
|
4559
|
+
mkdirSync6(".vhk", { recursive: true });
|
|
4560
|
+
writeFileSync7(MEMORY_PATH, JSON.stringify(memories, null, 2) + "\n", "utf-8");
|
|
4561
|
+
}
|
|
4562
|
+
async function memoryAdd(content, tags) {
|
|
4563
|
+
console.log(chalk26.bold("\n\u{1F9E0} " + t("memory.addTitle")));
|
|
4564
|
+
console.log(chalk26.gray("\u2500".repeat(40)));
|
|
4565
|
+
if (!content) {
|
|
4566
|
+
console.log(chalk26.red("\u274C \uAE30\uC5B5\uD560 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694."));
|
|
4567
|
+
console.log(chalk26.gray(' \uC608: vhk memory add "API\uB294 tRPC \uC0AC\uC6A9\uD558\uAE30\uB85C \uACB0\uC815"'));
|
|
4568
|
+
return;
|
|
4569
|
+
}
|
|
4570
|
+
const memories = loadMemories();
|
|
4571
|
+
memories.push({
|
|
4572
|
+
content,
|
|
4573
|
+
addedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4574
|
+
tags: tags && tags.length > 0 ? tags : []
|
|
4575
|
+
});
|
|
4576
|
+
saveMemories(memories);
|
|
4577
|
+
console.log(chalk26.green(`
|
|
4578
|
+
\u2705 \uAE30\uC5B5 \uC800\uC7A5\uB428 (#${memories.length})`));
|
|
4579
|
+
console.log(chalk26.cyan(` \u{1F4DD} ${content}`));
|
|
4580
|
+
printNextStep({
|
|
4581
|
+
message: "\uAE30\uC5B5 \uC800\uC7A5 \uC644\uB8CC!",
|
|
4582
|
+
command: "vhk memory list",
|
|
4583
|
+
cursorHint: "\uAE30\uC5B5 \uBAA9\uB85D \uBCF4\uC5EC\uC918"
|
|
4584
|
+
});
|
|
4585
|
+
}
|
|
4586
|
+
async function memoryList() {
|
|
4587
|
+
console.log(chalk26.bold("\n\u{1F9E0} " + t("memory.listTitle")));
|
|
4588
|
+
console.log(chalk26.gray("\u2500".repeat(40)));
|
|
4589
|
+
const memories = loadMemories();
|
|
4590
|
+
if (memories.length === 0) {
|
|
4591
|
+
console.log(chalk26.yellow("\n\u{1F4ED} \uC800\uC7A5\uB41C \uAE30\uC5B5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
4592
|
+
console.log(chalk26.gray(' vhk memory add "\uB0B4\uC6A9"\uC73C\uB85C \uCD94\uAC00\uD558\uC138\uC694.'));
|
|
4593
|
+
return;
|
|
4594
|
+
}
|
|
4595
|
+
console.log(chalk26.cyan(`
|
|
4596
|
+
\uCD1D ${memories.length}\uAC1C\uC758 \uAE30\uC5B5:
|
|
4597
|
+
`));
|
|
4598
|
+
memories.forEach((m, index) => {
|
|
4599
|
+
const date = new Date(m.addedAt).toLocaleDateString("ko-KR");
|
|
4600
|
+
console.log(chalk26.white(` [${index + 1}] ${m.content}`));
|
|
4601
|
+
if (m.tags && m.tags.length > 0) {
|
|
4602
|
+
console.log(chalk26.blue(` \u{1F3F7}\uFE0F ${m.tags.join(", ")}`));
|
|
4603
|
+
}
|
|
4604
|
+
console.log(chalk26.gray(` \u{1F4C5} ${date}`));
|
|
4605
|
+
console.log("");
|
|
4606
|
+
});
|
|
4607
|
+
}
|
|
4608
|
+
async function memoryRemove(indexStr) {
|
|
4609
|
+
const memories = loadMemories();
|
|
4610
|
+
const idx = parseInt(indexStr, 10) - 1;
|
|
4611
|
+
if (Number.isNaN(idx) || idx < 0 || idx >= memories.length) {
|
|
4612
|
+
console.log(chalk26.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uBC88\uD638\uC785\uB2C8\uB2E4. (1~${memories.length || 0})`));
|
|
4613
|
+
return;
|
|
4614
|
+
}
|
|
4615
|
+
const removed = memories.splice(idx, 1)[0];
|
|
4616
|
+
saveMemories(memories);
|
|
4617
|
+
console.log(chalk26.green("\n\u2705 \uAE30\uC5B5 \uC0AD\uC81C\uB428:"));
|
|
4618
|
+
console.log(chalk26.gray(` ${removed.content}`));
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4621
|
+
// src/commands/brief.ts
|
|
4622
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
4623
|
+
import chalk27 from "chalk";
|
|
4624
|
+
var BRIEF_PATH = ".vhk/brief.md";
|
|
4625
|
+
function git2(args) {
|
|
4626
|
+
const result = safeExecFile("git", args);
|
|
4627
|
+
return result.ok ? result.out : "";
|
|
4628
|
+
}
|
|
4629
|
+
async function brief() {
|
|
4630
|
+
console.log(chalk27.bold("\n\u{1F4CB} " + t("brief.title")));
|
|
4631
|
+
console.log(chalk27.gray("\u2500".repeat(40)));
|
|
4632
|
+
const lines = [];
|
|
4633
|
+
lines.push("# \uD504\uB85C\uC81D\uD2B8 \uBE0C\uB9AC\uD551");
|
|
4634
|
+
lines.push("");
|
|
4635
|
+
lines.push(`> \uC0DD\uC131: ${(/* @__PURE__ */ new Date()).toLocaleString("ko-KR")}`);
|
|
4636
|
+
lines.push("");
|
|
4637
|
+
try {
|
|
4638
|
+
const pkg = readJsonFile("package.json");
|
|
4639
|
+
lines.push("## \uD504\uB85C\uC81D\uD2B8 \uC815\uBCF4");
|
|
4640
|
+
lines.push("");
|
|
4641
|
+
lines.push(`- **\uC774\uB984**: ${pkg.name ?? "\uBBF8\uC815"}`);
|
|
4642
|
+
lines.push(`- **\uBC84\uC804**: ${pkg.version ?? "\uBBF8\uC815"}`);
|
|
4643
|
+
lines.push(`- **\uC124\uBA85**: ${pkg.description ?? "\uC5C6\uC74C"}`);
|
|
4644
|
+
const deps = Object.keys(pkg.dependencies ?? {}).length;
|
|
4645
|
+
const devDeps = Object.keys(pkg.devDependencies ?? {}).length;
|
|
4646
|
+
lines.push(`- **\uC758\uC874\uC131**: ${deps}\uAC1C (dev: ${devDeps}\uAC1C)`);
|
|
4647
|
+
lines.push("");
|
|
4648
|
+
} catch {
|
|
4649
|
+
lines.push("## \uD504\uB85C\uC81D\uD2B8 \uC815\uBCF4");
|
|
4650
|
+
lines.push("");
|
|
4651
|
+
lines.push("\u26A0\uFE0F package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
4652
|
+
lines.push("");
|
|
4653
|
+
}
|
|
4654
|
+
const branch = git2(["branch", "--show-current"]);
|
|
4655
|
+
const lastCommit = git2(["log", "-1", "--pretty=format:%h %s (%cr)"]);
|
|
4656
|
+
const uncommitted = git2(["status", "--porcelain"]);
|
|
4657
|
+
const totalCommits = git2(["rev-list", "--count", "HEAD"]);
|
|
4658
|
+
lines.push("## Git \uC0C1\uD0DC");
|
|
4659
|
+
lines.push("");
|
|
4660
|
+
lines.push(`- **\uD604\uC7AC \uBE0C\uB79C\uCE58**: ${branch || "\uC54C \uC218 \uC5C6\uC74C"}`);
|
|
4661
|
+
lines.push(`- **\uB9C8\uC9C0\uB9C9 \uCEE4\uBC0B**: ${lastCommit || "\uC5C6\uC74C"}`);
|
|
4662
|
+
lines.push(`- **\uCD1D \uCEE4\uBC0B \uC218**: ${totalCommits || "\uC54C \uC218 \uC5C6\uC74C"}`);
|
|
4663
|
+
lines.push(
|
|
4664
|
+
`- **\uBBF8\uCEE4\uBC0B \uBCC0\uACBD**: ${uncommitted ? `${uncommitted.split("\n").length}\uAC1C \uD30C\uC77C` : "\uC5C6\uC74C \u2705"}`
|
|
4665
|
+
);
|
|
4666
|
+
lines.push("");
|
|
4667
|
+
if (existsSync13(".vhk/memory.json")) {
|
|
4668
|
+
try {
|
|
4669
|
+
const memories = readJsonFile(".vhk/memory.json");
|
|
4670
|
+
if (Array.isArray(memories) && memories.length > 0) {
|
|
4671
|
+
lines.push(`## \uC800\uC7A5\uB41C \uACB0\uC815\uC0AC\uD56D (${memories.length}\uAC1C)`);
|
|
4672
|
+
lines.push("");
|
|
4673
|
+
for (const m of memories.slice(-5)) {
|
|
4674
|
+
lines.push(`- ${m.content}`);
|
|
4675
|
+
}
|
|
4676
|
+
if (memories.length > 5) {
|
|
4677
|
+
lines.push(`- ... \uC678 ${memories.length - 5}\uAC1C`);
|
|
4678
|
+
}
|
|
4679
|
+
lines.push("");
|
|
4680
|
+
}
|
|
4681
|
+
} catch {
|
|
4682
|
+
}
|
|
4683
|
+
}
|
|
4684
|
+
if (existsSync13(".vhk/refs.json")) {
|
|
4685
|
+
try {
|
|
4686
|
+
const refs = readJsonFile(".vhk/refs.json");
|
|
4687
|
+
if (Array.isArray(refs) && refs.length > 0) {
|
|
4688
|
+
lines.push(`## \uB808\uD37C\uB7F0\uC2A4 (${refs.length}\uAC1C)`);
|
|
4689
|
+
lines.push("");
|
|
4690
|
+
for (const r of refs.slice(-3)) {
|
|
4691
|
+
const label = r.memo && r.memo.length > 0 ? r.memo : r.url;
|
|
4692
|
+
lines.push(`- [${label}](${r.url})`);
|
|
4693
|
+
}
|
|
4694
|
+
lines.push("");
|
|
4695
|
+
}
|
|
4696
|
+
} catch {
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4699
|
+
lines.push("## \uB2E4\uC74C \uB2E8\uACC4 \uC81C\uC548");
|
|
4700
|
+
lines.push("");
|
|
4701
|
+
const steps = [];
|
|
4702
|
+
if (uncommitted) steps.push("\uBBF8\uCEE4\uBC0B \uBCC0\uACBD \uC0AC\uD56D\uC744 \uCEE4\uBC0B\uD558\uC138\uC694: `vhk save`");
|
|
4703
|
+
steps.push("\uD488\uC9C8 \uC810\uAC80 \uC2E4\uD589: `vhk harness`");
|
|
4704
|
+
steps.push("\uBCF4\uC548 \uAC10\uC0AC: `vhk audit`");
|
|
4705
|
+
steps.push("\uCEE8\uD14D\uC2A4\uD2B8 \uAC31\uC2E0: `vhk context`");
|
|
4706
|
+
steps.forEach((s, i) => lines.push(`${i + 1}. ${s}`));
|
|
4707
|
+
lines.push("");
|
|
4708
|
+
lines.push("---");
|
|
4709
|
+
lines.push("");
|
|
4710
|
+
lines.push("_VHK CLI \uBE0C\uB9AC\uD551_");
|
|
4711
|
+
lines.push("");
|
|
4712
|
+
mkdirSync7(".vhk", { recursive: true });
|
|
4713
|
+
writeFileSync8(BRIEF_PATH, lines.join("\n"), "utf-8");
|
|
4714
|
+
console.log("\n" + lines.join("\n"));
|
|
4715
|
+
console.log(chalk27.green(`
|
|
4716
|
+
\u2705 ${BRIEF_PATH} \uC800\uC7A5 \uC644\uB8CC`));
|
|
4717
|
+
printNextStep({
|
|
4718
|
+
message: "\uBE0C\uB9AC\uD551 \uC0DD\uC131 \uC644\uB8CC!",
|
|
4719
|
+
command: "vhk context",
|
|
4720
|
+
cursorHint: "\uCEE8\uD14D\uC2A4\uD2B8 \uC5C5\uB370\uC774\uD2B8\uD574\uC918"
|
|
4721
|
+
});
|
|
4722
|
+
}
|
|
4723
|
+
|
|
4329
4724
|
// src/lib/nlp-run.ts
|
|
4330
4725
|
async function dispatchNlpRoute(route, input) {
|
|
4331
4726
|
switch (route.command) {
|
|
@@ -4382,19 +4777,27 @@ async function dispatchNlpRoute(route, input) {
|
|
|
4382
4777
|
return migrate();
|
|
4383
4778
|
case "update":
|
|
4384
4779
|
return update();
|
|
4780
|
+
case "context":
|
|
4781
|
+
return context();
|
|
4782
|
+
case "context-show":
|
|
4783
|
+
return contextShow();
|
|
4784
|
+
case "memory":
|
|
4785
|
+
return memoryList();
|
|
4786
|
+
case "brief":
|
|
4787
|
+
return brief();
|
|
4385
4788
|
}
|
|
4386
4789
|
}
|
|
4387
4790
|
async function runNaturalLanguageRoute(input) {
|
|
4388
4791
|
const route = routeNaturalLanguage(input);
|
|
4389
4792
|
if (!route) {
|
|
4390
|
-
console.log(
|
|
4793
|
+
console.log(chalk28.yellow(`
|
|
4391
4794
|
\u2753 "${input}" \u2014 ${ko.nlp.notMatched}
|
|
4392
4795
|
`));
|
|
4393
4796
|
return;
|
|
4394
4797
|
}
|
|
4395
4798
|
console.log("");
|
|
4396
|
-
console.log(
|
|
4397
|
-
console.log(
|
|
4799
|
+
console.log(chalk28.cyan(` \u{1F4AC} "${input}"`));
|
|
4800
|
+
console.log(chalk28.cyan(` \u2192 ${route.explanation}`));
|
|
4398
4801
|
if (route.confidence === "low") {
|
|
4399
4802
|
const { confirm } = await inquirer13.prompt([{
|
|
4400
4803
|
type: "confirm",
|
|
@@ -4403,7 +4806,7 @@ async function runNaturalLanguageRoute(input) {
|
|
|
4403
4806
|
default: true
|
|
4404
4807
|
}]);
|
|
4405
4808
|
if (!confirm) {
|
|
4406
|
-
console.log(
|
|
4809
|
+
console.log(chalk28.dim(` ${ko.nlp.menuHint}`));
|
|
4407
4810
|
return;
|
|
4408
4811
|
}
|
|
4409
4812
|
}
|
|
@@ -4416,8 +4819,8 @@ function getVersion() {
|
|
|
4416
4819
|
const dir = path15.dirname(fileURLToPath4(import.meta.url));
|
|
4417
4820
|
for (const pkgPath of [path15.join(dir, "../package.json"), path15.join(dir, "../../package.json")]) {
|
|
4418
4821
|
try {
|
|
4419
|
-
if (
|
|
4420
|
-
const pkg = JSON.parse(
|
|
4822
|
+
if (fs15.existsSync(pkgPath)) {
|
|
4823
|
+
const pkg = JSON.parse(fs15.readFileSync(pkgPath, "utf-8"));
|
|
4421
4824
|
if (pkg.version) return pkg.version;
|
|
4422
4825
|
}
|
|
4423
4826
|
} catch {
|
|
@@ -4452,7 +4855,11 @@ var KO_ALIASES = {
|
|
|
4452
4855
|
harness: "\uD558\uB124\uC2A4",
|
|
4453
4856
|
audit: "\uAC10\uC0AC",
|
|
4454
4857
|
migrate: "\uC804\uD658",
|
|
4455
|
-
update: "\uC5C5\uB370\uC774\uD2B8"
|
|
4858
|
+
update: "\uC5C5\uB370\uC774\uD2B8",
|
|
4859
|
+
context: "\uB9E5\uB77D",
|
|
4860
|
+
"context-show": "\uB9E5\uB77D\uBCF4\uAE30",
|
|
4861
|
+
memory: "\uAE30\uC5B5",
|
|
4862
|
+
brief: "\uBE0C\uB9AC\uD551"
|
|
4456
4863
|
};
|
|
4457
4864
|
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(getVersion());
|
|
4458
4865
|
program.configureHelp({
|
|
@@ -4548,6 +4955,28 @@ program.command("migrate [target]").alias("\uC804\uD658").description("\uD328\uD
|
|
|
4548
4955
|
program.command("update").alias("\uC5C5\uB370\uC774\uD2B8").description("VHK CLI \uCD5C\uC2E0 \uBC84\uC804 \uC5C5\uB370\uC774\uD2B8").action(async () => {
|
|
4549
4956
|
await update();
|
|
4550
4957
|
});
|
|
4958
|
+
program.command("context").alias("\uB9E5\uB77D").description("\uD504\uB85C\uC81D\uD2B8 \uB9E5\uB77D \uD30C\uC77C \uC0DD\uC131 (.vhk/context.md)").action(async () => {
|
|
4959
|
+
await context();
|
|
4960
|
+
});
|
|
4961
|
+
program.command("context-show").alias("\uB9E5\uB77D\uBCF4\uAE30").description("\uD604\uC7AC \uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C \uB0B4\uC6A9 \uCD9C\uB825").action(async () => {
|
|
4962
|
+
await contextShow();
|
|
4963
|
+
});
|
|
4964
|
+
var memoryCmd = program.command("memory").alias("\uAE30\uC5B5").description("\uACB0\uC815\uC0AC\uD56D \uAE30\uC5B5 \uAD00\uB9AC (add / list / remove)").action(async () => {
|
|
4965
|
+
await memoryList();
|
|
4966
|
+
});
|
|
4967
|
+
memoryCmd.command("add <content>").option("--tags <tags>", "\uD0DC\uADF8 (\uC27C\uD45C \uAD6C\uBD84)").description("\uACB0\uC815\uC0AC\uD56D \uAE30\uC5B5 \uC800\uC7A5").action(async (content, opts) => {
|
|
4968
|
+
const tags = opts.tags ? opts.tags.split(",").map((s) => s.trim()) : void 0;
|
|
4969
|
+
await memoryAdd(content, tags);
|
|
4970
|
+
});
|
|
4971
|
+
memoryCmd.command("list").alias("\uBAA9\uB85D").description("\uC800\uC7A5\uB41C \uAE30\uC5B5 \uBAA9\uB85D").action(async () => {
|
|
4972
|
+
await memoryList();
|
|
4973
|
+
});
|
|
4974
|
+
memoryCmd.command("remove <index>").alias("\uC0AD\uC81C").description("\uAE30\uC5B5 \uC0AD\uC81C (1\uBD80\uD130 \uC2DC\uC791\uD558\uB294 \uBC88\uD638)").action(async (index) => {
|
|
4975
|
+
await memoryRemove(index);
|
|
4976
|
+
});
|
|
4977
|
+
program.command("brief").alias("\uBE0C\uB9AC\uD551").description("\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC694\uC57D \uBCF4\uACE0\uC11C \uC0DD\uC131 (.vhk/brief.md)").action(async () => {
|
|
4978
|
+
await brief();
|
|
4979
|
+
});
|
|
4551
4980
|
program.on("command:*", async (operands) => {
|
|
4552
4981
|
const unknown = operands[0] ?? "";
|
|
4553
4982
|
const rest = operands.slice(1);
|
package/dist/mcp/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@byh3071/vhk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Vibe Harness Kit โ ๋ฐ์ด๋ธ์ฝ๋ฉ ํ์ฌ์ดํด CLI",
|
|
5
|
-
"bin": {
|
|
6
|
-
"vhk": "dist/index.js",
|
|
7
|
-
"vhk-mcp": "dist/mcp/index.js"
|
|
8
|
-
},
|
|
9
|
-
"type": "module",
|
|
10
|
-
"scripts": {
|
|
11
|
-
"dev": "tsx src/index.ts",
|
|
12
|
-
"build": "tsup",
|
|
13
|
-
"test": "vitest",
|
|
14
|
-
"test:run": "vitest --run",
|
|
15
|
-
"prepublishOnly": "pnpm build && pnpm test:run",
|
|
16
|
-
"save": "vhk save",
|
|
17
|
-
"check": "vhk check",
|
|
18
|
-
"scan": "vhk secure scan",
|
|
19
|
-
"recap": "vhk recap",
|
|
20
|
-
"ship": "vhk ship",
|
|
21
|
-
"doctor": "vhk doctor"
|
|
22
|
-
},
|
|
23
|
-
"files": [
|
|
24
|
-
"dist",
|
|
25
|
-
"README.md",
|
|
26
|
-
"LICENSE"
|
|
27
|
-
],
|
|
28
|
-
"keywords": [
|
|
29
|
-
"vibe-coding",
|
|
30
|
-
"harness",
|
|
31
|
-
"cli",
|
|
32
|
-
"scaffold",
|
|
33
|
-
"session-log",
|
|
34
|
-
"rules-sync"
|
|
35
|
-
],
|
|
36
|
-
"author": "byh3071 <byh3071@gmail.com>",
|
|
37
|
-
"license": "MIT",
|
|
38
|
-
"repository": {
|
|
39
|
-
"type": "git",
|
|
40
|
-
"url": "git+https://github.com/byh3071-cpu/vhk.git"
|
|
41
|
-
},
|
|
42
|
-
"engines": {
|
|
43
|
-
"node": ">=20"
|
|
44
|
-
},
|
|
45
|
-
"dependencies": {
|
|
46
|
-
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
47
|
-
"@notionhq/client": "^5.22.0",
|
|
48
|
-
"chalk": "^5.6.2",
|
|
49
|
-
"commander": "^14.0.3",
|
|
50
|
-
"handlebars": "^4.7.9",
|
|
51
|
-
"inquirer": "^9.3.8",
|
|
52
|
-
"ora": "^9.4.0",
|
|
53
|
-
"simple-git": "^3.36.0",
|
|
54
|
-
"zod": "^4.4.3"
|
|
55
|
-
},
|
|
56
|
-
"devDependencies": {
|
|
57
|
-
"@types/inquirer": "^9.0.9",
|
|
58
|
-
"@types/node": "^25.9.1",
|
|
59
|
-
"ignore": "^7.0.5",
|
|
60
|
-
"tsup": "^8.5.1",
|
|
61
|
-
"tsx": "^4.22.3",
|
|
62
|
-
"typescript": "^6.0.3",
|
|
63
|
-
"vitest": "^4.1.7"
|
|
64
|
-
}
|
|
65
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@byh3071/vhk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Vibe Harness Kit โ ๋ฐ์ด๋ธ์ฝ๋ฉ ํ์ฌ์ดํด CLI",
|
|
5
|
+
"bin": {
|
|
6
|
+
"vhk": "dist/index.js",
|
|
7
|
+
"vhk-mcp": "dist/mcp/index.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev": "tsx src/index.ts",
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"test": "vitest",
|
|
14
|
+
"test:run": "vitest --run",
|
|
15
|
+
"prepublishOnly": "pnpm build && pnpm test:run",
|
|
16
|
+
"save": "vhk save",
|
|
17
|
+
"check": "vhk check",
|
|
18
|
+
"scan": "vhk secure scan",
|
|
19
|
+
"recap": "vhk recap",
|
|
20
|
+
"ship": "vhk ship",
|
|
21
|
+
"doctor": "vhk doctor"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"keywords": [
|
|
29
|
+
"vibe-coding",
|
|
30
|
+
"harness",
|
|
31
|
+
"cli",
|
|
32
|
+
"scaffold",
|
|
33
|
+
"session-log",
|
|
34
|
+
"rules-sync"
|
|
35
|
+
],
|
|
36
|
+
"author": "byh3071 <byh3071@gmail.com>",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/byh3071-cpu/vhk.git"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
47
|
+
"@notionhq/client": "^5.22.0",
|
|
48
|
+
"chalk": "^5.6.2",
|
|
49
|
+
"commander": "^14.0.3",
|
|
50
|
+
"handlebars": "^4.7.9",
|
|
51
|
+
"inquirer": "^9.3.8",
|
|
52
|
+
"ora": "^9.4.0",
|
|
53
|
+
"simple-git": "^3.36.0",
|
|
54
|
+
"zod": "^4.4.3"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/inquirer": "^9.0.9",
|
|
58
|
+
"@types/node": "^25.9.1",
|
|
59
|
+
"ignore": "^7.0.5",
|
|
60
|
+
"tsup": "^8.5.1",
|
|
61
|
+
"tsx": "^4.22.3",
|
|
62
|
+
"typescript": "^6.0.3",
|
|
63
|
+
"vitest": "^4.1.7"
|
|
64
|
+
}
|
|
65
|
+
}
|