@kood/claude-code 0.5.3 → 0.5.5
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 +552 -340
- package/package.json +1 -1
- package/templates/.claude/agents/document-writer.md +73 -306
- package/templates/.claude/instructions/agent-patterns/index.md +7 -7
- package/templates/.claude/instructions/document-templates/ralph-templates.md +71 -0
- package/templates/.claude/instructions/index.md +14 -14
- package/templates/.claude/instructions/multi-agent/agent-roster.md +14 -14
- package/templates/.claude/instructions/multi-agent/index.md +4 -4
- package/templates/.claude/skills/docs-creator/AGENTS.md +54 -176
- package/templates/.claude/skills/docs-creator/SKILL.md +98 -464
- package/templates/.claude/skills/docs-refactor/AGENTS.md +61 -190
- package/templates/.claude/skills/docs-refactor/SKILL.md +67 -443
- package/templates/.claude/skills/execute/SKILL.md +540 -13
- package/templates/.claude/skills/plan/SKILL.md +84 -18
- package/templates/.claude/skills/ralph/SKILL.md +17 -14
- package/templates/.claude/skills/refactor/AGENTS.md +269 -0
- package/templates/.claude/skills/refactor/SKILL.md +424 -66
- package/templates/.claude/skills/stitch-design/README.md +34 -0
- package/templates/.claude/skills/stitch-design/SKILL.md +213 -0
- package/templates/.claude/skills/stitch-design/examples/DESIGN.md +154 -0
- package/templates/.claude/skills/stitch-loop/README.md +54 -0
- package/templates/.claude/skills/stitch-loop/SKILL.md +316 -0
- package/templates/.claude/skills/stitch-loop/examples/SITE.md +73 -0
- package/templates/.claude/skills/stitch-loop/examples/next-prompt.md +25 -0
- package/templates/.claude/skills/stitch-loop/resources/baton-schema.md +61 -0
- package/templates/.claude/skills/stitch-loop/resources/site-template.md +104 -0
- package/templates/.claude/skills/stitch-react/README.md +36 -0
- package/templates/.claude/skills/stitch-react/SKILL.md +323 -0
- package/templates/.claude/skills/stitch-react/examples/gold-standard-card.tsx +88 -0
- package/templates/.claude/skills/stitch-react/package-lock.json +231 -0
- package/templates/.claude/skills/stitch-react/package.json +16 -0
- package/templates/.claude/skills/stitch-react/resources/architecture-checklist.md +15 -0
- package/templates/.claude/skills/stitch-react/resources/component-template.tsx +37 -0
- package/templates/.claude/skills/stitch-react/resources/stitch-api-reference.md +14 -0
- package/templates/.claude/skills/stitch-react/resources/style-guide.json +24 -0
- package/templates/.claude/skills/stitch-react/scripts/fetch-stitch.sh +30 -0
- package/templates/.claude/skills/stitch-react/scripts/validate.js +77 -0
- package/templates/hono/CLAUDE.md +28 -28
- package/templates/hono/docs/architecture.md +24 -24
- package/templates/hono/docs/deployment/cloudflare.md +18 -18
- package/templates/hono/docs/deployment/docker.md +13 -13
- package/templates/hono/docs/deployment/index.md +19 -19
- package/templates/hono/docs/deployment/railway.md +32 -32
- package/templates/hono/docs/deployment/vercel.md +29 -29
- package/templates/hono/docs/guides/conventions.md +57 -57
- package/templates/hono/docs/guides/env-setup.md +47 -47
- package/templates/hono/docs/guides/getting-started.md +27 -27
- package/templates/hono/docs/library/hono/error-handling.md +11 -11
- package/templates/hono/docs/library/hono/index.md +4 -4
- package/templates/hono/docs/library/hono/middleware.md +18 -18
- package/templates/hono/docs/library/hono/rpc.md +7 -7
- package/templates/hono/docs/library/hono/validation.md +6 -6
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +29 -29
- package/templates/hono/docs/library/prisma/config.md +16 -16
- package/templates/hono/docs/library/prisma/index.md +32 -32
- package/templates/hono/docs/library/t3-env/index.md +22 -22
- package/templates/hono/docs/library/zod/index.md +31 -31
- package/templates/nextjs/CLAUDE.md +54 -54
- package/templates/nextjs/docs/architecture.md +146 -146
- package/templates/nextjs/docs/design.md +183 -183
- package/templates/nextjs/docs/guides/conventions.md +86 -86
- package/templates/nextjs/docs/guides/getting-started.md +28 -28
- package/templates/nextjs/docs/guides/routes.md +32 -32
- package/templates/nextjs/docs/library/better-auth/index.md +70 -70
- package/templates/nextjs/docs/library/nextjs/app-router.md +43 -43
- package/templates/nextjs/docs/library/nextjs/caching.md +73 -73
- package/templates/nextjs/docs/library/nextjs/index.md +51 -51
- package/templates/nextjs/docs/library/nextjs/middleware.md +41 -41
- package/templates/nextjs/docs/library/nextjs/route-handlers.md +31 -31
- package/templates/nextjs/docs/library/nextjs/server-actions.md +34 -34
- package/templates/nextjs/docs/library/prisma/cloudflare-d1.md +20 -20
- package/templates/nextjs/docs/library/prisma/config.md +18 -18
- package/templates/nextjs/docs/library/prisma/crud.md +17 -17
- package/templates/nextjs/docs/library/prisma/index.md +18 -18
- package/templates/nextjs/docs/library/prisma/relations.md +16 -16
- package/templates/nextjs/docs/library/prisma/schema.md +23 -23
- package/templates/nextjs/docs/library/prisma/setup.md +6 -6
- package/templates/nextjs/docs/library/prisma/transactions.md +10 -10
- package/templates/nextjs/docs/library/tanstack-query/index.md +6 -6
- package/templates/nextjs/docs/library/tanstack-query/invalidation.md +20 -20
- package/templates/nextjs/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/nextjs/docs/library/tanstack-query/use-mutation.md +15 -15
- package/templates/nextjs/docs/library/tanstack-query/use-query.md +22 -22
- package/templates/nextjs/docs/library/zod/complex-types.md +11 -11
- package/templates/nextjs/docs/library/zod/index.md +8 -8
- package/templates/nextjs/docs/library/zod/transforms.md +11 -11
- package/templates/nextjs/docs/library/zod/validation.md +9 -9
- package/templates/npx/CLAUDE.md +38 -38
- package/templates/npx/docs/library/commander/index.md +12 -12
- package/templates/npx/docs/library/fs-extra/index.md +9 -9
- package/templates/npx/docs/library/prompts/index.md +3 -3
- package/templates/npx/docs/references/patterns.md +12 -12
- package/templates/tanstack-start/CLAUDE.md +54 -54
- package/templates/tanstack-start/docs/architecture.md +128 -128
- package/templates/tanstack-start/docs/design.md +169 -169
- package/templates/tanstack-start/docs/guides/conventions.md +43 -43
- package/templates/tanstack-start/docs/guides/env-setup.md +35 -35
- package/templates/tanstack-start/docs/guides/getting-started.md +19 -19
- package/templates/tanstack-start/docs/guides/hooks.md +45 -45
- package/templates/tanstack-start/docs/guides/routes.md +54 -54
- package/templates/tanstack-start/docs/guides/services.md +45 -45
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +19 -19
- package/templates/tanstack-start/docs/library/prisma/config.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/crud.md +17 -17
- package/templates/tanstack-start/docs/library/prisma/relations.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/schema.md +23 -23
- package/templates/tanstack-start/docs/library/prisma/setup.md +6 -6
- package/templates/tanstack-start/docs/library/prisma/transactions.md +10 -10
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +19 -19
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +14 -14
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +21 -21
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +11 -11
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +17 -17
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +5 -5
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +10 -10
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +8 -8
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +6 -6
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +18 -18
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +4 -4
- package/templates/tanstack-start/docs/library/zod/complex-types.md +11 -11
- package/templates/tanstack-start/docs/library/zod/transforms.md +11 -11
- package/templates/tanstack-start/docs/library/zod/validation.md +9 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Zod -
|
|
1
|
+
# Zod - 검증
|
|
2
2
|
|
|
3
3
|
<patterns>
|
|
4
4
|
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
// Refinement (v4: message → error)
|
|
7
7
|
const PasswordSchema = z.string()
|
|
8
8
|
.min(8)
|
|
9
|
-
.refine((val) => /[A-Z]/.test(val), { error: '
|
|
10
|
-
.refine((val) => /[0-9]/.test(val), { error: '
|
|
9
|
+
.refine((val) => /[A-Z]/.test(val), { error: '대문자 필수' })
|
|
10
|
+
.refine((val) => /[0-9]/.test(val), { error: '숫자 필수' })
|
|
11
11
|
|
|
12
|
-
z.string().refine(val => val.includes("@")).min(5) // v4:
|
|
12
|
+
z.string().refine(val => val.includes("@")).min(5) // v4: refinement 후 체이닝
|
|
13
13
|
|
|
14
14
|
// Async
|
|
15
15
|
const schema = z.string().refine(async (val) => val.length <= 8)
|
|
@@ -23,20 +23,20 @@ z.object({
|
|
|
23
23
|
if (data.password !== data.confirmPassword) {
|
|
24
24
|
ctx.addIssue({
|
|
25
25
|
code: z.ZodIssueCode.custom,
|
|
26
|
-
message: '
|
|
26
|
+
message: '비밀번호 불일치',
|
|
27
27
|
path: ['confirmPassword'],
|
|
28
28
|
})
|
|
29
29
|
}
|
|
30
|
-
}) // v4: ctx.path
|
|
30
|
+
}) // v4: ctx.path 사용 불가
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// 커스텀
|
|
33
33
|
const px = z.custom<`${number}px`>((val) =>
|
|
34
34
|
typeof val === 'string' && /^\d+px$/.test(val)
|
|
35
35
|
)
|
|
36
36
|
px.parse('42px') // ✅
|
|
37
37
|
px.parse('42vw') // throws
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// 에러 처리
|
|
40
40
|
const result = schema.safeParse(data)
|
|
41
41
|
if (!result.success) {
|
|
42
42
|
result.error.errors.forEach((err) => {
|
|
@@ -50,7 +50,7 @@ export const createUser = createServerFn({ method: 'POST' })
|
|
|
50
50
|
.inputValidator(zodValidator(createUserSchema))
|
|
51
51
|
.handler(async ({ data }) => prisma.user.create({ data }))
|
|
52
52
|
|
|
53
|
-
//
|
|
53
|
+
// 환경 변수
|
|
54
54
|
const env = z.object({
|
|
55
55
|
NODE_ENV: z.enum(['development', 'production', 'test']),
|
|
56
56
|
DATABASE_URL: z.string().url(),
|
package/templates/npx/CLAUDE.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# CLAUDE.md - NPX CLI
|
|
2
2
|
|
|
3
|
-
> Node.js CLI
|
|
3
|
+
> Node.js CLI 도구 개발
|
|
4
4
|
|
|
5
5
|
<context>
|
|
6
6
|
|
|
7
|
-
**Purpose:**
|
|
7
|
+
**Purpose:** Node.js CLI 도구 개발을 위한 작업 지침
|
|
8
8
|
|
|
9
|
-
**Scope:**
|
|
9
|
+
**Scope:** npx 배포 가능한 CLI 패키지 구현
|
|
10
10
|
|
|
11
11
|
**Key Features:**
|
|
12
|
-
- Commander.js
|
|
13
|
-
-
|
|
14
|
-
-
|
|
12
|
+
- Commander.js 명령어 체계
|
|
13
|
+
- 대화형 프롬프트 (prompts)
|
|
14
|
+
- 파일 시스템 작업 (fs-extra)
|
|
15
15
|
- TypeScript + ESM
|
|
16
|
-
-
|
|
16
|
+
- 색상 출력 (picocolors)
|
|
17
17
|
|
|
18
18
|
</context>
|
|
19
19
|
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
|
|
32
32
|
<forbidden>
|
|
33
33
|
|
|
34
|
-
|
|
|
35
|
-
|
|
36
|
-
| **Git
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
34
|
+
| 분류 | 금지 행동 |
|
|
35
|
+
|------|----------|
|
|
36
|
+
| **Git 커밋** | AI 표시 (`Generated with Claude Code`, `🤖`, `Co-Authored-By:`), 여러 줄 메시지, 이모지 |
|
|
37
|
+
| **콘솔 출력** | `console.log` 직접 사용 (logger 함수 사용) |
|
|
38
|
+
| **파일 작업** | 동기 API (`fs.readFileSync` 등), 하드코딩된 경로 (path.join 사용) |
|
|
39
|
+
| **에러 처리** | `process.exit()` 누락, try-catch 없는 async 작업 |
|
|
40
|
+
| **코드 검색** | Bash의 grep/rg/find 명령어 (ast-grep 또는 전용 도구 사용) |
|
|
41
41
|
|
|
42
42
|
</forbidden>
|
|
43
43
|
|
|
@@ -45,16 +45,16 @@
|
|
|
45
45
|
|
|
46
46
|
<required>
|
|
47
47
|
|
|
48
|
-
|
|
|
49
|
-
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
48
|
+
| 작업 | 필수 행동 |
|
|
49
|
+
|------|----------|
|
|
50
|
+
| **작업 시작 전** | 관련 docs 읽기 (Commander → commander, 파일 → fs-extra) |
|
|
51
|
+
| **문서 검색** | serena mcp 사용 (문서 인덱싱/검색, context 길이 최적화) |
|
|
52
|
+
| **콘솔 출력** | logger 함수 사용 (info/success/error/warn) |
|
|
53
|
+
| **파일 작업** | async API (`fs-extra`), `path.join`으로 경로 조합 |
|
|
54
|
+
| **에러 처리** | try-catch + `process.exit(1)`, 사용자에게 명확한 에러 메시지 |
|
|
55
|
+
| **코드 검색** | ast-grep 사용 (함수/클래스/패턴 검색) |
|
|
56
|
+
| **코드 작성** | UTF-8 인코딩, 코드 묶음별 한글 주석, const 함수 선언 |
|
|
57
|
+
| **복잡한 작업** | Sequential Thinking MCP (5+ 단계 작업) |
|
|
58
58
|
|
|
59
59
|
</required>
|
|
60
60
|
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
|
|
63
63
|
<tech_stack>
|
|
64
64
|
|
|
65
|
-
|
|
|
66
|
-
|
|
65
|
+
| 기술 | 버전 |
|
|
66
|
+
|------|------|
|
|
67
67
|
| Node.js | >= 18 (ESM) |
|
|
68
68
|
| TypeScript | 5.x (strict) |
|
|
69
69
|
| Commander | 12.x |
|
|
@@ -79,13 +79,13 @@
|
|
|
79
79
|
<structure>
|
|
80
80
|
```
|
|
81
81
|
src/
|
|
82
|
-
├── index.ts # CLI
|
|
83
|
-
├── commands/ #
|
|
82
|
+
├── index.ts # CLI 진입점
|
|
83
|
+
├── commands/ # 명령어 모듈
|
|
84
84
|
├── utils/ # logger, copy
|
|
85
|
-
└── types/ #
|
|
85
|
+
└── types/ # 타입
|
|
86
86
|
|
|
87
|
-
templates/ #
|
|
88
|
-
dist/ #
|
|
87
|
+
templates/ # 빌드 시 복사
|
|
88
|
+
dist/ # 빌드 결과물
|
|
89
89
|
```
|
|
90
90
|
</structure>
|
|
91
91
|
|
|
@@ -93,9 +93,9 @@ dist/ # Build output
|
|
|
93
93
|
|
|
94
94
|
<conventions>
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
**TypeScript:** const
|
|
98
|
-
**Import
|
|
96
|
+
**파일명:** kebab-case
|
|
97
|
+
**TypeScript:** const 선언, 명시적 return type, interface(객체)/type(유니온), any→unknown
|
|
98
|
+
**Import 순서:** 외부 → 내부 → type
|
|
99
99
|
|
|
100
100
|
</conventions>
|
|
101
101
|
|
|
@@ -104,7 +104,7 @@ dist/ # Build output
|
|
|
104
104
|
<quick_patterns>
|
|
105
105
|
|
|
106
106
|
```typescript
|
|
107
|
-
// CLI
|
|
107
|
+
// CLI 진입점 (index.ts)
|
|
108
108
|
#!/usr/bin/env node
|
|
109
109
|
import { Command } from 'commander'
|
|
110
110
|
import { logger } from './utils/logger.js'
|
|
@@ -143,7 +143,7 @@ export const logger = {
|
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
```typescript
|
|
146
|
-
//
|
|
146
|
+
// 파일 복사 (utils/copy.ts)
|
|
147
147
|
import path from 'node:path'
|
|
148
148
|
import { copy, pathExists } from 'fs-extra'
|
|
149
149
|
|
|
@@ -163,7 +163,7 @@ export const copyTemplate = async (
|
|
|
163
163
|
```
|
|
164
164
|
|
|
165
165
|
```typescript
|
|
166
|
-
//
|
|
166
|
+
// 대화형 프롬프트
|
|
167
167
|
import prompts from 'prompts'
|
|
168
168
|
|
|
169
169
|
const response = await prompts([
|
|
@@ -193,6 +193,6 @@ const response = await prompts([
|
|
|
193
193
|
```
|
|
194
194
|
docs/
|
|
195
195
|
├── library/ # commander, fs-extra, prompts
|
|
196
|
-
└── references/ # CLI
|
|
196
|
+
└── references/ # CLI 패턴, 베스트 프랙티스
|
|
197
197
|
```
|
|
198
198
|
</docs_structure>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Commander.js
|
|
2
2
|
|
|
3
|
-
> Node.js CLI
|
|
3
|
+
> Node.js CLI 프레임워크
|
|
4
4
|
|
|
5
5
|
<patterns>
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 기본 설정
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
10
|
import { Command } from 'commander';
|
|
@@ -22,7 +22,7 @@ program.parse();
|
|
|
22
22
|
## Options
|
|
23
23
|
|
|
24
24
|
```typescript
|
|
25
|
-
//
|
|
25
|
+
// 기본
|
|
26
26
|
program
|
|
27
27
|
.option('-t, --template <name>', 'template name')
|
|
28
28
|
.option('-f, --force', 'force overwrite')
|
|
@@ -31,19 +31,19 @@ program
|
|
|
31
31
|
console.log(options.force); // boolean | undefined
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
//
|
|
34
|
+
// 필수
|
|
35
35
|
program
|
|
36
36
|
.requiredOption('-c, --config <path>', 'config file path')
|
|
37
37
|
.action((options) => {
|
|
38
|
-
// options.config
|
|
38
|
+
// options.config는 항상 존재
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
//
|
|
41
|
+
// 기본값
|
|
42
42
|
program
|
|
43
43
|
.option('-p, --port <number>', 'port number', '3000')
|
|
44
44
|
.option('-e, --env <name>', 'environment', 'development')
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// 여러 값
|
|
47
47
|
program
|
|
48
48
|
.option('-i, --include <path...>', 'include paths')
|
|
49
49
|
.action((options) => {
|
|
@@ -58,8 +58,8 @@ program
|
|
|
58
58
|
.argument('<source>', 'source file')
|
|
59
59
|
.argument('[destination]', 'destination file')
|
|
60
60
|
.action((source, destination, options) => {
|
|
61
|
-
console.log(source); //
|
|
62
|
-
console.log(destination); //
|
|
61
|
+
console.log(source); // 필수
|
|
62
|
+
console.log(destination); // 선택
|
|
63
63
|
});
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -71,14 +71,14 @@ program
|
|
|
71
71
|
.description('Initialize project')
|
|
72
72
|
.option('-t, --template <name>', 'template')
|
|
73
73
|
.action((options) => {
|
|
74
|
-
//
|
|
74
|
+
// init 처리
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
program
|
|
78
78
|
.command('build')
|
|
79
79
|
.description('Build project')
|
|
80
80
|
.action(() => {
|
|
81
|
-
//
|
|
81
|
+
// build 처리
|
|
82
82
|
});
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -95,7 +95,7 @@ program
|
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
await program.parseAsync(); // await
|
|
98
|
+
await program.parseAsync(); // await 필수
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
</patterns>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# fs-extra
|
|
2
2
|
|
|
3
|
-
> Node.js
|
|
3
|
+
> Node.js 파일 시스템 유틸리티
|
|
4
4
|
|
|
5
5
|
<patterns>
|
|
6
6
|
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
import fs from 'fs-extra';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
|
|
11
|
-
//
|
|
11
|
+
// 존재 확인
|
|
12
12
|
const exists = await fs.pathExists('/path/to/file');
|
|
13
13
|
|
|
14
|
-
//
|
|
14
|
+
// 디렉토리 생성
|
|
15
15
|
await fs.ensureDir('/path/to/nested/dir');
|
|
16
16
|
await fs.mkdir('/path/to/dir');
|
|
17
17
|
|
|
18
|
-
//
|
|
18
|
+
// 복사
|
|
19
19
|
await fs.copy('/src/file.txt', '/dest/file.txt');
|
|
20
20
|
await fs.copy('/src/dir', '/dest/dir');
|
|
21
21
|
await fs.copy(src, dest, {
|
|
@@ -24,18 +24,18 @@ await fs.copy(src, dest, {
|
|
|
24
24
|
filter: (src) => !src.includes('node_modules'),
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// 삭제
|
|
28
28
|
await fs.remove('/path/to/dir');
|
|
29
29
|
|
|
30
|
-
//
|
|
30
|
+
// 디렉토리 읽기
|
|
31
31
|
const items = await fs.readdir('/path/to/dir');
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// 파일 타입 확인
|
|
34
34
|
const stat = await fs.stat(itemPath);
|
|
35
35
|
if (stat.isDirectory()) { /* ... */ }
|
|
36
36
|
if (stat.isFile()) { /* ... */ }
|
|
37
37
|
|
|
38
|
-
//
|
|
38
|
+
// 파일 읽기/쓰기
|
|
39
39
|
const content = await fs.readFile('/path/to/file', 'utf-8');
|
|
40
40
|
await fs.writeFile('/path/to/file', content, 'utf-8');
|
|
41
41
|
|
|
@@ -43,7 +43,7 @@ await fs.writeFile('/path/to/file', content, 'utf-8');
|
|
|
43
43
|
const data = await fs.readJson('/path/to/file.json');
|
|
44
44
|
await fs.writeJson('/path/to/file.json', data, { spaces: 2 });
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// 재귀 복사
|
|
47
47
|
const copyRecursive = async (src: string, dest: string) => {
|
|
48
48
|
const counter = { files: 0, directories: 0 };
|
|
49
49
|
|
|
@@ -66,7 +66,7 @@ const { secret } = await prompts({
|
|
|
66
66
|
message: 'Enter password:',
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
//
|
|
69
|
+
// 취소 처리
|
|
70
70
|
const { template } = await prompts({ /* ... */ });
|
|
71
71
|
|
|
72
72
|
if (!template) {
|
|
@@ -74,14 +74,14 @@ if (!template) {
|
|
|
74
74
|
process.exit(0);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
//
|
|
77
|
+
// 연속 질문
|
|
78
78
|
const response = await prompts([
|
|
79
79
|
{ type: 'text', name: 'name', message: 'Project name?' },
|
|
80
80
|
{ type: 'select', name: 'template', message: 'Template?', choices: [...] },
|
|
81
81
|
{ type: 'confirm', name: 'git', message: 'Initialize git?' },
|
|
82
82
|
]);
|
|
83
83
|
|
|
84
|
-
//
|
|
84
|
+
// 조건부 질문
|
|
85
85
|
const response = await prompts([
|
|
86
86
|
{ type: 'confirm', name: 'useTypescript', message: 'Use TypeScript?' },
|
|
87
87
|
{ type: (prev) => prev ? 'confirm' : null, name: 'strict', message: 'Enable strict mode?' },
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# NPX CLI Patterns
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> CLI 구현 통합 패턴
|
|
4
4
|
|
|
5
5
|
<patterns>
|
|
6
6
|
|
|
7
|
-
## CLI
|
|
7
|
+
## CLI 진입점
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
10
|
#!/usr/bin/env node
|
|
@@ -35,7 +35,7 @@ program
|
|
|
35
35
|
program.parse();
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
## Logger
|
|
38
|
+
## Logger 유틸
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
41
|
import pc from 'picocolors';
|
|
@@ -49,7 +49,7 @@ export const logger = {
|
|
|
49
49
|
};
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
##
|
|
52
|
+
## 대화형 템플릿 선택
|
|
53
53
|
|
|
54
54
|
```typescript
|
|
55
55
|
import prompts from 'prompts';
|
|
@@ -61,7 +61,7 @@ export const selectAndCopyTemplate = async (
|
|
|
61
61
|
templatesDir: string,
|
|
62
62
|
targetDir: string,
|
|
63
63
|
): Promise<void> => {
|
|
64
|
-
// 1.
|
|
64
|
+
// 1. 템플릿 선택
|
|
65
65
|
const { template } = await prompts({
|
|
66
66
|
type: 'select',
|
|
67
67
|
name: 'template',
|
|
@@ -77,7 +77,7 @@ export const selectAndCopyTemplate = async (
|
|
|
77
77
|
process.exit(0);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// 2.
|
|
80
|
+
// 2. 덮어쓰기 확인
|
|
81
81
|
const targetExists = await fs.pathExists(targetDir);
|
|
82
82
|
if (targetExists) {
|
|
83
83
|
const { overwrite } = await prompts({
|
|
@@ -93,14 +93,14 @@ export const selectAndCopyTemplate = async (
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
// 3.
|
|
96
|
+
// 3. 복사
|
|
97
97
|
const src = path.join(templatesDir, template);
|
|
98
98
|
await fs.copy(src, targetDir, { overwrite: true });
|
|
99
99
|
logger.success(`Template copied to ${targetDir}`);
|
|
100
100
|
};
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
## ESM __dirname
|
|
103
|
+
## ESM __dirname 처리
|
|
104
104
|
|
|
105
105
|
```typescript
|
|
106
106
|
import { fileURLToPath } from 'url';
|
|
@@ -109,11 +109,11 @@ import path from 'path';
|
|
|
109
109
|
const __filename = fileURLToPath(import.meta.url);
|
|
110
110
|
const __dirname = path.dirname(__filename);
|
|
111
111
|
|
|
112
|
-
//
|
|
112
|
+
// 템플릿 디렉토리 경로
|
|
113
113
|
const templatesDir = path.resolve(__dirname, '../templates');
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
##
|
|
116
|
+
## 재귀 복사 with Counter
|
|
117
117
|
|
|
118
118
|
```typescript
|
|
119
119
|
import fs from 'fs-extra';
|
|
@@ -147,7 +147,7 @@ export const copyRecursive = async (
|
|
|
147
147
|
};
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
## package.json
|
|
150
|
+
## package.json 설정
|
|
151
151
|
|
|
152
152
|
```json
|
|
153
153
|
{
|
|
@@ -167,7 +167,7 @@ export const copyRecursive = async (
|
|
|
167
167
|
}
|
|
168
168
|
```
|
|
169
169
|
|
|
170
|
-
## tsup
|
|
170
|
+
## tsup 설정
|
|
171
171
|
|
|
172
172
|
```typescript
|
|
173
173
|
import { defineConfig } from 'tsup';
|
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
<context>
|
|
6
6
|
|
|
7
|
-
**Purpose:**
|
|
7
|
+
**Purpose:** TanStack Start 프레임워크 개발을 위한 작업 지침
|
|
8
8
|
|
|
9
|
-
**Scope:** Full-stack React
|
|
9
|
+
**Scope:** Full-stack React 애플리케이션 구현
|
|
10
10
|
|
|
11
11
|
**Key Features:**
|
|
12
12
|
- File-based routing (TanStack Router)
|
|
13
|
-
- Server Functions (
|
|
13
|
+
- Server Functions (타입 안전 API)
|
|
14
14
|
- SSR + Streaming
|
|
15
|
-
- TanStack Query
|
|
16
|
-
- Middleware
|
|
17
|
-
- Deployment
|
|
15
|
+
- TanStack Query 통합
|
|
16
|
+
- Middleware 체계
|
|
17
|
+
- Deployment 유연성 (Vercel, Cloudflare, Nitro)
|
|
18
18
|
|
|
19
19
|
</context>
|
|
20
20
|
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
|
|
37
37
|
<forbidden>
|
|
38
38
|
|
|
39
|
-
|
|
|
40
|
-
|
|
41
|
-
| **Git
|
|
42
|
-
| **Prisma** |
|
|
43
|
-
| **API
|
|
44
|
-
| **Server Fn** |
|
|
45
|
-
|
|
|
46
|
-
|
|
|
39
|
+
| 분류 | 금지 행동 |
|
|
40
|
+
|------|----------|
|
|
41
|
+
| **Git 커밋** | AI 표시 (`Generated with Claude Code`, `🤖`, `Co-Authored-By:`), 여러 줄 메시지, 이모지 |
|
|
42
|
+
| **Prisma** | `db push/migrate/generate` 자동 실행, `schema.prisma` 무단 수정 |
|
|
43
|
+
| **API 라우터** | `/api` 경로에 라우터 생성 (Server Functions 사용) |
|
|
44
|
+
| **Server Fn** | handler 내부에서 수동 검증/인증, `.validator()` 사용 (`.inputValidator()` 사용) |
|
|
45
|
+
| **클라이언트** | Server Function 직접 호출 (TanStack Query 사용) |
|
|
46
|
+
| **코드 검색** | Bash의 grep/rg/find 명령어 (ast-grep 또는 전용 도구 사용) |
|
|
47
47
|
|
|
48
48
|
</forbidden>
|
|
49
49
|
|
|
@@ -51,18 +51,18 @@
|
|
|
51
51
|
|
|
52
52
|
<required>
|
|
53
53
|
|
|
54
|
-
|
|
|
55
|
-
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
| **Server Function** | POST/PUT/PATCH → `.inputValidator()`
|
|
62
|
-
|
|
|
63
|
-
| **Custom Hook
|
|
64
|
-
|
|
|
65
|
-
| **Prisma** | Multi-File
|
|
54
|
+
| 작업 | 필수 행동 |
|
|
55
|
+
|------|----------|
|
|
56
|
+
| **작업 시작 전** | 관련 docs 읽기 (UI → design, API → tanstack-start, DB → prisma, 인증 → better-auth) |
|
|
57
|
+
| **문서 검색** | serena mcp 사용 (문서 인덱싱/검색, context 길이 최적화) |
|
|
58
|
+
| **코드 검색** | ast-grep 사용 (함수/컴포넌트/패턴 검색) |
|
|
59
|
+
| **복잡한 작업** | Sequential Thinking MCP (5+ 단계 작업) |
|
|
60
|
+
| **대규모 수정** | gemini-review (3+ 파일 변경, 아키텍처 결정) |
|
|
61
|
+
| **Server Function** | POST/PUT/PATCH → `.inputValidator()` 필수, 인증 필요 시 → `.middleware()` 필수 |
|
|
62
|
+
| **클라이언트 API** | TanStack Query (`useQuery`/`useMutation`)로 Server Function 호출 |
|
|
63
|
+
| **Custom Hook 순서** | State → Global Hooks (useParams, useNavigate) → React Query → Handlers → Memo → Effect |
|
|
64
|
+
| **코드 작성** | UTF-8 인코딩, 코드 묶음별 한글 주석, const 함수 선언 |
|
|
65
|
+
| **Prisma** | Multi-File 구조 (`prisma/schema/`), 모든 요소 한글 주석 필수 |
|
|
66
66
|
|
|
67
67
|
</required>
|
|
68
68
|
|
|
@@ -70,14 +70,14 @@
|
|
|
70
70
|
|
|
71
71
|
<tech_stack>
|
|
72
72
|
|
|
73
|
-
|
|
|
74
|
-
|
|
75
|
-
| TanStack Start |
|
|
73
|
+
| 기술 | 버전 | 주의 |
|
|
74
|
+
|------|------|------|
|
|
75
|
+
| TanStack Start | 최신 | - |
|
|
76
76
|
| TypeScript | 5.x | strict |
|
|
77
77
|
| Tailwind CSS | 4.x | @theme |
|
|
78
|
-
| Prisma | **7.x** | `prisma-client`, output
|
|
78
|
+
| Prisma | **7.x** | `prisma-client`, output 필수 |
|
|
79
79
|
| Zod | **4.x** | `z.email()`, `z.url()` |
|
|
80
|
-
| Better Auth |
|
|
80
|
+
| Better Auth | 최신 | - |
|
|
81
81
|
| TanStack Query | 5.x | - |
|
|
82
82
|
|
|
83
83
|
</tech_stack>
|
|
@@ -89,36 +89,36 @@
|
|
|
89
89
|
src/
|
|
90
90
|
├── routes/ # __root.tsx, index.tsx, $slug.tsx
|
|
91
91
|
│ └── [path]/
|
|
92
|
-
│ ├── -components/ #
|
|
93
|
-
│ ├── -hooks/ #
|
|
94
|
-
│ └── -functions/ #
|
|
95
|
-
├── functions/ #
|
|
92
|
+
│ ├── -components/ # 페이지 전용 (필수)
|
|
93
|
+
│ ├── -hooks/ # 페이지 전용 Custom Hooks (필수)
|
|
94
|
+
│ └── -functions/ # 페이지 전용 Server Functions (필수)
|
|
95
|
+
├── functions/ # 공통 Server Functions
|
|
96
96
|
├── components/ui/
|
|
97
97
|
├── middleware/
|
|
98
98
|
├── database/prisma.ts
|
|
99
99
|
└── lib/
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
- Custom
|
|
105
|
-
-
|
|
102
|
+
**필수 규칙:**
|
|
103
|
+
- 페이지당 `-components/`, `-hooks/`, `-functions/` 폴더 필수 (줄 수 무관)
|
|
104
|
+
- Custom Hook은 페이지 크기와 무관하게 **반드시** `-hooks/` 폴더에 분리
|
|
105
|
+
- 공통 함수 → `@/functions/`, 라우트 전용 → `routes/[경로]/-functions/`
|
|
106
106
|
</structure>
|
|
107
107
|
|
|
108
108
|
---
|
|
109
109
|
|
|
110
110
|
<conventions>
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
TypeScript: const
|
|
114
|
-
Import
|
|
112
|
+
파일명: kebab-case, Routes: `__root.tsx`, `$param.tsx`
|
|
113
|
+
TypeScript: const 선언, 명시적 return type, interface(객체)/type(유니온), any→unknown
|
|
114
|
+
Import 순서: 외부 → @/ → 상대경로 → type
|
|
115
115
|
|
|
116
116
|
Prisma Multi-File:
|
|
117
117
|
```
|
|
118
118
|
prisma/schema/
|
|
119
119
|
├── +base.prisma # datasource, generator
|
|
120
|
-
├── +enum.prisma #
|
|
121
|
-
└── [model].prisma #
|
|
120
|
+
├── +enum.prisma # enum
|
|
121
|
+
└── [model].prisma # 모델별 (한글 주석!)
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
</conventions>
|
|
@@ -128,12 +128,12 @@ prisma/schema/
|
|
|
128
128
|
<quick_patterns>
|
|
129
129
|
|
|
130
130
|
```typescript
|
|
131
|
-
// Server Function (GET +
|
|
131
|
+
// Server Function (GET + 인증)
|
|
132
132
|
export const getUsers = createServerFn({ method: 'GET' })
|
|
133
133
|
.middleware([authMiddleware])
|
|
134
134
|
.handler(async () => prisma.user.findMany())
|
|
135
135
|
|
|
136
|
-
// Server Function (POST + Validation +
|
|
136
|
+
// Server Function (POST + Validation + 인증)
|
|
137
137
|
export const createUser = createServerFn({ method: 'POST' })
|
|
138
138
|
.middleware([authMiddleware])
|
|
139
139
|
.inputValidator(createUserSchema)
|
|
@@ -166,12 +166,12 @@ const mutation = useMutation({
|
|
|
166
166
|
|
|
167
167
|
<ui_ux>
|
|
168
168
|
|
|
169
|
-
|
|
|
170
|
-
|
|
171
|
-
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
|
169
|
+
| 원칙 | 값 |
|
|
170
|
+
|------|------|
|
|
171
|
+
| 색상 | 60-30-10 (배경-보조-강조) |
|
|
172
|
+
| 간격 | 8px 그리드 |
|
|
173
|
+
| 접근성 | WCAG AA (대비 4.5:1+) |
|
|
174
|
+
| 폰트 | 2-3개 |
|
|
175
175
|
| Safe Area | tailwindcss-safe-area |
|
|
176
176
|
|
|
177
177
|
</ui_ux>
|
|
@@ -181,8 +181,8 @@ const mutation = useMutation({
|
|
|
181
181
|
<docs_structure>
|
|
182
182
|
```
|
|
183
183
|
docs/
|
|
184
|
-
├── guides/ #
|
|
184
|
+
├── guides/ # 시작하기, 규칙, 패턴
|
|
185
185
|
├── library/ # tanstack-start/router/query, prisma, better-auth, t3-env, zod
|
|
186
|
-
└── design.md # UI/UX
|
|
186
|
+
└── design.md # UI/UX 가이드
|
|
187
187
|
```
|
|
188
188
|
</docs_structure>
|