@kood/claude-code 0.1.6 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/index.js +109 -216
  2. package/package.json +8 -2
  3. package/templates/hono/CLAUDE.md +59 -328
  4. package/templates/hono/docs/architecture/architecture.md +93 -747
  5. package/templates/hono/docs/deployment/cloudflare.md +59 -513
  6. package/templates/hono/docs/deployment/docker.md +41 -356
  7. package/templates/hono/docs/deployment/index.md +54 -190
  8. package/templates/hono/docs/deployment/railway.md +36 -306
  9. package/templates/hono/docs/deployment/vercel.md +49 -434
  10. package/templates/hono/docs/library/ai-sdk/index.md +53 -290
  11. package/templates/hono/docs/library/ai-sdk/openrouter.md +19 -387
  12. package/templates/hono/docs/library/ai-sdk/providers.md +28 -394
  13. package/templates/hono/docs/library/ai-sdk/streaming.md +52 -353
  14. package/templates/hono/docs/library/ai-sdk/structured-output.md +63 -395
  15. package/templates/hono/docs/library/ai-sdk/tools.md +62 -431
  16. package/templates/hono/docs/library/hono/env-setup.md +24 -313
  17. package/templates/hono/docs/library/hono/error-handling.md +34 -295
  18. package/templates/hono/docs/library/hono/index.md +29 -121
  19. package/templates/hono/docs/library/hono/middleware.md +21 -188
  20. package/templates/hono/docs/library/hono/rpc.md +40 -341
  21. package/templates/hono/docs/library/hono/validation.md +35 -195
  22. package/templates/hono/docs/library/pino/index.md +42 -333
  23. package/templates/hono/docs/library/prisma/cloudflare-d1.md +64 -367
  24. package/templates/hono/docs/library/prisma/config.md +19 -260
  25. package/templates/hono/docs/library/prisma/index.md +67 -320
  26. package/templates/hono/docs/library/zod/index.md +53 -257
  27. package/templates/npx/CLAUDE.md +62 -274
  28. package/templates/npx/docs/references/patterns.md +160 -0
  29. package/templates/tanstack-start/CLAUDE.md +100 -256
  30. package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
  31. package/templates/tanstack-start/docs/deployment/cloudflare.md +37 -424
  32. package/templates/tanstack-start/docs/deployment/index.md +57 -286
  33. package/templates/tanstack-start/docs/deployment/nitro.md +36 -318
  34. package/templates/tanstack-start/docs/deployment/railway.md +40 -409
  35. package/templates/tanstack-start/docs/deployment/vercel.md +43 -465
  36. package/templates/tanstack-start/docs/design/components.md +77 -311
  37. package/templates/tanstack-start/docs/design/index.md +113 -69
  38. package/templates/tanstack-start/docs/design/safe-area.md +51 -250
  39. package/templates/tanstack-start/docs/design/tailwind-setup.md +45 -359
  40. package/templates/tanstack-start/docs/guides/conventions.md +103 -0
  41. package/templates/tanstack-start/docs/guides/env-setup.md +34 -340
  42. package/templates/tanstack-start/docs/guides/getting-started.md +22 -209
  43. package/templates/tanstack-start/docs/guides/hooks.md +166 -0
  44. package/templates/tanstack-start/docs/guides/routes.md +166 -0
  45. package/templates/tanstack-start/docs/guides/services.md +143 -0
  46. package/templates/tanstack-start/docs/library/better-auth/2fa.md +27 -115
  47. package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
  48. package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
  49. package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
  50. package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
  51. package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
  52. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
  53. package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
  54. package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
  55. package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
  56. package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
  57. package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
  58. package/templates/tanstack-start/docs/library/prisma/setup.md +12 -112
  59. package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
  60. package/templates/tanstack-start/docs/library/tanstack-query/index.md +26 -97
  61. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
  62. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
  63. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
  64. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
  65. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
  66. package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
  67. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
  68. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
  69. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +34 -246
  70. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
  71. package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
  72. package/templates/tanstack-start/docs/library/zod/index.md +31 -144
  73. package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
  74. package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
  75. package/templates/hono/docs/commands/git.md +0 -145
  76. package/templates/hono/docs/mcp/context7.md +0 -106
  77. package/templates/hono/docs/mcp/index.md +0 -176
  78. package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
  79. package/templates/hono/docs/mcp/serena.md +0 -269
  80. package/templates/hono/docs/mcp/sgrep.md +0 -105
  81. package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
  82. package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
  83. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
  84. package/templates/npx/docs/commands/git.md +0 -145
  85. package/templates/npx/docs/mcp/index.md +0 -60
  86. package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
  87. package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
  88. package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
  89. package/templates/tanstack-start/docs/commands/git.md +0 -145
  90. package/templates/tanstack-start/docs/design/accessibility.md +0 -433
  91. package/templates/tanstack-start/docs/design/color.md +0 -235
  92. package/templates/tanstack-start/docs/design/spacing.md +0 -341
  93. package/templates/tanstack-start/docs/design/typography.md +0 -324
  94. package/templates/tanstack-start/docs/guides/best-practices.md +0 -950
  95. package/templates/tanstack-start/docs/guides/husky-lint-staged.md +0 -303
  96. package/templates/tanstack-start/docs/guides/prettier.md +0 -189
  97. package/templates/tanstack-start/docs/guides/project-templates.md +0 -710
  98. package/templates/tanstack-start/docs/library/tanstack-query/setup.md +0 -107
  99. package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -186
  100. package/templates/tanstack-start/docs/mcp/context7.md +0 -204
  101. package/templates/tanstack-start/docs/mcp/index.md +0 -177
  102. package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
  103. package/templates/tanstack-start/docs/mcp/serena.md +0 -269
  104. package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
  105. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
  106. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
  107. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +0 -292
