@no-k/hermes 0.1.0 → 0.3.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.
Files changed (38) hide show
  1. package/README.md +210 -13
  2. package/catalog.json +2640 -98
  3. package/dist/bin/hermes.js +87 -0
  4. package/dist/lib/catalog-query.js +63 -0
  5. package/dist/lib/catalog-selection.js +199 -0
  6. package/dist/lib/catalog.js +144 -0
  7. package/dist/lib/command.js +50 -0
  8. package/dist/lib/config-syntax.js +210 -0
  9. package/dist/lib/conflict-selection.js +89 -0
  10. package/dist/lib/contracts.js +4 -0
  11. package/dist/lib/files.js +94 -0
  12. package/dist/lib/install-prompts.js +106 -0
  13. package/dist/lib/install-view.js +61 -0
  14. package/dist/lib/install-wizard.js +105 -0
  15. package/dist/lib/install.js +184 -0
  16. package/dist/lib/installation-status.js +80 -0
  17. package/dist/lib/json.js +19 -0
  18. package/dist/lib/picker-view.js +81 -0
  19. package/dist/lib/picker.js +135 -0
  20. package/dist/lib/project-config.js +171 -0
  21. package/dist/lib/report.js +89 -0
  22. package/dist/lib/terminal-input.js +61 -0
  23. package/dist/lib/terminal-style.js +15 -0
  24. package/dist/lib/terminal-text.js +75 -0
  25. package/dist/lib/terminal.js +133 -0
  26. package/dist/lib/versions.js +251 -0
  27. package/docs/interactive-install.md +405 -0
  28. package/docs/module-versioning.md +105 -0
  29. package/package.json +25 -4
  30. package/templates/lint/fsd/fsd.ts +180 -0
  31. package/templates/lint/fsd/import-listener.ts +41 -0
  32. package/templates/lint/fsd/index.ts +32 -0
  33. package/templates/lint/fsd/options.ts +74 -0
  34. package/templates/lint/fsd/rules/fsd-layer-imports.ts +22 -0
  35. package/templates/lint/fsd/rules/fsd-public-api.ts +20 -0
  36. package/templates/lint/fsd/rules/fsd-slice-segments.ts +33 -0
  37. package/bin/hermes.mjs +0 -159
  38. package/lib/catalog.mjs +0 -51
package/README.md CHANGED
@@ -2,21 +2,30 @@
2
2
 
3
3
  Hermes CLI로 필요한 TypeScript 유틸 소스를 지정한 디렉터리에 생성합니다.
4
4
  선택한 유틸과 필요한 보조 파일은 npm 패키지에 함께 들어 있습니다.
5
- CLI는 Node.js 기본 모듈만 사용하며 별도 런타임 의존성이 없습니다.
5
+ CLI는 터미널 화면에 Ink·React, 버전 범위 검사에 `semver`를 사용합니다.
6
6
 
7
7
  ## 사용
8
8
 
9
9
  Node.js 22 이상이 필요합니다. 아래 명령은 공개 배포 후 사용할 수 있습니다.
10
10
 
11
11
  ```bash
12
- npx @no-k/hermes@0.1.0 list
13
- npx @no-k/hermes@0.1.0 add array-chunk --dir src/lib/hermes
12
+ npx @no-k/hermes@latest
13
+ # 최신 카탈로그를 탐색하고 설치 계획만 확인
14
+ npx @no-k/hermes@latest --dry-run
15
+ # 특정 항목을 미리 체크한 상태로 시작
16
+ npx @no-k/hermes@0.1.0 add array-chunk
14
17
  ```
15
18
 
