sleepcode 1.2.0 → 1.4.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.
@@ -11,7 +11,8 @@
11
11
  "Bash(npm publish)",
12
12
  "Bash(npm version:*)",
13
13
  "Bash(NPM_TOKEN=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 npm publish:*)",
14
- "Bash(NPM_TOKEN=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 npm publish)"
14
+ "Bash(NPM_TOKEN=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 npm publish)",
15
+ "Bash(git push:*)"
15
16
  ]
16
17
  }
17
18
  }
package/README.md CHANGED
@@ -31,7 +31,22 @@ npx sleepcode
31
31
 
32
32
  인터랙티브 모드로 프로젝트 타입, 이름, AI 역할 등을 설정합니다.
33
33
 
34
- ### 2. 태스크 작성
34
+ ### 2. 참고 자료 추가
35
+
36
+ `.sleepcode/docs/`에 기획서, 피그마 스크린샷 등 참고 자료를 넣습니다.
37
+
38
+ ### 3. 태스크 작성
39
+
40
+ **방법 A: 자동 생성 (추천)**
41
+
42
+ ```bash
43
+ npx sleepcode generate
44
+ ```
45
+
46
+ 참고 자료(docs/, Figma, Notion)와 프로젝트 구조를 분석해서 `tasks.md`를 자동 생성합니다.
47
+ 이미 구현된 기능은 제외됩니다.
48
+
49
+ **방법 B: 직접 작성**
35
50
 
36
51
  `.sleepcode/tasks.md` 에 AI가 수행할 작업을 작성합니다:
37
52
 
@@ -43,27 +58,19 @@ npx sleepcode
43
58
  - [ ] 홈 화면 UI 개선
44
59
  ```
45
60
 
46
- ### 3. 실행
61
+ ### 4. 실행
47
62
 
48
- **macOS / Linux:**
49
63
  ```bash
50
64
  # 1회 실행
51
- ./.sleepcode/scripts/ai_worker.sh
65
+ npx sleepcode run
52
66
 
53
- # 무한 루프 (tmux 권장)
54
- tmux new -s ai './.sleepcode/scripts/run_forever.sh'
67
+ # 무한 루프 (잠자기 )
68
+ npx sleepcode run --loop
55
69
  ```
56
70
 
57
- **Windows (PowerShell):**
58
- ```powershell
59
- # 1회 실행
60
- powershell -File .\.sleepcode\scripts\ai_worker.ps1
61
-
62
- # 무한 루프
63
- powershell -File .\.sleepcode\scripts\run_forever.ps1
64
- ```
71
+ OS에 맞는 스크립트를 자동으로 선택합니다 (macOS/Linux: `.sh`, Windows: `.ps1`).
65
72
 
66
- ### 4. 아침에 확인
73
+ ### 5. 아침에 확인
67
74
 
68
75
  ```bash
69
76
  git log --oneline --since="12 hours ago"
@@ -82,6 +89,15 @@ git log --oneline --since="12 hours ago"
82
89
 
83
90
  ---
84
91
 
92
+ ## CLI 명령어
93
+
94
+ | 명령어 | 설명 |
95
+ |--------|------|
96
+ | `npx sleepcode` | 인터랙티브 초기화 |
97
+ | `npx sleepcode run` | 1회 실행 |
98
+ | `npx sleepcode run --loop` | 무한 루프 실행 |
99
+ | `npx sleepcode generate` | 참고자료 기반 tasks.md 자동 생성 |
100
+
85
101
  ## CLI 옵션
86
102
 
87
103
  인터랙티브 모드 외에 CLI 인자로도 사용 가능합니다:
@@ -96,6 +112,9 @@ npx sleepcode --type react-native --name my-app --role "쇼핑몰 앱 개발"
96
112
  | `--name <name>` | 프로젝트 이름 |
97
113
  | `--role <desc>` | AI 역할 설명 |
98
114
  | `--figma-key <key>` | Figma API Key (선택) |
115
+ | `--figma-file <name>` | Figma 참고 파일명 (선택) |
116
+ | `--notion-key <key>` | Notion API Key (선택) |
117
+ | `--notion-page <name>` | Notion 참고 페이지명 (선택) |
99
118
  | `--interval <sec>` | 반복 간격 초 (기본: 30) |
100
119
  | `-f, --force` | 기존 `.sleepcode/` 폴더 덮어쓰기 |
101
120
  | `-h, --help` | 도움말 |
@@ -109,7 +128,8 @@ npx sleepcode --type react-native --name my-app --role "쇼핑몰 앱 개발"
109
128
  rules.md # ✏️ AI 역할 + 작업 규칙 (수정하세요)
110
129
  tasks.md # ✏️ 작업 목록 (수정하세요)
111
130
  docs/ # ✏️ 참고 자료 (피그마 스크린샷, 기획서 등)