@@ -1,309 +1,97 @@
1
- # CLAUDE.md - Claude Code Instructions
1
+ # CLAUDE.md - NPX CLI 프로젝트
2
2
 
3
- > NPX CLI 도구 프로젝트 작업 지침
3
+ > Node.js CLI 도구 개발 지침
4
4
 
5
- ---
6
-
7
- ## 🚨 STOP - 작업 전 필수 확인
5
+ ## Instructions
8
6
 
9
- ```
10
- ┌─────────────────────────────────────────────────────────────┐
11
- │ 이 프로젝트에서 작업하기 전에 이 문서를 끝까지 읽으세요. │
12
- │ 특히 ⛔ NEVER DO 섹션의 규칙은 절대 위반하지 마세요. │
13
- │ │
14
- │ 📖 작업 유형별 상세 문서: docs/ 폴더 참조 │
15
- └─────────────────────────────────────────────────────────────┘
16
- ```
7
+ @docs/library/commander/index.md
8
+ @docs/library/fs-extra/index.md
9
+ @docs/library/prompts/index.md
17
10
 
18
11
  ---
19
12
 
20
- ## ⛔ NEVER DO (절대 금지 - 예외 없음)
13
+ ## 금지 사항
21
14
 
22
- ### Git 커밋 금지 사항
23
- ```
24
- "Generated with Claude Code" 포함 금지
25
- "🤖" 또는 AI 관련 이모지 포함 금지
26
- ❌ "Co-Authored-By:" 헤더 포함 금지
27
- ❌ AI/봇이 작성했다는 어떤 표시도 금지
28
- ❌ 커밋 메시지 여러 줄 작성 금지
29
- ❌ 커밋 메시지에 이모지 사용 금지
30
- ```
15
+ ### Git 커밋
16
+ - `Generated with Claude Code` 포함 금지
17
+ - AI 관련 이모지/표시 금지
18
+ - `Co-Authored-By:` 헤더 금지
19
+ - 여러 커밋 메시지 금지
31
20
 
32
- ### CLI 구현 금지 사항
33
- ```
34
- process.exit() 없이 에러 상황 종료 금지
35
- console.log 직접 사용 금지 (logger 사용)
36
- 동기 파일 작업 (fs.readFileSync ) 금지
37
- hardcoded 경로 사용 금지 (path.join 사용)
38
- ❌ 사용자 입력 검증 없이 처리 금지
39
- ```
21
+ ### CLI 구현
22
+ - `process.exit()` 없이 에러 종료 금지
23
+ - `console.log` 직접 사용 금지 (logger 사용)
24
+ - 동기 파일 작업 (`fs.readFileSync` ) 금지
25
+ - hardcoded 경로 금지 (`path.join` 사용)
26
+ - 사용자 입력 미검증 처리 금지
40
27
 