16
- 두 번째 명령은 다음 파일을 생성합니다.
19
+ 터미널에서 Core / 라이브러리 → 하위 분류 → 유틸을 여러 개 선택합니다.
20
+ 각 대분류의 경로와 기존 파일 처리를 검토한 뒤, 최종 목록에서 Yes를 선택하고 Enter를 누르면 설치합니다.
21
+ No는 선택·경로·파일별 교체 결정을 유지하고 수정 화면으로 돌아갑니다.
22
+ ↑↓로 이동하고 Space로 체크합니다. `/`로 이름·한국어 설명을 검색한 뒤 Enter로 검색 입력을
23
+ 끝내고, Space로 항목을 체크합니다. 다시 Enter를 누르면 다음 단계로 이동합니다.
24
+ Tab으로 설명·의존성을 자세히 보고 Esc로 돌아갈 수 있습니다.
25
+ 기본 경로로 array-chunk를 설치하면 다음 파일과 실행 디렉터리의 `no-k.config.ts`를 생성합니다.
17
26
 
18
27
  ```text
19
- src/lib/hermes/
28
+ src/utils/hermes/
20
29
  ├── array/chunk/chunk.ts
21
30
  ├── array/chunk/index.ts
22
31
  └── LICENSE
@@ -25,23 +34,31 @@ src/lib/hermes/
25
34
  프로젝트의 실제 경로에 맞춰 import합니다.
26
35
 
27
36
  ```ts
28
- import { chunk } from "./lib/hermes/array/chunk";
37
+ import { chunk } from "./utils/hermes/array/chunk";
29
38
 
30
39
  chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
31
40
  ```
32
41
 
33
42
  `--dir`는 현재 작업 디렉터리 기준 상대 경로나 절대 경로를 받습니다.
34
43
  공백이 있는 경로는 따옴표로 감싸세요. 그 아래에는 유틸의 카테고리/이름 구조를 유지합니다.
44
+ 경로 입력의 초기값은 `--dir` → 현재 디렉터리의 저장된 설정 → 기본 경로 순서입니다.
45
+ Core 기본값은 `src/utils/hermes`, 라이브러리는 `libs/hermes`이고 화면에서 각각 수정할 수 있습니다.
46
+ 경로 입력에서 Enter는 현재 값 사용, Ctrl+U는 전체 지우기, Esc는 이전 화면입니다.
47
+ 모노레포에서는 설치할 앱·패키지 디렉터리에서 실행합니다. 상위 디렉터리의 설정은 찾지 않습니다.
35
48
  설정 파일이나 package.json이 없는 디렉터리에서도 파일 생성이 가능합니다.
49
+ 설치가 성공하면 `no-k.config.ts`에 목적지, 선택한 유틸과 함께 복사한 모듈의 버전·해시를 저장합니다.
50
+ 기존 설정이 있으면 읽어서 갱신하며, `--dry-run`에서는 설정도 쓰지 않습니다.
36
51
 
37
52
  ## 명령과 옵션
38
53
 
39
54
  | 명령/옵션 | 동작 |
40
55
  | --- | --- |
41
56
  | list | 설치 가능한 항목과 설명 출력 |
42
- | add <항목...> --dir <경로> | 선택한 항목과 보조 파일 생성 |
43
- | --dry-run | 생성·유지·교체 예정 파일만 출력 |
44
- | --overwrite | 내용이 다른 기존 파일 교체를 명시적으로 허용 |
57
+ | 명령 없음 / add | 카탈로그 선택 설치 시작 |
58
+ | add <항목...> | 해당 항목을 미리 선택한 상태로 시작 |
59
+ | --dir <경로> | 선택한 대분류들의 경로 초기값 |
60
+ | --dry-run | 동일한 선택·검토 과정 후 예정 내역만 출력. 설정도 쓰지 않음 |
61
+ | --overwrite | 첫 충돌 화면의 교체 후보를 미리 체크. 개별 해제와 최종 확인 가능 |
45
62
  | --help | 도움말 |
46
63
  | --version | CLI 버전 |
47
64
 
@@ -50,14 +67,22 @@ npx @no-k/hermes@0.1.0 add array-chunk number-lcm --dir src/shared/hermes
50
67
  npx @no-k/hermes@0.1.0 add array-chunk --dir "src/my utilities" --dry-run
51
68
  ```
52
69
 
