sleepcode 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
- {
2
- "name": "sleepcode",
3
- "version": "1.0.0",
4
- "description": "AI codes while you sleep — Claude AI 야간 자동화 세팅 CLI",
5
- "bin": {
6
- "sleepcode": "bin/index.js"
7
- },
8
- "keywords": [
9
- "claude",
10
- "ai",
11
- "automation",
12
- "coding",
13
- "nightshift",
14
- "sleepcode"
15
- ],
16
- "license": "MIT"
17
- }
1
+ {
2
+ "name": "sleepcode",
3
+ "version": "1.2.0",
4
+ "description": "AI codes while you sleep — Claude AI 야간 자동화 세팅 CLI",
5
+ "bin": {
6
+ "sleepcode": "./bin/index.js"
7
+ },
8
+ "keywords": [
9
+ "claude",
10
+ "ai",
11
+ "automation",
12
+ "coding",
13
+ "nightshift",
14
+ "sleepcode"
15
+ ],
16
+ "license": "MIT"
17
+ }
@@ -1,97 +1,100 @@
1
- # SleepCode
2
-
3
- AI codes while you sleep — 밤새 개발 작업을 자동화하는 시스템입니다.
4
-
5
- ---
6
-
7
- ## 폴더 구조
8
-
9
- ```
10
- .ai/
11
- rules.md # AI 역할 + 작업 규칙
12
- tasks.md # 오늘 진행할 작업 목록
13
- docs/ # 개발 참고 자료 (피그마 스크린샷, 기획서 등)
14
- ai_worker.sh # 1회 실행 스크립트
15
- run_forever.sh # 무한 루프 감시자 스크립트
16
- log_filter.py # 로그 필터 (핵심 메시지만 추출)
17
- logs/ # 실행 로그 (자동 생성)
18
- ```
19
-
20
- ---
21
-
22
- ## 작동 원리
23
-
24
- 1. `claude -p` 로 비대화형 모드 실행
25
- 2. `rules.md` + `tasks.md` 합쳐서 프롬프트로 전달
26
- 3. AI가 코드 작성 빌드/테스트 오류 수정 → git commit
27
- 4. 대기 다시 반복
28
-
29
- ---
30
-
31
- ## 실행 방법
32
-
33
- ### 1. 권한 부여
34
-
35
- ```bash
36
- chmod +x .ai/*.sh
37
- ```
38
-
39
- ### 2. (최초 1회) --dangerously-skip-permissions 수락
40
-
41
- ```bash
42
- claude --dangerously-skip-permissions
43
- ```
44
-
45
- 동의 프롬프트가 뜨면 수락 후 `Ctrl + C`로 나옵니다.
46
-
47
- ### 3. tmux 세션 생성 + 실행
48
-
49
- ```bash
50
- tmux new -s ai './.ai/run_forever.sh'
51
- ```
52
-
53
- ### 4. tmux 분리 (백그라운드 전환)
54
-
55
- ```
56
- Ctrl + B → D
57
- ```
58
-
59
- ---
60
-
61
- ## 수동 1회 실행
62
-
63
- ```bash
64
- ./.ai/ai_worker.sh
65
- ```
66
-
67
- ---
68
-
69
- ## 관리 명령어
70
-
71
- | 동작 | 명령어 |
72
- |------|--------|
73
- | 세션 재접속 | `tmux attach -t ai` |
74
- | 실시간 로그 | `tail -f .ai/logs/worker_*.log` |
75
- | 종료 | `tmux attach -t ai` → `Ctrl + C` |
76
- | 세션 삭제 | `tmux kill-session -t ai` |
77
-
78
- ---
79
-
80
- ## 아침 확인
81
-
82
- ```bash
83
- # 밤 동안의 커밋 확인
84
- git log --oneline --since="12 hours ago"
85
-
86
- # 로그 확인
87
- tail -100 .ai/logs/worker_*.log
88
- ```
89
-
90
- ---
91
-
92
- ## 커스터마이징
93
-
94
- - **역할/규칙 변경**: `.ai/rules.md` 수정
95
- - **태스크 변경**: `.ai/tasks.md` 수정
96
- - **참고 자료 추가**: `.ai/docs/` 에 파일 추가
97
- - **반복 간격 변경**: `run_forever.sh` 의 `sleep` 값 수정
1
+ # SleepCode
2
+
3
+ AI codes while you sleep — 밤새 개발 작업을 자동화하는 시스템입니다.
4
+
5
+ ---
6
+
7
+ ## 폴더 구조
8
+
9
+ ```
10
+ .sleepcode/
11
+ rules.md # ✏️ AI 역할 + 작업 규칙 (수정하세요)
12
+ tasks.md # ✏️ 오늘 진행할 작업 목록 (수정하세요)
13
+ docs/ # ✏️ 개발 참고 자료 (피그마 스크린샷, 기획서 등)
14
+ scripts/ # ⚙️ 시스템 스크립트 (수정하지 마세요)
15
+ ai_worker.* # 1회 실행 스크립트
16
+ run_forever.* # 무한 루프 감시자 스크립트
17
+ log_filter.py # 로그 필터 (핵심 메시지만 추출)
18
+ logs/ # 실행 로그 (자동 생성)
19
+ ```
20
+
21
+ ---
22
+
23
+ ## 작동 원리
24
+
25
+ 1. `claude -p` 비대화형 모드 실행
26
+ 2. `rules.md` + `tasks.md` 합쳐서 프롬프트로 전달
27
+ 3. AI가 코드 작성 → 빌드/테스트 → 오류 수정 → git commit
28
+ 4. 대기 후 다시 반복
29
+
30
+ ---
31
+
32
+ ## 실행 방법
33
+
34
+ ### 1. (최초 1회) --dangerously-skip-permissions 수락
35
+
36
+ ```bash
37
+ claude --dangerously-skip-permissions
38
+ ```
39
+
40
+ 동의 프롬프트가 뜨면 수락 후 `Ctrl + C`로 나옵니다.
41
+
42
+ ### 2. 실행
43
+
44
+ **macOS / Linux:**
45
+ ```bash
46
+ # 권한 부여
47
+ chmod +x .sleepcode/scripts/*.sh
48
+
49
+ # 1회 실행
50
+ ./.sleepcode/scripts/ai_worker.sh
51
+
52
+ # 무한 루프 (tmux)
53
+ tmux new -s ai './.sleepcode/scripts/run_forever.sh'
54
+ ```
55
+
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
+ ```
64
+
65
+ ### 3. tmux 분리 (백그라운드 전환, macOS/Linux)
66
+
67
+ ```
68
+ Ctrl + B → D
69
+ ```
70
+
71
+ ---
72
+
73
+ ## 관리 명령어
74
+
75
+ | 동작 | 명령어 |
76
+ |------|--------|
77
+ | 세션 재접속 | `tmux attach -t ai` |
78
+ | 실시간 로그 | `tail -f .sleepcode/logs/worker_*.log` |
79
+ | 종료 | `tmux attach -t ai` → `Ctrl + C` |
80
+ | 세션 삭제 | `tmux kill-session -t ai` |
81
+
82
+ ---
83
+
84
+ ## 아침 확인
85
+
86
+ ```bash
87
+ # 동안의 커밋 확인
88
+ git log --oneline --since="12 hours ago"
89
+
90
+ # 로그 확인
91
+ tail -100 .sleepcode/logs/worker_*.log
92
+ ```
93
+
94
+ ---
95
+
96
+ ## 커스터마이징
97
+
98
+ - **역할/규칙 변경**: `.sleepcode/rules.md` 수정
99
+ - **태스크 변경**: `.sleepcode/tasks.md` 수정
100
+ - **참고 자료 추가**: `.sleepcode/docs/` 에 파일 추가
@@ -0,0 +1,20 @@
1
+ # AI Worker - 1회 실행 스크립트 (Windows PowerShell)
2
+ # run_forever.ps1 (무한 루프) 대신 수동으로 1회만 돌릴 때 사용
3
+
4
+ $ErrorActionPreference = "Stop"
5
+ Set-Location (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent)
6
+
7
+ $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
8
+ Write-Host "[$timestamp] AI 단일 실행 시작"
9
+
10
+ $rules = Get-Content .sleepcode/rules.md -Raw -Encoding UTF8
11
+ $tasks = Get-Content .sleepcode/tasks.md -Raw -Encoding UTF8
12
+
13
+ $prompt = "$rules`n`n---`n`n$tasks"
14
+
15
+ # stream-json + verbose: 토큰 단위 실시간 출력
16
+ $prompt | claude -p --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 |
17
+ python .sleepcode/scripts/log_filter.py
18
+
19
+ $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
20
+ Write-Host "[$timestamp] AI 단일 실행 종료"
@@ -1,23 +1,23 @@
1
- #!/bin/bash
2
-
3
- # AI Worker - 1회 실행 스크립트
4
- # run_forever.sh (무한 루프) 대신 수동으로 1회만 돌릴 때 사용
5
-
6
- cd "$(dirname "$0")/.." || exit 1
7
-
8
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] AI 단일 실행 시작"
9
-
10
- RULES=$(cat .ai/rules.md)
11
- TASKS=$(cat .ai/tasks.md)
12
-
13
- PROMPT="${RULES}
14
-
15
- ---
16
-
17
- ${TASKS}"
18
-
19
- # stream-json + verbose: 토큰 단위 실시간 출력
20
- claude -p "$PROMPT" --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 \
21
- | python3 .ai/log_filter.py
22
-
23
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] AI 단일 실행 종료"
1
+ #!/bin/bash
2
+
3
+ # AI Worker - 1회 실행 스크립트
4
+ # run_forever.sh (무한 루프) 대신 수동으로 1회만 돌릴 때 사용
5
+
6
+ cd "$(dirname "$0")/../.." || exit 1
7
+
8
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] AI 단일 실행 시작"
9
+
10
+ RULES=$(cat .sleepcode/rules.md)
11
+ TASKS=$(cat .sleepcode/tasks.md)
12
+
13
+ PROMPT="${RULES}
14
+
15
+ ---
16
+
17
+ ${TASKS}"
18
+
19
+ # stream-json + verbose: 토큰 단위 실시간 출력
20
+ claude -p "$PROMPT" --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 \
21
+ | python3 .sleepcode/scripts/log_filter.py
22
+
23
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] AI 단일 실행 종료"
@@ -1,63 +1,63 @@
1
- #!/usr/bin/env python3
2
- """
3
- stream-json 출력에서 핵심 메시지만 추출하는 필터.
4
- Usage: claude ... --output-format stream-json | python3 .ai/log_filter.py
5
- """
6
- import sys
7
- import json
8
-
9
- for line in sys.stdin:
10
- line = line.strip()
11
- if not line:
12
- continue
13
- try:
14
- obj = json.loads(line)
15
- except json.JSONDecodeError:
16
- continue
17
-
18
- msg_type = obj.get("type")
19
-
20
- # assistant 메시지만 처리
21
- if msg_type == "assistant":
22
- message = obj.get("message", {})
23
- contents = message.get("content", [])
24
- for c in contents:
25
- ctype = c.get("type")
26
- if ctype == "text":
27
- text = c.get("text", "").strip()
28
- if text:
29
- print(f"[TEXT] {text}", flush=True)
30
- elif ctype == "tool_use":
31
- name = c.get("name", "?")
32
- inp = c.get("input", {})
33
- # 도구별 핵심 파라미터만 요약
34
- if name in ("Read", "Write", "Edit"):
35
- param = inp.get("file_path", "")
36
- print(f"[TOOL] {name}: {param}", flush=True)
37
- elif name == "Bash":
38
- cmd = inp.get("command", "")
39
- if len(cmd) > 120:
40
- cmd = cmd[:120] + "..."
41
- print(f"[TOOL] Bash: {cmd}", flush=True)
42
- elif name == "Glob":
43
- print(f"[TOOL] Glob: {inp.get('pattern', '')}", flush=True)
44
- elif name == "Grep":
45
- print(f"[TOOL] Grep: {inp.get('pattern', '')}", flush=True)
46
- elif name == "TodoWrite":
47
- todos = inp.get("todos", [])
48
- active = [t for t in todos if t.get("status") == "in_progress"]
49
- if active:
50
- print(f"[TODO] {active[0].get('activeForm', '')}", flush=True)
51
- else:
52
- print(f"[TOOL] {name}", flush=True)
53
-
54
- # 최종 결과
55
- elif msg_type == "result":
56
- message = obj.get("message", "")
57
- if isinstance(message, str) and message:
58
- short = message[:200] + "..." if len(message) > 200 else message
59
- print(f"[DONE] {short}", flush=True)
60
- cost = obj.get("cost_usd")
61
- duration = obj.get("duration_ms")
62
- if cost is not None:
63
- print(f"[COST] ${cost:.4f} | {(duration or 0) / 1000:.0f}s", flush=True)
1
+ #!/usr/bin/env python3
2
+ """
3
+ stream-json 출력에서 핵심 메시지만 추출하는 필터.
4
+ Usage: claude ... --output-format stream-json | python3 .sleepcode/log_filter.py
5
+ """
6
+ import sys
7
+ import json
8
+
9
+ for line in sys.stdin:
10
+ line = line.strip()
11
+ if not line:
12
+ continue
13
+ try:
14
+ obj = json.loads(line)
15
+ except json.JSONDecodeError:
16
+ continue
17
+
18
+ msg_type = obj.get("type")
19
+
20
+ # assistant 메시지만 처리
21
+ if msg_type == "assistant":
22
+ message = obj.get("message", {})
23
+ contents = message.get("content", [])
24
+ for c in contents:
25
+ ctype = c.get("type")
26
+ if ctype == "text":
27
+ text = c.get("text", "").strip()
28
+ if text:
29
+ print(f"[TEXT] {text}", flush=True)
30
+ elif ctype == "tool_use":
31
+ name = c.get("name", "?")
32
+ inp = c.get("input", {})
33
+ # 도구별 핵심 파라미터만 요약
34
+ if name in ("Read", "Write", "Edit"):
35
+ param = inp.get("file_path", "")
36
+ print(f"[TOOL] {name}: {param}", flush=True)
37
+ elif name == "Bash":
38
+ cmd = inp.get("command", "")
39
+ if len(cmd) > 120:
40
+ cmd = cmd[:120] + "..."
41
+ print(f"[TOOL] Bash: {cmd}", flush=True)
42
+ elif name == "Glob":
43
+ print(f"[TOOL] Glob: {inp.get('pattern', '')}", flush=True)
44
+ elif name == "Grep":
45
+ print(f"[TOOL] Grep: {inp.get('pattern', '')}", flush=True)
46
+ elif name == "TodoWrite":
47
+ todos = inp.get("todos", [])
48
+ active = [t for t in todos if t.get("status") == "in_progress"]
49
+ if active:
50
+ print(f"[TODO] {active[0].get('activeForm', '')}", flush=True)
51
+ else:
52
+ print(f"[TOOL] {name}", flush=True)
53
+
54
+ # 최종 결과
55
+ elif msg_type == "result":
56
+ message = obj.get("message", "")
57
+ if isinstance(message, str) and message:
58
+ short = message[:200] + "..." if len(message) > 200 else message
59
+ print(f"[DONE] {short}", flush=True)
60
+ cost = obj.get("cost_usd")
61
+ duration = obj.get("duration_ms")
62
+ if cost is not None:
63
+ print(f"[COST] ${cost:.4f} | {(duration or 0) / 1000:.0f}s", flush=True)
@@ -0,0 +1,59 @@
1
+ # AI Night Worker - 감시자 스크립트 (Windows PowerShell)
2
+ # 사용법: powershell -File .\.sleepcode\scripts\run_forever.ps1
3
+
4
+ $ErrorActionPreference = "Continue"
5
+ Set-Location (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent)
6
+
7
+ $logDir = ".sleepcode/logs"
8
+ if (!(Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }
9
+ $logFile = "$logDir/worker_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
10
+
11
+ function Log($msg) {
12
+ $line = "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $msg"
13
+ Write-Host $line
14
+ Add-Content -Path $logFile -Value $line -Encoding UTF8
15
+ }
16
+
17
+ Log "=== AI Night Worker 시작 ==="
18
+ Log "로그 파일: $logFile"
19
+
20
+ $iteration = 0
21
+
22
+ while ($true) {
23
+ $iteration++
24
+ Log "--- 반복 #$iteration 시작 ---"
25
+
26
+ # 미완료 태스크 확인
27
+ $remaining = 0
28
+ if (Test-Path .sleepcode/tasks.md) {
29
+ $remaining = (Select-String -Pattern '\[ \]' -Path .sleepcode/tasks.md -SimpleMatch).Count
30
+ }
31
+ Log "남은 태스크: ${remaining}개"
32
+
33
+ if ($remaining -eq 0) {
34
+ Log "=== 모든 태스크 완료. 종료합니다. ==="
35
+ exit 0
36
+ }
37
+
38
+ # rules.md + tasks.md 를 합쳐서 프롬프트 구성
39
+ $rules = Get-Content .sleepcode/rules.md -Raw -Encoding UTF8
40
+ $tasks = Get-Content .sleepcode/tasks.md -Raw -Encoding UTF8
41
+ $prompt = "$rules`n`n---`n`n$tasks"
42
+
43
+ Log "claude 실행 중..."
44
+ # stream-json -> log_filter.py 로 핵심 메시지만 추출
45
+ $prompt | claude -p --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 |
46
+ python .sleepcode/scripts/log_filter.py |
47
+ Tee-Object -Append $logFile
48
+ $exitCode = $LASTEXITCODE
49
+ Log "claude 종료 (exit code: $exitCode)"
50
+
51
+ # 미커밋 변경사항 체크
52
+ $porcelain = git status --porcelain
53
+ if ($porcelain) {
54
+ Log "경고: 커밋되지 않은 변경사항 감지"
55
+ }
56
+
57
+ Log "--- 반복 #$iteration 종료, {{SLEEP_INTERVAL}}초 대기 ---"
58
+ Start-Sleep -Seconds {{SLEEP_INTERVAL}}
59
+ }
@@ -1,59 +1,59 @@
1
- #!/bin/bash
2
-
3
- # AI Night Worker - 감시자 스크립트
4
- # 사용법: tmux new -s ai './.ai/run_forever.sh'
5
-
6
- cd "$(dirname "$0")/.." || exit 1
7
-
8
- LOG_DIR=".ai/logs"
9
- mkdir -p "$LOG_DIR"
10
- LOG_FILE="$LOG_DIR/worker_$(date +%Y%m%d_%H%M%S).log"
11
-
12
- log() {
13
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
14
- }
15
-
16
- log "=== AI Night Worker 시작 ==="
17
- log "로그 파일: $LOG_FILE"
18
-
19
- ITERATION=0
20
-
21
- while true; do
22
- ITERATION=$((ITERATION + 1))
23
- log "--- 반복 #${ITERATION} 시작 ---"
24
-
25
- # 미완료 태스크가 있는지 확인
26
- REMAINING=$(grep -c '\[ \]' .ai/tasks.md 2>/dev/null || echo "0")
27
- log "남은 태스크: ${REMAINING}개"
28
-
29
- if [ "$REMAINING" -eq 0 ]; then
30
- log "=== 모든 태스크 완료. 종료합니다. ==="
31
- exit 0
32
- fi
33
-
34
- # rules.md + tasks.md 를 합쳐서 프롬프트 구성
35
- RULES=$(cat .ai/rules.md)
36
- TASKS=$(cat .ai/tasks.md)
37
-
38
- PROMPT="${RULES}
39
-
40
- ---
41
-
42
- ${TASKS}"
43
-
44
- log "claude 실행 중..."
45
- # stream-json → log_filter.py 로 핵심 메시지만 추출
46
- claude -p "$PROMPT" --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 \
47
- | python3 .ai/log_filter.py \
48
- | tee -a "$LOG_FILE"
49
- EXIT_CODE=${PIPESTATUS[0]}
50
- log "claude 종료 (exit code: $EXIT_CODE)"
51
-
52
- # 미커밋 변경사항 체크
53
- if [[ -n $(git status --porcelain) ]]; then
54
- log "경고: 커밋되지 않은 변경사항 감지"
55
- fi
56
-
57
- log "--- 반복 #${ITERATION} 종료, {{SLEEP_INTERVAL}}초 대기 ---"
58
- sleep {{SLEEP_INTERVAL}}
59
- done
1
+ #!/bin/bash
2
+
3
+ # AI Night Worker - 감시자 스크립트
4
+ # 사용법: tmux new -s ai './.sleepcode/scripts/run_forever.sh'
5
+
6
+ cd "$(dirname "$0")/../.." || exit 1
7
+
8
+ LOG_DIR=".sleepcode/logs"
9
+ mkdir -p "$LOG_DIR"
10
+ LOG_FILE="$LOG_DIR/worker_$(date +%Y%m%d_%H%M%S).log"
11
+
12
+ log() {
13
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
14
+ }
15
+
16
+ log "=== AI Night Worker 시작 ==="
17
+ log "로그 파일: $LOG_FILE"
18
+
19
+ ITERATION=0
20
+
21
+ while true; do
22
+ ITERATION=$((ITERATION + 1))
23
+ log "--- 반복 #${ITERATION} 시작 ---"
24
+
25
+ # 미완료 태스크가 있는지 확인
26
+ REMAINING=$(grep -c '\[ \]' .sleepcode/tasks.md 2>/dev/null || echo "0")
27
+ log "남은 태스크: ${REMAINING}개"
28
+
29
+ if [ "$REMAINING" -eq 0 ]; then
30
+ log "=== 모든 태스크 완료. 종료합니다. ==="
31
+ exit 0
32
+ fi
33
+
34
+ # rules.md + tasks.md 를 합쳐서 프롬프트 구성
35
+ RULES=$(cat .sleepcode/rules.md)
36
+ TASKS=$(cat .sleepcode/tasks.md)
37
+
38
+ PROMPT="${RULES}
39
+
40
+ ---
41
+
42
+ ${TASKS}"
43
+
44
+ log "claude 실행 중..."
45
+ # stream-json → log_filter.py 로 핵심 메시지만 추출
46
+ claude -p "$PROMPT" --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 \
47
+ | python3 .sleepcode/scripts/log_filter.py \
48
+ | tee -a "$LOG_FILE"
49
+ EXIT_CODE=${PIPESTATUS[0]}
50
+ log "claude 종료 (exit code: $EXIT_CODE)"
51
+
52
+ # 미커밋 변경사항 체크
53
+ if [[ -n $(git status --porcelain) ]]; then
54
+ log "경고: 커밋되지 않은 변경사항 감지"
55
+ fi
56
+
57
+ log "--- 반복 #${ITERATION} 종료, {{SLEEP_INTERVAL}}초 대기 ---"
58
+ sleep {{SLEEP_INTERVAL}}
59
+ done