41
- ### 코드 검색 금지 사항
42
- ```
43
- ❌ grep, rg 등 기본 검색 도구 사용 금지
44
- ❌ find 명령어로 코드 검색 금지
45
- ✅ 코드베이스 검색 시 sgrep 사용 필수
46
- ```
28
+ ### 코드 검색
29
+ - `grep`, `rg` 사용 금지 → `ast-grep` 필수
47
30
 
48
31
  ---
49
32
 
50
- ## ✅ ALWAYS DO (필수 실행)
33
+ ## 필수 사항
51
34
 
52
- ### 1. 작업 전: 관련 문서 읽기
53
- ```
54
- CLI 작업 → docs/library/commander/ 읽기
55
- 파일 작업 docs/library/fs-extra/ 읽기
56
- 사용자 입력 → docs/library/prompts/ 읽기
57
- ```
35
+ ### 작업
36
+ | 작업 | 참조 문서 |
37
+ |------|----------|
38
+ | CLI 작업 | `docs/library/commander/` |
39
+ | 파일 작업 | `docs/library/fs-extra/` |
40
+ | 사용자 입력 | `docs/library/prompts/` |
58
41
 
59
- ### 2. MCP 도구 적극 활용
42
+ ### 커밋 형식
60
43
  ```
61
- 코드베이스 검색 → sgrep 사용 (grep/rg 금지)
62
- 복잡한 분석/디버깅 → Sequential Thinking 사용
63
- 라이브러리 문서 → Context7 사용
44
+ <prefix>: <설명>
64
45
  ```
65
- **상세**: `docs/mcp/` 참고
66
-
67
- ### 3. 작업 완료 후: Git 커밋
68
- ```bash
69
- git add .
70
- git commit -m "<prefix>: <설명>"
71
- ```
72
-
73
- **커밋 형식**: `<prefix>: <설명>` (한 줄, 본문 없음)
74
46
 
75
- **Prefix**: `feat` | `fix` | `refactor` | `style` | `docs` | `test` | `chore` | `perf` | `ci`
76
-
77
- **예시**:
78
- ```bash
79
- feat: 템플릿 복사 기능 추가
80
- fix: 경로 처리 오류 수정
81
- docs: README 업데이트
82
- ```
47
+ | Prefix | 용도 |
48
+ |--------|------|
49
+ | feat | 새 기능 |
50
+ | fix | 버그 수정 |
51
+ | refactor | 리팩토링 |
52
+ | docs | 문서 수정 |
53
+ | chore | 빌드/설정 |
83
54
 
84
55
  ---
85
56
 
86
- ## 📚 문서 참조 테이블
57
+ ## Tech Stack
87
58
 
88
- | 작업 | 문서 경로 | 필독 여부 |
89
- |------|----------|----------|
90
- | **Git 규칙** | `docs/git/git.md` | 🔴 필수 |
91
- | **MCP 도구** | `docs/mcp/` | 🔴 필수 |
92
- | **Commander** | `docs/library/commander/` | 🔴 필수 |
93
- | **fs-extra** | `docs/library/fs-extra/` | 🔴 필수 |
94
- | **prompts** | `docs/library/prompts/` | 🔴 필수 |
95
-
96
- ---
97
-
98
- ## 🛠 Tech Stack (버전 주의)
99
-
100
- | 기술 | 버전 | 주의사항 |
101
- |------|------|----------|
102
- | Node.js | >= 18 | ESM 모듈 사용 |
59
+ | 기술 | 버전 | 비고 |
60
+ |------|------|------|
61
+ | Node.js | >= 18 | ESM 모듈 |
103
62
  | TypeScript | 5.x | strict mode |
104
63
  | Commander | 12.x | CLI 프레임워크 |