53
- 내용이 같은 기존 파일은 유지합니다. 내용이 다른 파일이 하나라도 있으면 쓰기 전에 중단합니다.
54
- 의도적으로 바꾸려면 변경 내용을 검토한 뒤 --overwrite를 사용하세요.
70
+ 내용이 같은 기존 파일은 유지합니다. 내용이 다른 파일도 기본은 유지이며,
71
+ 파일 검토 화면에서 Space로 교체할 파일만 체크하고 Tab으로 차이를 확인합니다.
72
+ 최종 목록에서 ↑↓로 스크롤하고, `y`/`n` 또는 Tab으로 Yes/No를 선택한 뒤 Enter로 확정합니다.
73
+ 기본 선택은 No이며 인자나 옵션을 모두 전달해도 최종 확인을 건너뛰지 않습니다.
74
+ 검토 중 파일이나 설정이 바뀌면 다시 계획하고 확인받습니다. 변경된 충돌에는 이전 교체 승인을 적용하지 않습니다.
55
75
  목적지의 심볼릭 링크를 통해 파일을 쓰지 않습니다.
56
76
 
77
+ 설치는 입력·출력이 모두 연결된 대화형 터미널에서 실행합니다. 파이프·리다이렉트 환경의
78
+ `add`는 오류 안내로 끝나고, 명령 없이 실행하면 도움말을 출력합니다. `list`, `--help`, `--version`은
79
+ 항상 바로 출력합니다. `q` 취소는 종료 코드 0, Ctrl+C는 130, 입력 종료는 1입니다.
80
+ 경로·검색 입력 중에는 `q`도 입력 문자이므로 Ctrl+C로 중단합니다.
81
+
57
82
  ## 항목과 의존성
58
83
 
59
84
  항목 이름은 core 디렉터리 경로를 하이픈으로 연결한 이름입니다.
60
- Tailwind 항목에는 tailwindcss- 접두어를 붙입니다.
85
+ 라이브러리 항목에는 tailwindcss-, lint-처럼 라이브러리 이름 접두어를 붙입니다.
61
86
 
62
87
  | 항목 | 포함하는 소스 |
63
88
  | --- | --- |
@@ -67,22 +92,194 @@ Tailwind 항목에는 tailwindcss- 접두어를 붙입니다.
67
92
  | tailwindcss-cn | 클래스 병합과 설정 |
68
93
  | tailwindcss-create-tailwind-css | 설정을 공유하는 cn·classVariant |
69
94
  | string-uuid | Node.js UUID 생성 |
95
+ | lint-fsd | 수정 가능한 FSD ESLint 플러그인 소스 |
70
96
 
71
97
  core 항목은 외부 런타임 npm 의존성이 없습니다.
72
98
  Tailwind 항목은 clsx, tailwind-merge, tailwind-variants 중 해당 항목이 참조하는 패키지가 필요합니다.
73
99
  CLI가 필요한 설치 명령을 출력합니다. 소비 프로젝트의 패키지 매니저에 맞춰 직접 설치하세요.
74
100
  CLI는 package.json이나 lockfile을 수정하지 않습니다.
101
+ 설치 결과의 `npm install ...`은 같은 패키지·버전 범위를 유지한 채 `pnpm add ...`, `yarn add ...`,
102
+ `bun add ...`로 바꿔 실행할 수 있습니다. `npm install --save-dev ...`는 각 도구의 `add -D ...`에
103
+ 해당합니다. 이 명령도 유틸을 사용하는 앱·패키지 디렉터리에서 실행하고 lockfile을 함께 관리하세요.
104
+ 내부 모듈의 필수 `dependencies`와 필수 `peerDependencies`는 소스로 함께 복사합니다.
105
+ 서로 import하는 모듈의 버전 범위, 기존 설치 기록, 설치된 외부 패키지의 peer 범위를 검사하고
106
+ 알려진 충돌이 있으면 파일을 쓰기 전에 중단합니다. 아직 없는 외부 패키지는 설치 명령으로 안내합니다.
75
107
 
76
108
  Node용 항목은 @types/node 설치 명령도 안내합니다.
77
109
  string-uuid는 정적 node:crypto import 때문에 Node.js에서 사용해야 합니다.
78
110
  dom-* 항목에는 DOM API와 DOM TypeScript 타입이 필요합니다.