112
- scripts/ # ⚙️ 시스템 스크립트 (수정하지 마세요)
131
+ scripts/ # ⚙️ 시스템 (수정하지 마세요)
132
+ base_rules.md # 공통 작업 규칙
113
133
  ai_worker.sh/.ps1 # 1회 실행 스크립트 (OS별)
114
134
  run_forever.sh/.ps1 # 무한 루프 스크립트 (OS별)
115
135
  log_filter.py # 실시간 로그 필터
@@ -153,7 +173,7 @@ rules.md + tasks.md → 프롬프트 조합 → claude -p (비대화형) → 코
153
173
 
154
174
  | 동작 | 명령어 |
155
175
  |------|--------|
156
- | 세션 생성 + 실행 | `tmux new -s ai './.sleepcode/scripts/run_forever.sh'` |
176
+ | 세션 생성 + 실행 | `tmux new -s ai 'npx sleepcode run --loop'` |
157
177
  | 백그라운드 전환 | `Ctrl+B` → `D` |
158
178
  | 세션 재접속 | `tmux attach -t ai` |
159
179
  | 실시간 로그 | `tail -f .sleepcode/logs/worker_*.log` |
package/bin/index.js CHANGED
@@ -190,19 +190,32 @@ function parseArgs() {
190
190
  else if (args[i] === '--name' && args[i + 1]) parsed.name = args[++i];
191
191
  else if (args[i] === '--role' && args[i + 1]) parsed.role = args[++i];
192
192
  else if (args[i] === '--figma-key' && args[i + 1]) parsed.figmaKey = args[++i];
193
+ else if (args[i] === '--figma-file' && args[i + 1]) parsed.figmaFileNames = args[++i];
194
+ else if (args[i] === '--notion-key' && args[i + 1]) parsed.notionKey = args[++i];
195
+ else if (args[i] === '--notion-page' && args[i + 1]) parsed.notionPages = args[++i];
193
196
  else if (args[i] === '--interval' && args[i + 1]) parsed.interval = args[++i];
194
197
  else if (args[i] === '--force' || args[i] === '-f') parsed.force = true;
195
198
  else if (args[i] === '--help' || args[i] === '-h') {
196
199
  console.log(`
197
200
  사용법: sleepcode [옵션]
201
+ sleepcode run [--loop]
202
+ sleepcode generate
198
203
 
199
204
  옵션 없이 실행하면 인터랙티브 모드로 동작합니다.
200
205
 
206
+ 명령어:
207
+ run 1회 실행 (ai_worker 스크립트)
208
+ run --loop 무한 루프 실행 (run_forever 스크립트)
209
+ generate 참고자료 기반으로 tasks.md 자동 생성
210
+
201
211
  옵션:
202
212
  --type <type> 프로젝트 타입 (spring-boot, react-native, nextjs, custom)
203
213
  --name <name> 프로젝트 이름
204
214
  --role <desc> AI 역할 설명
205
215
  --figma-key <key> Figma API Key
216
+ --figma-file <name> Figma 참고 파일명
217
+ --notion-key <key> Notion API Key
218
+ --notion-page <name> Notion 참고 페이지명
206
219
  --interval <sec> 반복 간격 (초, 기본 30)
207
220
  -f, --force 기존 .sleepcode/ 덮어쓰기
208
221
  -h, --help 도움말
@@ -246,7 +259,7 @@ function writeFile(filePath, content) {
246
259
  fs.writeFileSync(filePath, content);
247
260
  }
248
261
 
249
- function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCmd, lintCmd, figmaKey, sleepInterval }) {
262
+ function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCmd, lintCmd, figmaKey, figmaFileNames, notionKey, notionPages, sleepInterval }) {
250
263
  const scDir = path.join(targetDir, '.sleepcode');
251
264
  const claudeDir = path.join(targetDir, '.claude');
252
265
  fs.mkdirSync(path.join(scDir, 'docs'), { recursive: true });
@@ -270,6 +283,36 @@ function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCm
270
283
  }
271
284
  }
272
285
 
286
+ // base_rules.md → scripts/ 하위로 복사 (Figma/Notion 섹션 조건부 처리)
287
+ const baseRulesSrc = path.join(TEMPLATES_DIR, 'common', 'base_rules.md');
288
+ if (fs.existsSync(baseRulesSrc)) {
289
+ let baseRules = fs.readFileSync(baseRulesSrc, 'utf-8');
290
+
291
+ // Figma 섹션
292
+ if (figmaKey) {
293
+ let figmaSection = `## Figma\n\n- **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: \`${figmaKey}\`)`;
294
+ if (figmaFileNames) {
295
+ figmaSection += `\n- **참고 파일**: ${figmaFileNames}`;
296
+ }
297
+ baseRules = baseRules.replace('{{FIGMA_SECTION}}', figmaSection);
298
+ } else {
299
+ baseRules = baseRules.replace('\n{{FIGMA_SECTION}}\n', '');
300
+ }
301
+
302
+ // Notion 섹션
303
+ if (notionKey) {
304
+ let notionSection = `\n## Notion\n\n- **기획/문서**: Notion MCP 도구로 직접 조회 가능 (API Key: \`${notionKey}\`)`;
305
+ if (notionPages) {
306
+ notionSection += `\n- **참고 페이지**: ${notionPages}`;
307
+ }
308
+ baseRules = baseRules.replace('{{NOTION_SECTION}}', notionSection);
309
+ } else {
310
+ baseRules = baseRules.replace('\n{{NOTION_SECTION}}\n', '');
311
+ }
312
+
313
+ fs.writeFileSync(path.join(scDir, 'scripts', 'base_rules.md'), baseRules);
314
+ }
315
+
273
316
  // README.md → .sleepcode/ 루트에 복사
274
317
  const readmeSrc = path.join(TEMPLATES_DIR, 'common', 'README.md');
275
318
  if (fs.existsSync(readmeSrc)) {
@@ -308,12 +351,6 @@ function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCm
308
351
  rules = rules.replace(/\{\{BUILD_CMD\}\}/g, buildCmd);
309
352
  rules = rules.replace(/\{\{TEST_CMD\}\}/g, testCmd);
310
353
  rules = rules.replace(/\{\{LINT_CMD\}\}/g, lintCmd);
311
- rules = rules.replace(/\{\{FIGMA_API_KEY\}\}/g, figmaKey);
312
-
313
- if (!figmaKey) {
314
- rules = rules.replace(/\n## Figma[\s\S]*?(?=\n## |$)/, '');
315
- }
316
-
317
354
  writeFile(path.join(scDir, 'rules.md'), rules);
318
355
  }
319
356
 
@@ -342,44 +379,195 @@ function printResult() {
342
379
  console.log(` ${C.green}✓${C.reset} .sleepcode/rules.md ${C.dim}← 수정하세요${C.reset}`);
343
380
  console.log(` ${C.green}✓${C.reset} .sleepcode/tasks.md ${C.dim}← 수정하세요${C.reset}`);
344
381
  console.log(` ${C.green}✓${C.reset} .sleepcode/docs/ ${C.dim}← 참고자료 추가${C.reset}`);
382
+ console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/base_rules.md`);
345
383
  console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/${workerScript}`);
346
384
  console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/${foreverScript}`);
347
385
  console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/log_filter.py`);
348
386
  console.log(` ${C.green}✓${C.reset} .sleepcode/README.md`);
349
387
  console.log(` ${C.green}✓${C.reset} .claude/settings.local.json`);
350
388
 
351
- if (IS_WIN) {
352
- console.log(`
389
+ console.log(`
353
390
  ${C.bold}${C.green}완료!${C.reset} 다음 단계:
354
391
 
355
392
  ${C.bold}1.${C.reset} .sleepcode/rules.md 를 프로젝트에 맞게 수정
356
- ${C.bold}2.${C.reset} .sleepcode/tasks.md작업 목록 작성
357
- ${C.bold}3.${C.reset} 실행 (PowerShell):
358
- ${C.dim}# 1회 실행${C.reset}
359
- powershell -File .\\.sleepcode\\scripts\\ai_worker.ps1
360
-
361
- ${C.dim}# 무한 루프${C.reset}
362
- powershell -File .\\.sleepcode\\scripts\\run_forever.ps1
393
+ ${C.bold}2.${C.reset} .sleepcode/docs/참고 자료 추가 (기획서, 스크린샷 등)
394
+ ${C.bold}3.${C.reset} 태스크 생성:
395
+ ${C.cyan}npx sleepcode generate${C.reset} ${C.dim}# 참고자료 기반 tasks.md 자동 생성${C.reset}
396
+ ${C.dim}또는 .sleepcode/tasks.md 를 직접 작성${C.reset}
397
+ ${C.bold}4.${C.reset} 실행:
398
+ ${C.cyan}npx sleepcode run${C.reset} ${C.dim}# 1회 실행${C.reset}
399
+ ${C.cyan}npx sleepcode run --loop${C.reset} ${C.dim}# 무한 루프${C.reset}
363
400
  `);
364
- } else {
365
- console.log(`
366
- ${C.bold}${C.green}완료!${C.reset} 다음 단계:
401
+ }
367
402
 
368
- ${C.bold}1.${C.reset} .sleepcode/rules.md 프로젝트에 맞게 수정
369
- ${C.bold}2.${C.reset} .sleepcode/tasks.md 에 작업 목록 작성
370
- ${C.bold}3.${C.reset} 실행:
371
- ${C.dim}# 1회 실행${C.reset}
372
- ./.sleepcode/scripts/ai_worker.sh
403
+ // ─── 실행 명령어 ───
404
+ function runWorker(loop) {
405
+ const targetDir = process.cwd();
406
+ const scDir = path.join(targetDir, '.sleepcode', 'scripts');
373
407
 
374
- ${C.dim}# 무한 루프 (tmux)${C.reset}
375
- tmux new -s ai './.sleepcode/scripts/run_forever.sh'
376
- `);
408
+ if (!fs.existsSync(scDir)) {
409
+ console.error(`${C.red}.sleepcode/scripts/ 폴더가 없습니다. 먼저 'npx sleepcode'로 초기화하세요.${C.reset}`);
410
+ process.exit(1);
411
+ }
412
+
413
+ const scriptName = loop
414
+ ? (IS_WIN ? 'run_forever.ps1' : 'run_forever.sh')
415
+ : (IS_WIN ? 'ai_worker.ps1' : 'ai_worker.sh');
416
+ const scriptPath = path.join(scDir, scriptName);
417
+
418
+ if (!fs.existsSync(scriptPath)) {
419
+ console.error(`${C.red}스크립트를 찾을 수 없습니다: ${scriptPath}${C.reset}`);
420
+ process.exit(1);
421
+ }
422
+
423
+ const cmd = IS_WIN
424
+ ? `powershell -File "${scriptPath}"`
425
+ : `"${scriptPath}"`;
426
+
427
+ console.log(`${C.cyan}${loop ? '무한 루프' : '1회'} 실행: ${scriptName}${C.reset}\n`);
428
+
429
+ try {
430
+ execSync(cmd, { stdio: 'inherit', cwd: targetDir });
431
+ } catch (e) {
432
+ process.exit(e.status || 1);
433
+ }
434
+ }
435
+
436
+ // ─── 태스크 자동 생성 ───
437
+ function generateTasks() {
438
+ const targetDir = process.cwd();
439
+ const scDir = path.join(targetDir, '.sleepcode');
440
+
441
+ if (!fs.existsSync(scDir)) {
442
+ console.error(`${C.red}.sleepcode/ 폴더가 없습니다. 먼저 'npx sleepcode'로 초기화하세요.${C.reset}`);
443
+ process.exit(1);
444
+ }
445
+
446
+ // claude CLI 확인
447
+ if (!checkCommand('claude --version')) {
448
+ console.error(`${C.red}claude CLI가 설치되어 있지 않습니다.${C.reset}`);
449
+ process.exit(1);
450
+ }
451
+
452
+ console.log(`${C.cyan}태스크 자동 생성 중...${C.reset}\n`);
453
+
454
+ // 참고 자료 수집
455
+ const parts = [];
456
+
457
+ // 1. base_rules.md (프로젝트 공통 규칙 — 역할 파악용)
458
+ const baseRulesPath = path.join(scDir, 'scripts', 'base_rules.md');
459
+ if (fs.existsSync(baseRulesPath)) {
460
+ parts.push(fs.readFileSync(baseRulesPath, 'utf-8'));
461
+ }
462
+
463
+ // 2. rules.md (프로젝트별 역할/작업방식)
464
+ const rulesPath = path.join(scDir, 'rules.md');
465
+ if (fs.existsSync(rulesPath)) {
466
+ parts.push(fs.readFileSync(rulesPath, 'utf-8'));
467
+ }
468
+
469
+ // 3. docs/ 디렉토리 파일 목록 + 내용
470
+ const docsDir = path.join(scDir, 'docs');
471
+ if (fs.existsSync(docsDir)) {
472
+ const files = fs.readdirSync(docsDir).filter(f => f !== '.gitkeep');
473
+ for (const file of files) {
474
+ const filePath = path.join(docsDir, file);
475
+ const stat = fs.statSync(filePath);
476
+ if (stat.isFile() && stat.size < 100000) {
477
+ // 텍스트 파일만 읽기 (이미지 등은 파일명만)
478
+ const ext = path.extname(file).toLowerCase();
479
+ if (['.md', '.txt', '.json', '.yaml', '.yml', '.csv', '.html'].includes(ext)) {
480
+ parts.push(`--- docs/${file} ---\n${fs.readFileSync(filePath, 'utf-8')}`);
481
+ } else {
482
+ parts.push(`--- docs/${file} --- (파일 존재, 내용은 직접 참고)`);
483
+ }
484
+ }
485
+ }
486
+ }
487
+
488
+ // 4. 현재 프로젝트 구조 (이미 구현된 것 파악용)
489
+ try {
490
+ const tree = execSync('git ls-files', { cwd: targetDir, stdio: ['pipe', 'pipe', 'pipe'], timeout: 10000 })
491
+ .toString().trim();
492
+ if (tree) {
493
+ parts.push(`--- 현재 프로젝트 파일 목록 (이미 구현됨) ---\n${tree}`);
494
+ }
495
+ } catch {
496
+ // git이 없거나 실패하면 무시
497
+ }
498
+
499
+ // 5. 기존 tasks.md (있으면 참고)
500
+ const tasksPath = path.join(scDir, 'tasks.md');
501
+ if (fs.existsSync(tasksPath)) {
502
+ const existing = fs.readFileSync(tasksPath, 'utf-8');
503
+ if (existing.includes('[ ]') || existing.includes('[x]')) {
504
+ parts.push(`--- 기존 tasks.md ---\n${existing}`);
505
+ }
506
+ }
507
+
508
+ // 프롬프트 구성
509
+ const context = parts.join('\n\n---\n\n');
510
+ const prompt = `${context}
511
+
512
+ ---
513
+
514
+ 위 프로젝트 정보와 참고 자료를 바탕으로 .sleepcode/tasks.md 파일을 생성해주세요.
515
+
516
+ 규칙:
517
+ - 마크다운 체크리스트 형식으로 작성: \`- [ ] 태스크 내용\`
518
+ - 구체적이고 실행 가능한 단위로 태스크를 나눌 것
519
+ - 태스크 순서는 의존성을 고려하여 배치
520
+ - Figma 디자인이 있으면 UI 구현 태스크도 포함
521
+ - Notion 문서가 있으면 기획 내용을 반영
522
+ - docs/ 폴더의 참고 자료를 반영
523
+ - **이미 프로젝트에 구현되어 있는 기능은 태스크에 포함하지 않는다**
524
+ - 현재 프로젝트 파일 목록을 분석하여 아직 구현되지 않은 것만 태스크로 작성
525
+ - 첫 줄은 \`# 작업 목록\` 으로 시작
526
+ - 태스크 목록 앞에 간단한 안내 문구 포함
527
+
528
+ tasks.md 내용만 출력하세요. 다른 설명은 하지 마세요.`;
529
+
530
+ try {
531
+ const result = execSync(
532
+ 'claude -p --output-format text',
533
+ {
534
+ input: prompt,
535
+ cwd: targetDir,
536
+ stdio: ['pipe', 'pipe', 'pipe'],
537
+ timeout: 300000,
538
+ maxBuffer: 1024 * 1024,
539
+ }
540
+ ).toString().trim();
541
+
542
+ // tasks.md에 저장
543
+ fs.writeFileSync(tasksPath, result + '\n');
544
+ console.log(`${C.green}✓${C.reset} .sleepcode/tasks.md 생성 완료\n`);
545
+ console.log(`${C.dim}${result}${C.reset}\n`);
546
+ console.log(`필요하면 tasks.md를 직접 수정한 뒤 실행하세요:`);
547
+ console.log(` ${C.cyan}npx sleepcode run${C.reset} ${C.dim}# 1회 실행${C.reset}`);
548
+ console.log(` ${C.cyan}npx sleepcode run --loop${C.reset} ${C.dim}# 무한 루프${C.reset}`);
549
+ } catch (e) {
550
+ console.error(`${C.red}태스크 생성 실패: ${e.message}${C.reset}`);
551
+ process.exit(1);
377
552
  }
378
553
  }
379
554
 
380
555
  // ─── 메인 ───
381
556
  async function main() {
382
557
  const targetDir = process.cwd();
558
+
559
+ // 서브커맨드 처리
560
+ const firstArg = process.argv[2];
561
+ if (firstArg === 'run') {
562
+ const loop = process.argv.includes('--loop');
563
+ runWorker(loop);
564
+ return;
565
+ }
566
+ if (firstArg === 'generate') {
567
+ generateTasks();
568
+ return;
569
+ }
570
+
383
571
  const cliArgs = parseArgs();
384
572
 
385
573
  console.log(`
@@ -410,6 +598,9 @@ ${C.bold}${C.magenta} ╔══════════════════
410
598
  const projectName = cliArgs.name || path.basename(targetDir);
411
599
  const role = cliArgs.role || `${projectName} 서비스 개발`;
412
600
  const figmaKey = cliArgs.figmaKey || '';
601
+ const figmaFileNames = cliArgs.figmaFileNames || '';
602
+ const notionKey = cliArgs.notionKey || '';
603
+ const notionPages = cliArgs.notionPages || '';
413
604
  const sleepInterval = cliArgs.interval || '30';
414
605
 
415
606
  console.log(`${C.dim}타입: ${typeConfig.label}${C.reset}`);
@@ -424,6 +615,9 @@ ${C.bold}${C.magenta} ╔══════════════════
424
615
  testCmd: typeConfig.testCmd,
425
616
  lintCmd: typeConfig.lintCmd,
426
617
  figmaKey,
618
+ figmaFileNames,
619
+ notionKey,
620
+ notionPages,
427
621
  sleepInterval,
428
622
  });
429
623
 
@@ -476,7 +670,24 @@ ${C.bold}${C.magenta} ╔══════════════════
476
670
  console.log(`${C.dim} 린트: ${lintCmd || '(없음)'}${C.reset}`);
477
671
  }
478
672
 
479
- const figmaKey = await ask(rl, 'Figma API Key (없으면 Enter)', '');
673
+ // Figma 연동
674
+ let figmaKey = '';
675
+ let figmaFileNames = '';
676
+ const useFigma = await ask(rl, 'Figma 디자인을 참고하나요? (y/N)', 'N');
677
+ if (useFigma.toLowerCase() === 'y') {
678
+ figmaKey = await ask(rl, 'Figma API Key', '');
679
+ figmaFileNames = await ask(rl, '참고할 Figma 파일명 (예: 홈화면, 로그인)', '');
680
+ }
681
+
682
+ // Notion 연동
683
+ let notionKey = '';
684
+ let notionPages = '';
685
+ const useNotion = await ask(rl, 'Notion 문서를 참고하나요? (y/N)', 'N');
686
+ if (useNotion.toLowerCase() === 'y') {
687
+ notionKey = await ask(rl, 'Notion API Key', '');
688
+ notionPages = await ask(rl, '참고할 Notion 페이지명 (예: 기획서, API명세)', '');
689
+ }
690
+
480
691
  const sleepInterval = await ask(rl, '반복 간격 (초)', '30');
481
692
 
482
693
  rl.close();
@@ -489,6 +700,9 @@ ${C.bold}${C.magenta} ╔══════════════════
489
700
  testCmd,
490
701
  lintCmd,
491
702
  figmaKey,
703
+ figmaFileNames,
704
+ notionKey,
705
+ notionPages,
492
706
  sleepInterval,
493
707
  });
494
708
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sleepcode",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "AI codes while you sleep — Claude AI 야간 자동화 세팅 CLI",
5
5
  "bin": {
6
6
  "sleepcode": "./bin/index.js"
@@ -11,7 +11,8 @@ AI codes while you sleep — 밤새 개발 작업을 자동화하는 시스템
11
11
  rules.md # ✏️ AI 역할 + 작업 규칙 (수정하세요)
12
12
  tasks.md # ✏️ 오늘 진행할 작업 목록 (수정하세요)
13
13
  docs/ # ✏️ 개발 참고 자료 (피그마 스크린샷, 기획서 등)
14
- scripts/ # ⚙️ 시스템 스크립트 (수정하지 마세요)
14
+ scripts/ # ⚙️ 시스템 (수정하지 마세요)
15
+ base_rules.md # 공통 작업 규칙
15
16
  ai_worker.* # 1회 실행 스크립트
16
17
  run_forever.* # 무한 루프 감시자 스크립트
17
18
  log_filter.py # 로그 필터 (핵심 메시지만 추출)
@@ -41,26 +42,15 @@ claude --dangerously-skip-permissions
41
42
 
42
43
  ### 2. 실행
43
44
 
44
- **macOS / Linux:**
45
45
  ```bash
46
- # 권한 부여
47
- chmod +x .sleepcode/scripts/*.sh
48
-
49
46
  # 1회 실행
50
- ./.sleepcode/scripts/ai_worker.sh
47
+ npx sleepcode run
51
48
 
52
- # 무한 루프 (tmux)
53
- tmux new -s ai './.sleepcode/scripts/run_forever.sh'
49
+ # 무한 루프 (잠자기 전)
50
+ npx sleepcode run --loop
54
51
  ```
55
52
 
56
- **Windows (PowerShell):**
57
- ```powershell
58
- # 1회 실행
59
- powershell -File .\.sleepcode\scripts\ai_worker.ps1
60
-
61
- # 무한 루프
62
- powershell -File .\.sleepcode\scripts\run_forever.ps1
63
- ```
53
+ OS에 맞는 스크립트를 자동으로 선택합니다.
64
54
 
65
55
  ### 3. tmux 분리 (백그라운드 전환, macOS/Linux)
66
56
 
@@ -7,10 +7,11 @@ Set-Location (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent)
7
7
  $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
8
8
  Write-Host "[$timestamp] AI 단일 실행 시작"
9
9
 
10
+ $baseRules = Get-Content .sleepcode/scripts/base_rules.md -Raw -Encoding UTF8
10
11
  $rules = Get-Content .sleepcode/rules.md -Raw -Encoding UTF8
11
12
  $tasks = Get-Content .sleepcode/tasks.md -Raw -Encoding UTF8
12
13
 
13
- $prompt = "$rules`n`n---`n`n$tasks"
14
+ $prompt = "$baseRules`n`n---`n`n$rules`n`n---`n`n$tasks"
14
15
 
15
16
  # stream-json + verbose: 토큰 단위 실시간 출력
16
17
  $prompt | claude -p --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 |
@@ -7,10 +7,15 @@ cd "$(dirname "$0")/../.." || exit 1
7
7
 
8
8
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] AI 단일 실행 시작"
9
9
 
10
+ BASE_RULES=$(cat .sleepcode/scripts/base_rules.md)
10
11
  RULES=$(cat .sleepcode/rules.md)
11
12
  TASKS=$(cat .sleepcode/tasks.md)
12
13
 
13
- PROMPT="${RULES}
14
+ PROMPT="${BASE_RULES}
15
+
16
+ ---
17
+
18
+ ${RULES}
14
19
 
15
20
  ---
16
21
 
@@ -0,0 +1,39 @@
1
+ # 공통 작업 규칙
2
+
3
+ ## 기본 원칙
4
+
5
+ - 절대로 사용자에게 질문하지 않는다.
6
+ - 작업이 끝났다고 판단하지 않는다.
7
+ - 항상 다음 작업을 스스로 찾는다.
8
+ - 가능한 한 많은 기능을 구현하며 계속 진행한다.
9
+
10
+ ---
11
+
12
+ ## 참고 자료
13
+
14
+ - `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (피그마 스크린샷, 기획서, 참고 이미지 등)
15
+
16
+ {{FIGMA_SECTION}}
17
+ {{NOTION_SECTION}}
18
+
19
+ ---
20
+
21
+ ## 태스크 완료 처리
22
+
23
+ - `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
24
+ - 태스크를 **한 항목씩** 순서대로 진행한다.
25
+ - 한 항목을 완료하면 반드시 아래 순서를 따른다:
26
+ 1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
27
+ 2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
28
+ 3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
29
+ 4. 그 다음 항목으로 넘어간다.
30
+ - 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
31
+
32
+ ---
33
+
34
+ ## Git 작업 규칙
35
+
36
+ - tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
37
+ - 작업 중간에는 commit 하지 않는다.
38
+ - 기능이 정상 동작한다고 판단되면 commit 한다.
39
+ - commit message 는 변경 내용을 구체적으로 설명한다.
@@ -35,10 +35,11 @@ while ($true) {
35
35
  exit 0
36
36
  }
37
37
 
38
- # rules.md + tasks.md 를 합쳐서 프롬프트 구성
38
+ # base_rules.md + rules.md + tasks.md 를 합쳐서 프롬프트 구성
39
+ $baseRules = Get-Content .sleepcode/scripts/base_rules.md -Raw -Encoding UTF8
39
40
  $rules = Get-Content .sleepcode/rules.md -Raw -Encoding UTF8
40
41
  $tasks = Get-Content .sleepcode/tasks.md -Raw -Encoding UTF8
41
- $prompt = "$rules`n`n---`n`n$tasks"
42
+ $prompt = "$baseRules`n`n---`n`n$rules`n`n---`n`n$tasks"
42
43
 
43
44
  Log "claude 실행 중..."
44
45
  # stream-json -> log_filter.py 로 핵심 메시지만 추출
@@ -31,11 +31,16 @@ while true; do
31
31
  exit 0
32
32
  fi
33
33
 
34
- # rules.md + tasks.md 를 합쳐서 프롬프트 구성
34
+ # base_rules.md + rules.md + tasks.md 를 합쳐서 프롬프트 구성
35
+ BASE_RULES=$(cat .sleepcode/scripts/base_rules.md)
35
36
  RULES=$(cat .sleepcode/rules.md)
36
37
  TASKS=$(cat .sleepcode/tasks.md)
37
38
 
38
- PROMPT="${RULES}
39
+ PROMPT="${BASE_RULES}
40
+
41
+ ---
42
+
43
+ ${RULES}
39
44
 
40
45
  ---
41
46
 
@@ -8,25 +8,6 @@
8
8
 
9
9
  ---
10
10
 
11
- ## 기본 원칙
12
-
13
- - 절대로 사용자에게 질문하지 않는다.
14
- - 작업이 끝났다고 판단하지 않는다.
15
- - 항상 다음 작업을 스스로 찾는다.
16
- - 가능한 한 많은 기능을 구현하며 계속 진행한다.
17
-
18
- ---
19
-
20
- ## 참고 자료
21
-
22
- - `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고
23
-
24
- ## Figma
25
-
26
- - **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
27
-
28
- ---
29
-
30
11
  ## 작업 방식
31
12
 
32
13
  - 작은 단위로 작업하고 자주 확인한다.
@@ -45,25 +26,3 @@
45
26
 
46
27
  - 기존 프로젝트 구조와 패턴을 존중한다.
47
28
  - 중복 코드를 만들지 않는다.
48
-
49
- ---
50
-
51
- ## 태스크 완료 처리
52
-
53
- - `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
54
- - 태스크를 **한 항목씩** 순서대로 진행한다.
55
- - 한 항목을 완료하면 반드시 아래 순서를 따른다:
56
- 1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
57
- 2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
58
- 3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
59
- 4. 그 다음 항목으로 넘어간다.
60
- - 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
61
-
62
- ---
63
-
64
- ## Git 작업 규칙
65
-
66
- - tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
67
- - 작업 중간에는 commit 하지 않는다.
68
- - 기능이 정상 동작한다고 판단되면 commit 한다.
69
- - commit message 는 변경 내용을 구체적으로 설명한다.
@@ -8,25 +8,6 @@
8
8
 
9
9
  ---
10
10
 
11
- ## 기본 원칙
12
-
13
- - 절대로 사용자에게 질문하지 않는다.
14
- - 작업이 끝났다고 판단하지 않는다.
15
- - 항상 다음 작업을 스스로 찾는다.
16
- - 가능한 한 많은 기능을 구현하며 계속 진행한다.
17
-
18
- ---
19
-
20
- ## 참고 자료
21
-
22
- - `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (피그마 스크린샷, 기획서, 참고 이미지 등)
23
-
24
- ## Figma
25
-
26
- - **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
27
-
28
- ---
29
-
30
11
  ## 작업 방식
31
12
 
32
13
  - 작은 단위로 작업하고 자주 확인한다.
@@ -53,25 +34,3 @@
53
34
  - 중복 코드를 만들지 않는다.
54
35
  - App Router 구조를 따른다.
55
36
  - Server Component / Client Component 를 적절히 구분한다.
56
-
57
- ---
58
-
59
- ## 태스크 완료 처리
60
-
61
- - `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
62
- - 태스크를 **한 항목씩** 순서대로 진행한다.
63
- - 한 항목을 완료하면 반드시 아래 순서를 따른다:
64
- 1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
65
- 2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
66
- 3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
67
- 4. 그 다음 항목으로 넘어간다.
68
- - 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
69
-
70
- ---
71
-
72
- ## Git 작업 규칙
73
-
74
- - tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
75
- - 작업 중간에는 commit 하지 않는다.
76
- - 기능이 정상 동작한다고 판단되면 commit 한다.
77
- - commit message 는 변경 내용을 구체적으로 설명한다.
@@ -8,25 +8,6 @@
8
8
 
9
9
  ---
10
10
 
11
- ## 기본 원칙
12
-
13
- - 절대로 사용자에게 질문하지 않는다.
14
- - 작업이 끝났다고 판단하지 않는다.
15
- - 항상 다음 작업을 스스로 찾는다.
16
- - 가능한 한 많은 기능을 구현하며 계속 진행한다.
17
-
18
- ---
19
-
20
- ## 참고 자료
21
-
22
- - `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (피그마 스크린샷, 기획서, 참고 이미지 등)
23
-
24
- ## Figma
25
-
26
- - **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
27
-
28
- ---
29
-
30
11
  ## 작업 방식
31
12
 
32
13
  - 작은 단위로 작업하고 자주 확인한다.
@@ -52,25 +33,3 @@
52
33
  - 중복 코드를 만들지 않는다.
53
34
  - 기존 컴포넌트를 최대한 재사용한다.
54
35
  - 새 컴포넌트는 기존 디렉토리 구조에 맞게 배치한다.
55
-
56
- ---
57
-
58
- ## 태스크 완료 처리
59
-
60
- - `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
61
- - 태스크를 **한 항목씩** 순서대로 진행한다.
62
- - 한 항목을 완료하면 반드시 아래 순서를 따른다:
63
- 1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
64
- 2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
65
- 3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
66
- 4. 그 다음 항목으로 넘어간다.
67
- - 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
68
-
69
- ---
70
-
71
- ## Git 작업 규칙
72
-
73
- - tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
74
- - 작업 중간에는 commit 하지 않는다.
75
- - 기능이 정상 동작한다고 판단되면 commit 한다.
76
- - commit message 는 변경 내용을 구체적으로 설명한다.
@@ -8,25 +8,6 @@
8
8
 
9
9
  ---
10
10
 
11
- ## 기본 원칙
12
-
13
- - 절대로 사용자에게 질문하지 않는다.
14
- - 작업이 끝났다고 판단하지 않는다.
15
- - 항상 다음 작업을 스스로 찾는다.
16
- - 가능한 한 많은 기능을 구현하며 계속 진행한다.
17
-
18
- ---
19
-
20
- ## 참고 자료
21
-
22
- - `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (ERD, 화면설계, API 명세 등)
23
-
24
- ## Figma
25
-
26
- - **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
27
-
28
- ---
29
-
30
11
  ## 작업 방식
31
12
 
32
13
  - 작은 단위로 작업하고 자주 테스트한다.
@@ -54,25 +35,3 @@
54
35
  - REST API는 일관된 응답 형식을 유지한다.
55
36
  - Entity ↔ DTO 변환을 명확히 분리한다.
56
37
  - Service 계층에 비즈니스 로직을 집중한다.
57
-
58
- ---
59
-
60
- ## 태스크 완료 처리
61
-
62
- - `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
63
- - 태스크를 **한 항목씩** 순서대로 진행한다.
64
- - 한 항목을 완료하면 반드시 아래 순서를 따른다:
65
- 1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
66
- 2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
67
- 3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
68
- 4. 그 다음 항목으로 넘어간다.
69
- - 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
70
-
71
- ---
72
-
73
- ## Git 작업 규칙
74
-
75
- - tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
76
- - 작업 중간에는 commit 하지 않는다.
77
- - 기능이 정상 동작한다고 판단되면 commit 한다.
78
- - commit message 는 변경 내용을 구체적으로 설명한다.