105
- | fs-extra | 11.x | 파일 시스템 유틸리티 |
106
- | prompts | 2.x | Interactive CLI prompts |
107
- | picocolors | 1.x | 터미널 색상 출력 |
108
- | tsup | 8.x | TypeScript 번들러 |
64
+ | fs-extra | 11.x | 파일 시스템 |
65
+ | prompts | 2.x | Interactive prompts |
66
+ | picocolors | 1.x | 터미널 색상 |
67
+ | tsup | 8.x | 번들러 |
109
68
 
110
69
  ---
111
70
 
112
- ## 📁 Directory Structure
71
+ ## Directory Structure
113
72
 
114
73
  ```
115
74
  src/
116
- ├── index.ts # Entry point (CLI 정의)
117
- ├── commands/ # 명령어 모듈
118
- │ └── init.ts # init 명령어
119
- ├── utils/ # 유틸리티
120
- │ ├── copy.ts # 파일 복사 유틸
121
- │ └── logger.ts # 로깅 유틸
122
- └── types/ # 타입 정의
123
- └── index.ts # 공통 타입
124
-
125
- templates/ # 템플릿 파일 (빌드 시 복사)
126
- scripts/ # 빌드 스크립트
127
- dist/ # 빌드 결과물
128
- ```
129
-
130
- ---
131
-
132
- ## 🔧 Code Conventions
133
-
134
- ### File Naming
135
- - **kebab-case**: `copy-template.ts`, `file-utils.ts`
136
- - **index.ts**: 모듈 진입점
137
-
138
- ### TypeScript
139
- - `const` 선언 사용 (function 대신)
140
- - 명시적 return type
141
- - `interface` (객체) / `type` (유니온)
142
- - `any` 금지 → `unknown` 사용
143
-
144
- ### ESM Module
145
- ```typescript
146
- // ✅ ESM import
147
- import fs from 'fs-extra';
148
- import path from 'path';
149
- import { fileURLToPath } from 'url';
150
-
151
- // __dirname 대체
152
- const __filename = fileURLToPath(import.meta.url);
153
- const __dirname = path.dirname(__filename);
154
- ```
155
-
156
- ---
157
-
158
- ## 📝 Quick Patterns (복사용)
159
-
160
- ### CLI Entry Point
161
- ```typescript
162
- #!/usr/bin/env node
163
- import { Command } from 'commander';
164
-
165
- const program = new Command();
166
-
167
- program
168
- .name('my-cli')
169
- .description('CLI description')
170
- .version('1.0.0');
171
-
172
- program
173
- .option('-t, --template <name>', 'template name')
174
- .option('-f, --force', 'overwrite existing files')
175
- .action(async (options) => {
176
- // 명령어 실행
177
- });
178
-
179
- program.parse();
180
- ```
181
-
182
- ### Logger 유틸
183
- ```typescript
184
- import pc from 'picocolors';
185
-
186
- export const logger = {
187
- info: (msg: string) => console.log(pc.blue('ℹ'), msg),
188
- success: (msg: string) => console.log(pc.green('✔'), msg),
189
- warn: (msg: string) => console.log(pc.yellow('⚠'), msg),
190
- error: (msg: string) => console.log(pc.red('✖'), msg),
191
- step: (msg: string) => console.log(pc.gray(' →'), msg),
192
- blank: () => console.log(),
193
- };
194
- ```
195
-
196
- ### Interactive Prompts
197
- ```typescript
198
- import prompts from 'prompts';
199
-
200
- // Select (단일 선택)
201
- const { template } = await prompts({
202
- type: 'select',
203
- name: 'template',
204
- message: 'Select a template:',
205
- choices: [
206
- { title: 'Template A', value: 'a' },
207
- { title: 'Template B', value: 'b' },
208
- ],
209
- });
210
-
211
- // Multiselect (다중 선택)
212
- const { templates } = await prompts({
213
- type: 'multiselect',
214
- name: 'templates',
215
- message: 'Select templates:',
216
- choices: [
217
- { title: 'Template A', value: 'a' },
218
- { title: 'Template B', value: 'b' },
219
- ],
220
- min: 1,
221
- hint: '- Space to select. Return to submit',
222
- });
223
-
224
- // Confirm
225
- const { confirmed } = await prompts({
226
- type: 'confirm',
227
- name: 'confirmed',
228
- message: 'Overwrite existing files?',
229
- initial: false,
230
- });
231
- ```
232
-
233
- ### File Copy 유틸
234
- ```typescript
235
- import fs from 'fs-extra';
236
- import path from 'path';
237
-
238
- export const copyRecursive = async (
239
- src: string,
240
- dest: string,
241
- ): Promise<{ files: number; directories: number }> => {
242
- const counter = { files: 0, directories: 0 };
243
-
244
- const copy = async (s: string, d: string): Promise<void> => {
245
- const stat = await fs.stat(s);
246
-
247
- if (stat.isDirectory()) {
248
- await fs.ensureDir(d);
249
- counter.directories++;
250
-
251
- const items = await fs.readdir(s);
252
- for (const item of items) {
253
- await copy(path.join(s, item), path.join(d, item));
254
- }
255
- } else {
256
- await fs.copy(s, d);
257
- counter.files++;
258
- }
259
- };
260
-
261
- await copy(src, dest);
262
- return counter;
263
- };
264
- ```
265
-
266
- ### Package.json 설정
267
- ```json
268
- {
269
- "name": "@scope/my-cli",
270
- "version": "1.0.0",
271
- "type": "module",
272
- "bin": "./dist/index.js",
273
- "files": ["dist", "templates"],
274
- "scripts": {
275
- "build": "tsup",
276
- "dev": "tsup --watch",
277
- "prepublishOnly": "npm run build"
278
- },
279
- "engines": {
280
- "node": ">=18"
281
- }
282
- }
283
- ```
284
-
285
- ### tsup.config.ts
286
- ```typescript
287
- import { defineConfig } from 'tsup';
75
+ ├── index.ts # CLI 진입점
76
+ ├── commands/ # 명령어 모듈
77
+ │ └── init.ts
78
+ ├── utils/ # 유틸리티
79
+ │ ├── copy.ts
80
+ │ └── logger.ts
81
+ └── types/ # 타입 정의
288
82
 
289
- export default defineConfig({
290
- entry: ['src/index.ts'],
291
- format: ['esm'],
292
- target: 'node18',
293
- clean: true,
294
- dts: true,
295
- banner: {
296
- js: '#!/usr/bin/env node',
297
- },
298
- });
83
+ templates/ # 템플릿 (빌드 시 복사)
84
+ scripts/ # 빌드 스크립트
85
+ dist/ # 빌드 결과물
299
86
  ```