79
111
  현재 Tailwind 헬퍼의 병합 규칙은 Tailwind CSS 4 기준입니다.
80
112
 
113
+ ## FSD lint 소스 생성
114
+
115
+ 이 항목이 포함된 Hermes 릴리스 배포 후 사용합니다.
116
+
117
+ ```bash
118
+ npx @no-k/hermes@latest add lint-fsd
119
+ pnpm add -D eslint typescript-eslint typescript jiti@^2.2.0 @types/node@^22
120
+ ```
121
+
122
+ `libs/hermes/lint/fsd/`에 TypeScript 플러그인 진입점, 옵션, 경로 정책과 세 규칙을 생성합니다.
123
+ 기존 프로젝트에 저장된 라이브러리 경로가 있으면 그 값을 사용합니다.
124
+ 이번 설치 경로를 지정하려면 `--dir libs/hermes`를 붙이세요.
125
+ 레이어 의존 방향·slice 격리, public API와 디렉터리 구조를 검사합니다.
126
+ 생성된 파일은 직접 수정할 수 있으며, 다시 설치할 때도 변경된 파일은 기본 유지합니다.
127
+ ESLint 설정과 package.json은 직접 연결합니다.
128
+
129
+ ```ts
130
+ // eslint.config.ts
131
+ import tseslint from "typescript-eslint";
132
+ import fsd from "./libs/hermes/lint/fsd";
133
+
134
+ export default [...tseslint.configs.recommended, fsd.configs.recommended];
135
+ ```
136
+
137
+ 기존 flat config에는 `fsd.configs.recommended`를 추가하세요.
138
+ 기본 FSD 루트는 린터 실행 위치 기준 `src`이고 alias는 `@`·`~`입니다.
139
+ 다른 구조는 `createConfig({ roots, aliases, layers })`로 지정할 수 있습니다.
140
+ TypeScript 설정 로딩에 사용하는 `jiti`는 2.2 이상이 필요합니다.
141
+ 옵션, 규칙 수정 위치와 같은 소스를 사용하는 Oxlint 설정은
142
+ [FSD 모듈 문서](https://github.com/no-k/hermes/tree/main/packages/lib/lint/fsd)를 참고하세요.
143
+
81
144
  ## 업데이트와 라이선스
82
145
 
83
- 명령에서 Hermes 버전을 고정하면 같은 템플릿을 받습니다.
146
+ 새 유틸을 찾을 때는 `@latest`로 최신 CLI에 포함된 카탈로그를 탐색합니다.
147
+ 카탈로그는 실행 중 원격에서 갱신되지 않으므로 이전 버전으로 실행하면 그 버전의 항목만 보입니다.
148
+ 같은 카탈로그와 템플릿을 다시 사용하려면 CLI 버전을 확인하고 명령에서 고정하세요.
149
+
150
+ ```bash
151
+ npx @no-k/hermes@latest --version
152
+ # 확인한 버전이 0.1.0인 경우
153
+ npx @no-k/hermes@0.1.0
154
+ npx @no-k/hermes@0.1.0 list
155
+ ```
156
+
157
+ 설치할 때는 `@latest`와 버전 고정 모두 선택 화면과 최종 Yes/No를 거칩니다.
84
158
  안내하는 외부 의존성은 버전 범위를 사용하므로 정확한 설치 버전은 소비 프로젝트 lockfile로 관리합니다.
85
159
  이미 복사한 소스는 새 버전이 나와도 자동 변경되지 않습니다.
86
160
  업데이트할 때는 직접 수정한 부분과 공통 보조 파일의 호환성을 함께 검토하세요.
161
+ 유틸별 버전은 CLI 배포 버전과 별개입니다. 예를 들어 `number-lcm@1.0.0`과
162
+ `number-gcd@1.2.0`을 같은 CLI가 포함할 수 있습니다. 한 설치 위치에는 모듈별 한 버전만 둡니다.
163
+ 과거 버전을 별도로 내려받아 조합하는 기능은 제공하지 않습니다.
164
+
165
+ 각 유틸의 `package.json`과 `CHANGELOG.md`, Changesets 사용법은
166
+ [독립 버전 관리](docs/module-versioning.md)를 참고하세요.
87
167
 
88
168
  ISC 라이선스입니다. 함께 생성되는 LICENSE의 저작권·허가 문구를 유지해 주세요.
169
+
170
+ ## 개발 및 검증
171
+
172
+ CLI 소스와 관련 도구는 이 패키지 안에서 TypeScript로 관리합니다.
173
+
174
+ | 경로 | 역할 |
175
+ | --- | --- |
176
+ | `src/bin/hermes.ts` | 대화형 설치 진입, 조회 명령과 결과 출력 |
177
+ | `src/lib/install-wizard.ts` | 선택·경로·충돌·최종 확인 연결과 변경된 계획 재검토 |
178
+ | `src/lib/install-prompts.ts`, `install-view.tsx` | 경로 입력과 스크롤 가능한 최종 Yes/No 화면 |
179
+ | `src/lib/install.ts` | 쓰기 없는 설치 계획 계산, 파일별 충돌 결정, 설정 저장을 포함한 실행 |
180
+ | `src/lib/files.ts` | 목적지 검사, 계획 이후 변경 감지와 파일 쓰기 |
181
+ | `src/lib/project-config.ts`, `config-syntax.ts` | 설정 읽기·검증, 원문 보존 갱신과 설치 목록 병합 |
182
+ | `src/lib/report.ts` | 파일 결과·외부 의존성·실행 환경 안내 |
183
+ | `src/lib/catalog.ts`, `json.ts` | catalog 타입과 JSON 검증 |
184
+ | `src/lib/catalog-query.ts` | 분류 계층 조회, 이름·전체 설명 검색, 분류 필터와 표시용 요약 |
185
+ | `src/lib/catalog-selection.ts` | 대분류·하위 분류·유틸 선택과 이전 선택 복원 |
186
+ | `src/lib/picker.ts`, `picker-view.tsx`, `terminal.ts`, `terminal-text.ts` | 선택 상태, Ink 화면, 터미널 입력과 화면 복원 |
187
+ | `src/lib/installation-status.ts` | 설치 기록과 실제 파일을 대조한 상태·위치 표시 |
188
+ | `src/lib/conflict-selection.ts` | 기존 파일과 생성 후보의 차이 검토, 파일별 유지·교체 선택 |
189
+ | `src/lib/versions.ts` | 실제 파일 해시와 설치 버전 대조, 내부 의존성·외부 peer 호환성 검사 |
190
+ | `scripts/catalog-lib.ts` | 유틸 탐색, 의존성 추적과 README 설명 추출 |
191
+ | `scripts/build-cli.ts` | catalog와 템플릿 생성 |
192
+ | `scripts/version-modules.ts` | Changesets 버전 적용 시 유틸 변경을 CLI 배포 버전에 연결 |
193
+ | `scripts/preview-ui.ts` | 파일을 생성하지 않는 개발용 선택 화면 미리보기 |
194
+ | `scripts/pack-cli.ts` | npm tarball 생성 및 포함 파일 검증 |
195
+ | `scripts/smoke-cli.ts` | tarball을 설치해 소비 프로젝트에서 컴파일·실행 |
196
+ | `scripts/smoke-fsd.ts` | CLI로 lint 소스를 생성하고 ESLint·Oxlint 실행, 직접 수정과 재설치 보존 검증 |
197
+ | `test/*.test.ts` | CLI·catalog·패키징 회귀 테스트 |
198
+
199
+ 대화형 설치는 [단계별 계약](docs/interactive-install.md)에 따라 설치 엔진·설정, 카탈로그 탐색,
200
+ 독립 모듈 버전 관리와 터미널 선택 화면을 연결합니다.
201
+ `hermes`와 `hermes add` 모두 대화형 선택 후 최종 Yes에서 설치하고 설정과 버전을 저장합니다.
202
+
203
+ 개발용 화면은 다음 명령으로 확인할 수 있습니다. 선택 결과를 표시하고 파일을 생성하지 않습니다.
204
+ 매번 전체 빌드하지 않고 `tsx`로 화면 소스를 실행합니다. 기존 catalog.json을 읽으며,
205
+ 아직 빌드하지 않았다면 소스에서 카탈로그를 메모리에 구성합니다.
206
+
207
+ ```bash
208
+ pnpm --filter @no-k/hermes run preview:ui
209
+ # 초기 선택값을 넣어 탐색할 수도 있습니다.
210
+ pnpm --filter @no-k/hermes run preview:ui number-lcm tailwindcss-cn
211
+ # 결과와 재진입 상태를 JSON으로 확인합니다.
212
+ pnpm --filter @no-k/hermes run preview:ui --json number-lcm
213
+ ```
214
+
215
+ 현재 단계, 포커스, 체크 수를 색상으로 구분합니다. 101열 이상에서는 목록 옆에 상세 패널이
216
+ 표시되고, 좁거나 낮은 터미널에서는 한 열로 전환합니다. 키 입력을 즉시 선택 상태에 반영하고
217
+ 연속 입력의 화면 갱신을 합칩니다. 바뀐 줄만 최대 60fps로 출력해 전체 화면 지우기를 줄입니다.
218
+
219
+ 대분류 → 각 대분류의 하위 분류 → 각 하위 분류의 유틸 순서로 선택합니다.
220
+ ↑↓로 이동하고 Space로 체크하며 Enter로 다음 화면에 갑니다. `/`로 검색을 시작하고
221
+ Enter로 검색 입력을 끝냅니다. Tab은 상세 보기, Esc는 상세·검색 닫기 또는 이전 화면,
222
+ `a`는 검색 결과 전체 선택·해제, Ctrl+L은 검색 초기화, `q`는 취소입니다.
223
+ 목록에서는 `j`/`k`로도 이동할 수 있습니다. 한국어 검색과 bracketed paste를 지원합니다.
224
+ 분류를 해제하면 그 안의 선택은 설치 대상에서 제외되고, 다시 선택하면 체크가 복원됩니다.
225
+ 상세 화면에서 함께 생성되는 의존 모듈, npm·peer 의존성, 실행 환경과 기존 설치 위치를 확인할 수 있습니다.
226
+
227
+ 미리보기는 실행 디렉터리의 설정을 읽습니다. 위 pnpm 명령의 실행 디렉터리는 `packages/cli`입니다.
228
+ 다른 앱의 설치 기록을 보려면 CLI를 빌드한 뒤 그 앱 디렉터리에서
229
+ `node /저장소/절대경로/packages/cli/.build/scripts/preview-ui.js`를 실행합니다.
230
+
231
+ 설정 모듈은 `export default { ... }`의 데이터 리터럴, 주석, 마지막 쉼표, 최상위 `as const`를
232
+ 지원합니다. 사용자 필드와 주석을 보존하기 위해 필요한 값만 수정하며, import·함수·변수 참조 등
233
+ 지원하지 않는 구문은 위치를 안내하고 원본을 유지합니다. 설정 파일의 코드를 실행하지 않습니다.
234
+
235
+ 저장소 루트에서 실행합니다.
236
+
237
+ ```bash
238
+ pnpm install --frozen-lockfile
239
+ pnpm run build:cli
240
+ pnpm run check
241
+ pnpm run test:run
242
+ pnpm run check:cli
243
+ pnpm run pack:cli
244
+ pnpm run test:cli-install
245
+ pnpm run test:fsd-install
246
+ ```
247
+
248
+ `tsconfig.json`은 런타임·도구·테스트 전체를 strict 및 `noUncheckedIndexedAccess`로 검사합니다.
249
+ NodeNext 모듈 해석과 ES2022 출력을 사용하며, 상대 import에는 `.js` 확장자를 씁니다.
250
+ `tsconfig.build.json`은 런타임을 `dist/`에, `tsconfig.tools.json`은 도구·테스트와 참조하는
251
+ 공유 모듈을 `.build/`에 컴파일합니다. 타입 오류가 있으면 해당 컴파일의 출력은 생성되지 않습니다.
252
+
253
+ 빌드는 이전 `dist/`, `.build/`, `templates/`, `catalog.json`을 지우고 컴파일한 다음
254
+ catalog와 템플릿을 생성합니다. 항목 설명은 각 유틸 README의 첫 문단 전체에서 가져옵니다.
255
+ 생성된 catalog를 직접 수정하지 말고 해당 README를 수정하세요.
256
+
257
+ 카탈로그 스키마 3은 각 항목의 `scope`(core/lib)와 `category`(core/array, lib/tailwindcss 등)를
258
+ 원본 진입 경로에서 생성합니다. Core의 하위 분류와 `packages/lib`의 라이브러리 패키지를 빌드 시
259
+ 탐색하므로 새 유틸이나 분류가 자동 반영됩니다. 유틸 ID나 보조 파일 순서로 소속을 추측하지 않습니다.
260
+ 각 모듈의 manifest에서 패키지 이름·버전·의존 범위를 읽고, 함께 복사하는 모듈과 파일 해시를 기록합니다.
261
+ 프로젝트 설정인 no-k.config.ts의 스키마는 1을 유지하며 기존 위치 기록도 읽을 수 있습니다.
262
+
263
+ `filterCatalog`는 이름·소개 문단 전체 검색과 대분류·하위 분류 필터를 조합합니다.
264
+ 검색어를 공백으로 나누어 모두 일치하는 항목을 찾으며, 한글 Unicode 표현과 영문 대소문자를
265
+ 정규화합니다. `getCatalogGroups`는 같은 결과를 대분류별 하위 분류와 유틸 목록으로 구성합니다.
266
+ 필터 생략은 전체 조회, 빈 배열은 선택 없음입니다. `summarizeDescription`의 화면용 요약은
267
+ 전체 설명이나 검색 결과를 바꾸지 않습니다. 선택 화면은 이 조회 함수들을 재사용하며,
268
+ 검색 결과 밖에 있는 체크도 유지하고 전체 선택 수를 표시합니다.
269
+
270
+ `check:cli`, `pack:cli`, `test:cli-install`은 빌드부터 실행합니다.
271
+ 직접 `npm pack` 또는 `pnpm pack`을 실행해도 `prepack`이 같은 빌드를 수행합니다.
272
+ 검증 스크립트 내부의 `npm pack --ignore-scripts`는 이미 빌드한 결과를 포장해 중복 빌드를 피합니다.
273
+
274
+ npm 패키지에는 `dist/`의 ESM JavaScript, `catalog.json`, `templates/`의 TypeScript 유틸,
275
+ README·LICENSE·package.json이 포함됩니다. CLI TypeScript 소스, 개발 도구와 테스트는 포함하지 않습니다.
276
+ TypeScript·타입 패키지·tsx는 개발 의존성이며, 배포된 CLI의 직접 런타임 의존성은
277
+ `ink`, `react`, `semver`입니다. 소비 프로젝트에 생성되는 유틸에는 UI 의존성을 추가하지 않습니다.
278
+ `pack:cli`는 `artifacts/`에 tarball을 만들고 파일 목록·실행 권한을 검사합니다.
279
+ `test:cli-install`은 그 tarball을 별도 소비 프로젝트에서 검증하며 npm에 배포하지 않습니다.
280
+ 첫 `npx` 실행은 런타임 의존성을 내려받고, 다음 실행은 같은 캐시에서 오프라인으로 검증합니다.
281
+ PTY 통합 검증은 macOS·Linux의 `script` 명령으로 실제 터미널 입력을 전달합니다.
282
+ 한국어 탐색과 여러 분류 선택, 별도 경로 저장·재사용, No 이후 파일별 결정 유지,
283
+ 최종 확인 중 파일 변경, 화면별 취소, 입력·출력 각각의 리다이렉트를 검사합니다.
284
+ 최종 Yes 이전에는 파일이 생기거나 기존 파일이 바뀌지 않는지도 실제 실행 중 확인합니다.
285
+ Windows에서는 이 PTY 테스트를 건너뛰며 `test:cli-install`은 macOS·Linux에서 실행합니다.