300
87
 
301
88
  ---
302
89
 
303
- ## 🔗 Quick Links
90
+ ## 참조
304
91
 
305
- - [Commander 가이드](./docs/library/commander/index.md)
306
- - [fs-extra 가이드](./docs/library/fs-extra/index.md)
307
- - [prompts 가이드](./docs/library/prompts/index.md)
308
- - [Git 규칙](./docs/git/git.md)
309
- - [MCP 가이드](./docs/mcp/index.md)
92
+ | 문서 | 경로 |
93
+ |------|------|
94
+ | Commander 가이드 | [docs/library/commander/](docs/library/commander/index.md) |
95
+ | fs-extra 가이드 | [docs/library/fs-extra/](docs/library/fs-extra/index.md) |
96
+ | prompts 가이드 | [docs/library/prompts/](docs/library/prompts/index.md) |
97
+ | 코드 패턴 | [docs/references/patterns.md](docs/references/patterns.md) |
@@ -0,0 +1,160 @@
1
+ # NPX CLI Patterns
2
+
3
+ > 복사용 코드 패턴 모음
4
+
5
+ ## CLI Entry Point
6
+
7
+ ```typescript
8
+ #!/usr/bin/env node
9
+ import { Command } from 'commander';
10
+
11
+ const program = new Command();
12
+
13
+ program
14
+ .name('my-cli')
15
+ .description('CLI description')
16
+ .version('1.0.0');
17
+
18
+ program
19
+ .option('-t, --template <name>', 'template name')
20
+ .option('-f, --force', 'overwrite existing files')
21
+ .action(async (options) => {
22
+ // 명령어 실행
23
+ });
24
+
25
+ program.parse();
26
+ ```
27
+
28
+ ## Logger 유틸
29
+
30
+ ```typescript
31
+ import pc from 'picocolors';
32
+
33
+ export const logger = {
34
+ info: (msg: string): void => console.log(pc.blue('ℹ'), msg),
35
+ success: (msg: string): void => console.log(pc.green('✔'), msg),
36
+ warn: (msg: string): void => console.log(pc.yellow('⚠'), msg),
37
+ error: (msg: string): void => console.log(pc.red('✖'), msg),
38
+ step: (msg: string): void => console.log(pc.gray(' →'), msg),
39
+ blank: (): void => console.log(),
40
+ };
41
+ ```
42
+
43
+ ## Interactive Prompts
44
+
45
+ ```typescript
46
+ import prompts from 'prompts';
47
+
48
+ // Select (단일 선택)
49
+ const { template } = await prompts({
50
+ type: 'select',
51
+ name: 'template',
52
+ message: 'Select a template:',
53
+ choices: [
54
+ { title: 'Template A', value: 'a' },
55
+ { title: 'Template B', value: 'b' },
56
+ ],
57
+ });
58
+
59
+ // Multiselect (다중 선택)
60
+ const { templates } = await prompts({
61
+ type: 'multiselect',
62
+ name: 'templates',
63
+ message: 'Select templates:',
64
+ choices: [
65
+ { title: 'Template A', value: 'a' },
66
+ { title: 'Template B', value: 'b' },
67
+ ],
68
+ min: 1,
69
+ hint: '- Space to select. Return to submit',
70
+ });
71
+
72
+ // Confirm
73
+ const { confirmed } = await prompts({
74
+ type: 'confirm',
75
+ name: 'confirmed',
76
+ message: 'Overwrite existing files?',
77
+ initial: false,
78
+ });
79
+ ```
80
+
81
+ ## File Copy 유틸
82
+
83
+ ```typescript
84
+ import fs from 'fs-extra';
85
+ import path from 'path';
86
+
87
+ export const copyRecursive = async (
88
+ src: string,
89
+ dest: string,
90
+ ): Promise<{ files: number; directories: number }> => {
91
+ const counter = { files: 0, directories: 0 };
92
+
93
+ const copy = async (s: string, d: string): Promise<void> => {
94
+ const stat = await fs.stat(s);
95
+
96
+ if (stat.isDirectory()) {
97
+ await fs.ensureDir(d);
98
+ counter.directories++;
99
+
100
+ const items = await fs.readdir(s);
101
+ for (const item of items) {
102
+ await copy(path.join(s, item), path.join(d, item));
103
+ }
104
+ } else {
105
+ await fs.copy(s, d);
106
+ counter.files++;
107
+ }
108
+ };
109
+
110
+ await copy(src, dest);
111
+ return counter;
112
+ };
113
+ ```
114
+
115
+ ## ESM __dirname
116
+
117
+ ```typescript
118
+ import { fileURLToPath } from 'url';
119
+ import path from 'path';
120
+
121
+ const __filename = fileURLToPath(import.meta.url);
122
+ const __dirname = path.dirname(__filename);
123
+ ```
124
+
125
+ ## Package.json
126
+
127
+ ```json
128
+ {
129
+ "name": "@scope/my-cli",
130
+ "version": "1.0.0",
131
+ "type": "module",
132
+ "bin": "./dist/index.js",
133
+ "files": ["dist", "templates"],
134
+ "scripts": {
135
+ "build": "tsup",
136
+ "dev": "tsup --watch",
137
+ "prepublishOnly": "npm run build"
138
+ },
139
+ "engines": {
140
+ "node": ">=18"
141
+ }
142
+ }
143
+ ```
144
+
145
+ ## tsup.config.ts
146
+
147
+ ```typescript
148
+ import { defineConfig } from 'tsup';
149
+
150
+ export default defineConfig({
151
+ entry: ['src/index.ts'],
152
+ format: ['esm'],
153
+ target: 'node18',
154
+ clean: true,
155
+ dts: true,
156
+ banner: {
157
+ js: '#!/usr/bin/env node',
158
+ },
159
+ });
160
+ ```