jun-claude-code 0.0.11 → 0.0.13

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 (49) hide show
  1. package/README.md +122 -83
  2. package/dist/cli.js +40 -0
  3. package/dist/copy.js +92 -11
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +3 -1
  6. package/dist/init-context.d.ts +4 -0
  7. package/dist/init-context.js +143 -0
  8. package/dist/init-project.js +4 -4
  9. package/dist/validate.d.ts +4 -0
  10. package/dist/validate.js +105 -0
  11. package/package.json +2 -2
  12. package/{.claude → templates/global}/CLAUDE.md +50 -21
  13. package/{.claude → templates/global}/agents/architect.md +23 -11
  14. package/{.claude → templates/global}/agents/code-reviewer.md +17 -7
  15. package/{.claude → templates/global}/agents/code-writer.md +27 -15
  16. package/{.claude → templates/global}/agents/context-collector.md +11 -3
  17. package/{.claude → templates/global}/agents/context-manager.md +21 -9
  18. package/{.claude → templates/global}/agents/designer.md +32 -20
  19. package/{.claude → templates/global}/agents/director.md +43 -31
  20. package/{.claude → templates/global}/agents/explore.md +13 -5
  21. package/{.claude → templates/global}/agents/git-manager.md +39 -22
  22. package/{.claude → templates/global}/agents/impact-analyzer.md +17 -7
  23. package/{.claude → templates/global}/agents/qa-tester.md +22 -8
  24. package/{.claude → templates/global}/agents/simple-code-writer.md +13 -5
  25. package/{.claude → templates/global}/agents/task-planner.md +18 -10
  26. package/{.claude → templates/global}/hooks/skill-forced.sh +56 -56
  27. package/{.claude → templates/global}/hooks/workflow-enforced.sh +49 -31
  28. package/{.claude → templates/global}/skills/Backend/SKILL.md +38 -9
  29. package/{.claude → templates/global}/skills/Coding/SKILL.md +69 -29
  30. package/{.claude → templates/global}/skills/Director/SKILL.md +9 -5
  31. package/{.claude → templates/global}/skills/Documentation/SKILL.md +68 -1
  32. package/{.claude → templates/global}/skills/Git/SKILL.md +8 -4
  33. package/{.claude → templates/global}/skills/Git/git.md +60 -28
  34. package/{.claude → templates/global}/skills/Git/pr-apply.md +18 -6
  35. package/{.claude → templates/global}/skills/Git/pr-review.md +4 -0
  36. package/templates/global/skills/PromptStructuring/SKILL.md +67 -0
  37. package/templates/global/skills/PromptStructuring/positive-phrasing.md +206 -0
  38. package/templates/global/skills/PromptStructuring/xml-tags.md +330 -0
  39. package/{.claude → templates/global}/skills/React/SKILL.md +28 -8
  40. package/{.claude → templates/global}/skills/React/react-hook-form.md +20 -12
  41. package/{.claude → templates/global}/skills/React/tailwind-styled.md +29 -7
  42. package/{.claude → templates/global}/skills/React/tanstack-router.md +21 -9
  43. package/templates/project/agents/context-generator.md +66 -0
  44. package/{.claude → templates/project}/agents/project-task-manager.md +19 -7
  45. package/templates/project/skills/ContextGeneration/SKILL.md +160 -0
  46. package/templates/project/workflows/context-gen.yml +75 -0
  47. /package/{.claude → templates/global}/settings.json +0 -0
  48. /package/{.claude → templates/project}/hooks/task-loader.sh +0 -0
  49. /package/{.claude → templates/project}/project.env.example +0 -0
package/README.md CHANGED
@@ -1,140 +1,179 @@
1
1
  # jun-claude-code
2
2
 
3
- Claude Code 설정 템플릿 CLI입니다. 미리 정의된 `.claude` 설정을 `~/.claude`로 복사하여 프로젝트에서 빠르게 Claude Code 환경을 구축할 수 있습니다.
3
+ Claude Code 설정 템플릿 CLI. 미리 정의된 Agents, Skills, Hooks, Workflow를 프로젝트에 설치하여 Claude Code 환경을 빠르게 구축합니다.
4
4
 
5
- ## 설치
6
-
7
- ```bash
8
- # npx로 바로 실행
9
- npx jun-claude-code
10
-
11
- # 또는 전역 설치
12
- npm install -g jun-claude-code
13
- ```
14
-
15
- ## 사용법
16
-
17
- ```bash
18
- # 기본 실행 (기존 파일이 있으면 덮어쓰기 확인)
19
- jun-claude-code
20
-
21
- # 미리보기 (실제 복사 없이 복사될 파일 목록 확인)
22
- jun-claude-code --dry-run
5
+ ## 포함 내용
23
6
 
24
- # 강제 덮어쓰기 (확인 없이 모든 파일 복사)
25
- jun-claude-code --force
26
- ```
27
-
28
- ## 포함된 설정
7
+ ### Agents (`templates/global/agents/`)
29
8
 
30
- ### Agents (`.claude/agents/`)
9
+ 작업별 전문 Subagent 13종. Main Agent의 Context Window를 절약하면서 각 작업을 위임합니다.
31
10
 
32
- | Agent | 설명 |
11
+ | Agent | 역할 |
33
12
  |-------|------|
34
- | `explore` | 빠른 코드베이스 탐색 |
13
+ | `explore` | 코드베이스 탐색 |
35
14
  | `task-planner` | 작업 계획 수립 |
36
- | `code-writer` | 코드 작성 |
15
+ | `code-writer` | 코드 작성 (Opus) |
16
+ | `simple-code-writer` | 단순 수정 (Haiku) |
37
17
  | `code-reviewer` | 셀프 코드 리뷰 |
38
- | `git-manager` | Git 작업 (커밋, PR) |
18
+ | `git-manager` | Git 커밋/PR |
39
19
  | `impact-analyzer` | 사이드이펙트 분석 |
40
20
  | `qa-tester` | 테스트/빌드 검증 |
41
21
  | `architect` | 아키텍처 설계 |
42
22
  | `designer` | UI/UX 스타일링 |
23
+ | `director` | 작업 총괄 디렉터 |
43
24
  | `context-collector` | Context 수집 |
44
25
  | `context-manager` | Context 문서 관리 |
45
26
 
46
- ### Skills (`.claude/skills/`)
27
+ ### Skills (`templates/global/skills/`)
47
28
 
48
29
  | Skill | 설명 |
49
30
  |-------|------|
50
31
  | `Coding` | 공통 코딩 원칙 (SRP, 응집도, 가독성) |
51
- | `Git` | Git 커밋/PR 규칙 |
32
+ | `Git` | Git 커밋/PR 규칙, PR 리뷰, 피드백 적용 |
52
33
  | `Backend` | 백엔드 개발 원칙 (레이어, TypeORM) |
34
+ | `React` | React 개발 (TanStack Router, React Hook Form, Tailwind) |
35
+ | `Documentation` | .claude 문서 작성 가이드 |
36
+ | `Director` | 디렉터 Agent 운영 스킬 |
53
37
 
54
- ### Hooks (`.claude/hooks/`)
38
+ ### Hooks (`templates/global/hooks/`)
55
39
 
56
- - 워크플로우 순서 강제 프로토콜
57
- - Skill/Agent 평가 프로토콜
40
+ | Hook | 설명 |
41
+ |------|------|
42
+ | `workflow-enforced.sh` | 워크플로우 순서 강제 프로토콜 |
43
+ | `skill-forced.sh` | Skill/Agent 평가 프로토콜 |
58
44
 
59
- ## 커스터마이징
45
+ ### Project Agents (`templates/project/agents/`)
60
46
 
61
- 설치 후 `~/.claude/` 디렉토리에서 필요에 맞게 수정하세요.
47
+ 프로젝트 `.claude/`에 설치되는 프로젝트별 Agent.
62
48
 
63
- ```
64
- ~/.claude/
65
- ├── CLAUDE.md # 작업 가이드
66
- ├── agents/ # Agent 정의 수정/추가
67
- ├── skills/ # Skill 가이드 수정/추가
68
- ├── hooks/ # 자동 실행 스크립트
69
- └── context/ # 프로젝트별 Context (직접 추가)
70
- ```
49
+ | Agent | 역할 |
50
+ |-------|------|
51
+ | `project-task-manager` | GitHub Project 태스크 관리 |
52
+ | `context-generator` | Context 자동 생성 |
71
53
 
72
- ### 프로젝트별 설정
54
+ ### Project Skills (`templates/project/skills/`)
73
55
 
74
- 프로젝트 루트에 `.claude/` 폴더를 만들어 프로젝트별 설정을 추가할 수 있습니다.
56
+ | Skill | 설명 |
57
+ |-------|------|
58
+ | `ContextGeneration` | Context 자동 생성 스킬 |
75
59
 
60
+ ### Workflow
61
+
62
+ Planning -> Validation -> Implementation -> Review 순서의 작업 워크플로우와 Context 절약 원칙(Subagent 위임 규칙)을 정의합니다.
63
+
64
+ ## 설치
65
+
66
+ ```bash
67
+ # npx로 바로 실행
68
+ npx jun-claude-code
69
+
70
+ # 또는 전역 설치
71
+ npm install -g jun-claude-code
76
72
  ```
77
- your-project/
78
- ├── .claude/
79
- │ ├── context/ # 프로젝트 아키텍처, 도메인 지식
80
- │ └── skills/ # 프로젝트 전용 스킬
81
- └── CLAUDE.md # 프로젝트 설명
73
+
74
+ ## 사용법
75
+
76
+ ### 기본 명령어: 설정 복사
77
+
78
+ `templates/global` 설정 파일을 `~/.claude`로 복사합니다.
79
+
80
+ ```bash
81
+ jun-claude-code
82
82
  ```
83
83
 
84
- ### GitHub Project 연동
84
+ | 옵션 | 설명 |
85
+ |------|------|
86
+ | `--dry-run`, `-d` | 실제 복사 없이 복사될 파일 목록만 확인 |
87
+ | `--force`, `-f` | 확인 없이 모든 파일 덮어쓰기 |
85
88
 
86
- `init-project` 커맨드로 GitHub Project 태스크 관리를 프로젝트에 연동할 수 있습니다.
89
+ ### `init-project`: GitHub Project 연동
90
+
91
+ 프로젝트 디렉토리에서 GitHub Project 태스크 관리를 설정합니다.
87
92
 
88
93
  ```bash
89
- # 프로젝트 루트에서 실행
90
94
  jun-claude-code init-project
91
95
  ```
92
96
 
93
- 실행하면 다음을 인터랙티브로 설정합니다:
94
-
95
- 1. **GitHub Owner** (org 또는 user)
96
- 2. **Project Number**
97
- 3. **Repository** (owner/repo 형식)
97
+ 인터랙티브로 다음을 설정합니다:
98
+ - GitHub Owner (org 또는 user)
99
+ - Project Number
100
+ - Repository (owner/repo 형식)
98
101
 
99
- 설정 완료 프로젝트에 생성되는 파일:
102
+ 설정 후 생성되는 파일:
100
103
 
101
104
  ```
102
- your-project/
103
- ├── .claude/
104
- ├── project.env # GitHub Project 설정 (GITHUB_PROJECT_OWNER 등)
105
- ├── settings.json # StartSession hook (세션 시작 시 태스크 표시)
106
- ├── hooks/
107
- │ │ └── task-loader.sh # 태스크 조회 스크립트
108
- └── agents/
109
- │ └── project-task-manager.md # 태스크 관리 Agent
105
+ .claude/
106
+ ├── project.env # GitHub Project 환경변수
107
+ ├── settings.json # StartSession hook 설정
108
+ ├── hooks/
109
+ └── task-loader.sh # 태스크 조회 스크립트
110
+ └── agents/
111
+ └── project-task-manager.md # 태스크 관리 Agent
110
112
  ```
111
113
 
112
- #### 수동 설정
114
+ > `read:project` 스코프 필요: `gh auth refresh -s read:project,project`
115
+
116
+ ### `init-context`: Context 자동 생성 설정
113
117
 
114
- `init-project` 대신 직접 `.claude/project.env`를 생성할 수도 있습니다:
118
+ GitHub Actions를 통한 Context 문서 자동 생성을 설정합니다.
115
119
 
116
120
  ```bash
117
- # .claude/project.env
118
- GITHUB_PROJECT_OWNER=your-org
119
- GITHUB_PROJECT_NUMBER=1
120
- GITHUB_PROJECT_REPO=your-org/your-repo
121
+ jun-claude-code init-context
121
122
  ```
122
123
 
123
- #### 필요 권한
124
+ 설정 생성되는 파일:
124
125
 
125
- GitHub Project 접근에 `read:project` 스코프가 필요합니다:
126
+ ```
127
+ .github/workflows/
128
+ └── context-gen.yml # Context 생성 GitHub Actions 워크플로우
129
+
130
+ .claude/
131
+ ├── agents/
132
+ │ └── context-generator.md # Context 자동 생성 Agent
133
+ ├── skills/
134
+ │ └── ContextGeneration/
135
+ │ └── SKILL.md # Context 자동 생성 Skill
136
+ └── context/
137
+ ├── codebase/
138
+ │ └── INDEX.md # 코드베이스 모듈 참조 목록
139
+ └── business/
140
+ └── INDEX.md # 비즈니스 도메인 참조 목록
141
+ ```
142
+
143
+ > `CLAUDE_CODE_OAUTH_TOKEN`를 GitHub repository secrets에 추가해야 합니다.
144
+
145
+ ## 프로젝트 구조
126
146
 
127
- ```bash
128
- gh auth refresh -s read:project,project
129
147
  ```
148
+ templates/
149
+ ├── global/ # ~/.claude/에 설치되는 전역 설정
150
+ │ ├── CLAUDE.md # 작업 가이드 (워크플로우, Context 절약 원칙)
151
+ │ ├── agents/ # Subagent 정의 (13종)
152
+ │ ├── skills/ # 스킬 가이드 (코딩, Git, BE, FE 등)
153
+ │ ├── hooks/ # 자동 실행 스크립트 (워크플로우 강제, 스킬 평가)
154
+ │ └── settings.json # Claude Code 전역 설정
155
+ └── project/ # 프로젝트 .claude/에 설치되는 프로젝트별 설정
156
+ ├── agents/ # project-task-manager, context-generator Agent
157
+ ├── skills/ # ContextGeneration Skill
158
+ ├── hooks/ # task-loader Hook
159
+ ├── workflows/ # context-gen Workflow
160
+ └── project.env.example
161
+ ```
162
+
163
+ ## 커스터마이징
130
164
 
131
- ## 핵심 원칙
165
+ 설치 `~/.claude/`에서 필요에 맞게 수정할 수 있습니다. 프로젝트별로는 프로젝트 루트에 `.claude/`를 만들어 설정을 추가합니다.
132
166
 
133
- 이 템플릿의 핵심 원칙:
167
+ ```
168
+ your-project/
169
+ ├── .claude/
170
+ │ ├── context/ # 프로젝트 아키텍처, 도메인 지식
171
+ │ └── skills/ # 프로젝트 전용 스킬
172
+ └── CLAUDE.md # 프로젝트 설명
173
+ ```
134
174
 
135
- 1. **Context 절약**: Main Agent의 Context Window 보존을 위해 Subagent에 작업 위임
136
- 2. **워크플로우 준수**: Planning Validation Implementation Review
137
- 3. **Git 작업 위임**: 모든 Git 작업은 `git-manager` Agent 사용
175
+ - **context/**: 프로젝트의 사실/배경 정보 (아키텍처, 도메인 모델, API 스펙 등)
176
+ - **skills/**: 프로젝트 고유의 작업 절차 (배포 방법, 테스트 규칙 등)
138
177
 
139
178
  ## License
140
179
 
package/dist/cli.js CHANGED
@@ -33,9 +33,15 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  return result;
34
34
  };
35
35
  })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
36
39
  Object.defineProperty(exports, "__esModule", { value: true });
37
40
  const commander_1 = require("commander");
41
+ const chalk_1 = __importDefault(require("chalk"));
38
42
  const copy_1 = require("./copy");
43
+ const init_context_1 = require("./init-context");
44
+ const validate_1 = require("./validate");
39
45
  const program = new commander_1.Command();
40
46
  program
41
47
  .name('jun-claude-code')
@@ -78,4 +84,38 @@ program
78
84
  process.exit(1);
79
85
  }
80
86
  });
87
+ program
88
+ .command('init-context')
89
+ .description('Setup context auto-generation with GitHub Actions')
90
+ .action(async () => {
91
+ try {
92
+ await (0, init_context_1.initContext)();
93
+ }
94
+ catch (error) {
95
+ if (error instanceof Error) {
96
+ console.error('Error:', error.message);
97
+ }
98
+ else {
99
+ console.error('An unexpected error occurred');
100
+ }
101
+ process.exit(1);
102
+ }
103
+ });
104
+ program
105
+ .command('validate')
106
+ .description('Validate template directory structure')
107
+ .action(async () => {
108
+ try {
109
+ await (0, validate_1.validateTemplates)();
110
+ }
111
+ catch (error) {
112
+ if (error instanceof Error) {
113
+ console.error(chalk_1.default.red('Validation failed:'), error.message);
114
+ }
115
+ else {
116
+ console.error(chalk_1.default.red('Validation failed'));
117
+ }
118
+ process.exit(1);
119
+ }
120
+ });
81
121
  program.parse();
package/dist/copy.js CHANGED
@@ -93,12 +93,12 @@ function copyFile(src, dest) {
93
93
  fs.copyFileSync(src, dest);
94
94
  }
95
95
  /**
96
- * Get the source .claude directory path (from package installation)
96
+ * Get the source templates/global directory path (from package installation)
97
97
  */
98
- function getSourceClaudeDir() {
98
+ function getSourceGlobalDir() {
99
99
  // When installed as npm package, __dirname is in dist/
100
- // .claude folder is at package root (sibling to dist/)
101
- return path.resolve(__dirname, '..', '.claude');
100
+ // templates/global folder is at package root
101
+ return path.resolve(__dirname, '..', 'templates', 'global');
102
102
  }
103
103
  /**
104
104
  * Get the destination .claude directory path (user's home)
@@ -110,26 +110,100 @@ function getDestClaudeDir() {
110
110
  }
111
111
  return path.join(homeDir, '.claude');
112
112
  }
113
+ /**
114
+ * Merge settings.json from source into destination.
115
+ * Hooks are merged per event key; duplicate hook entries (by deep equality) are skipped.
116
+ * Non-hook keys are shallow-merged (source wins for new keys, dest preserved for existing).
117
+ */
118
+ function mergeSettingsJson(sourceDir, destDir) {
119
+ const sourcePath = path.join(sourceDir, 'settings.json');
120
+ const destPath = path.join(destDir, 'settings.json');
121
+ if (!fs.existsSync(sourcePath)) {
122
+ return;
123
+ }
124
+ let sourceSettings;
125
+ try {
126
+ sourceSettings = JSON.parse(fs.readFileSync(sourcePath, 'utf-8'));
127
+ }
128
+ catch {
129
+ console.log(chalk_1.default.yellow(' Warning: Could not parse source settings.json, skipping merge.'));
130
+ return;
131
+ }
132
+ let destSettings = {};
133
+ if (fs.existsSync(destPath)) {
134
+ try {
135
+ destSettings = JSON.parse(fs.readFileSync(destPath, 'utf-8'));
136
+ }
137
+ catch {
138
+ console.log(chalk_1.default.yellow(' Warning: Could not parse destination settings.json, creating fresh.'));
139
+ destSettings = {};
140
+ }
141
+ }
142
+ // Merge top-level keys (source fills in missing keys, dest's existing keys preserved)
143
+ for (const key of Object.keys(sourceSettings)) {
144
+ if (key === 'hooks') {
145
+ continue; // hooks are merged separately below
146
+ }
147
+ if (!(key in destSettings)) {
148
+ destSettings[key] = sourceSettings[key];
149
+ }
150
+ }
151
+ // Merge hooks
152
+ const sourceHooks = sourceSettings.hooks || {};
153
+ if (!destSettings.hooks) {
154
+ destSettings.hooks = {};
155
+ }
156
+ const destHooks = destSettings.hooks;
157
+ for (const event of Object.keys(sourceHooks)) {
158
+ const sourceEntries = sourceHooks[event] || [];
159
+ if (!destHooks[event]) {
160
+ destHooks[event] = [];
161
+ }
162
+ const destEntries = destHooks[event];
163
+ // Extract a command-based key from a hook entry for duplicate detection.
164
+ // Type 1: { type: "command", command: "..." } → returns "type:command"
165
+ // Type 2: { hooks: [{ type: "command", command: "..." }, ...] } → returns sorted "type:command" joined
166
+ const getHookKey = (entry) => {
167
+ if (entry.hooks && Array.isArray(entry.hooks)) {
168
+ return entry.hooks
169
+ .map((h) => `${h.type || ''}:${h.command || ''}`)
170
+ .sort()
171
+ .join('\n');
172
+ }
173
+ return `${entry.type || ''}:${entry.command || ''}`;
174
+ };
175
+ // Build a Set of command keys from existing entries for fast duplicate detection
176
+ const existingKeys = new Set(destEntries.map((entry) => getHookKey(entry)));
177
+ for (const entry of sourceEntries) {
178
+ const key = getHookKey(entry);
179
+ if (!existingKeys.has(key)) {
180
+ destEntries.push(entry);
181
+ existingKeys.add(key);
182
+ }
183
+ }
184
+ }
185
+ ensureDir(destDir);
186
+ fs.writeFileSync(destPath, JSON.stringify(destSettings, null, 2) + '\n', 'utf-8');
187
+ console.log(` ${chalk_1.default.blue('[merged]')} settings.json`);
188
+ }
113
189
  /**
114
190
  * Copy .claude files to user's home directory
115
191
  */
116
192
  async function copyClaudeFiles(options = {}) {
117
193
  const { dryRun = false, force = false } = options;
118
- const sourceDir = getSourceClaudeDir();
194
+ const sourceDir = getSourceGlobalDir();
119
195
  const destDir = getDestClaudeDir();
120
196
  console.log(chalk_1.default.blue('Source:'), sourceDir);
121
197
  console.log(chalk_1.default.blue('Destination:'), destDir);
122
198
  console.log();
123
199
  // Check if source exists
124
200
  if (!fs.existsSync(sourceDir)) {
125
- console.error(chalk_1.default.red('Error:'), 'Source .claude directory not found');
201
+ console.error(chalk_1.default.red('Error:'), 'Source templates/global directory not found');
126
202
  process.exit(1);
127
203
  }
128
- // Files to exclude from global copy (project-specific files)
204
+ // Files to exclude from global copy (merge-handled separately)
129
205
  const EXCLUDE_FROM_GLOBAL = [
130
- 'hooks/task-loader.sh',
131
- 'agents/project-task-manager.md',
132
- 'project.env.example',
206
+ 'settings.json',
133
207
  ];
134
208
  // Get all files to copy
135
209
  const allFiles = getAllFiles(sourceDir);
@@ -137,7 +211,7 @@ async function copyClaudeFiles(options = {}) {
137
211
  return !EXCLUDE_FROM_GLOBAL.includes(file);
138
212
  });
139
213
  if (files.length === 0) {
140
- console.log(chalk_1.default.yellow('No files found in .claude directory'));
214
+ console.log(chalk_1.default.yellow('No files found in templates/global directory'));
141
215
  return;
142
216
  }
143
217
  console.log(chalk_1.default.cyan(`Found ${files.length} files to copy:`));
@@ -152,6 +226,11 @@ async function copyClaudeFiles(options = {}) {
152
226
  const status = exists ? chalk_1.default.yellow('[overwrite]') : chalk_1.default.green('[new]');
153
227
  console.log(` ${status} ${file}`);
154
228
  }
229
+ // settings.json merge indicator
230
+ const sourceSettingsExists = fs.existsSync(path.join(sourceDir, 'settings.json'));
231
+ if (sourceSettingsExists) {
232
+ console.log(` ${chalk_1.default.blue('[merge]')} settings.json`);
233
+ }
155
234
  console.log();
156
235
  console.log(chalk_1.default.yellow('No files were copied (dry run mode)'));
157
236
  return;
@@ -177,6 +256,8 @@ async function copyClaudeFiles(options = {}) {
177
256
  console.log(` ${status} ${file}`);
178
257
  copiedCount++;
179
258
  }
259
+ // Merge settings.json (hooks are merged, not overwritten)
260
+ mergeSettingsJson(sourceDir, destDir);
180
261
  console.log();
181
262
  console.log(chalk_1.default.green(`Done! Copied ${copiedCount} files, skipped ${skippedCount} files.`));
182
263
  }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { copyClaudeFiles, CopyOptions } from './copy';
2
2
  export { initProject } from './init-project';
3
+ export { initContext } from './init-context';
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initProject = exports.copyClaudeFiles = void 0;
3
+ exports.initContext = exports.initProject = exports.copyClaudeFiles = void 0;
4
4
  var copy_1 = require("./copy");
5
5
  Object.defineProperty(exports, "copyClaudeFiles", { enumerable: true, get: function () { return copy_1.copyClaudeFiles; } });
6
6
  var init_project_1 = require("./init-project");
7
7
  Object.defineProperty(exports, "initProject", { enumerable: true, get: function () { return init_project_1.initProject; } });
8
+ var init_context_1 = require("./init-context");
9
+ Object.defineProperty(exports, "initContext", { enumerable: true, get: function () { return init_context_1.initContext; } });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Initialize context auto-generation with GitHub Actions
3
+ */
4
+ export declare function initContext(): Promise<void>;
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.initContext = initContext;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ /**
44
+ * Get the templates/project directory path (from package installation)
45
+ */
46
+ function getTemplatesDir() {
47
+ return path.resolve(__dirname, '..', 'templates', 'project');
48
+ }
49
+ /**
50
+ * Initialize context auto-generation with GitHub Actions
51
+ */
52
+ async function initContext() {
53
+ const cwd = process.cwd();
54
+ console.log(chalk_1.default.bold('\n📄 Initializing Context Auto-Generation...\n'));
55
+ // 1. templates/project/workflows/context-gen.yml → .github/workflows/context-gen.yml 복사
56
+ const templateSrc = path.join(getTemplatesDir(), 'workflows', 'context-gen.yml');
57
+ const workflowDest = path.join(cwd, '.github', 'workflows', 'context-gen.yml');
58
+ fs.mkdirSync(path.dirname(workflowDest), { recursive: true });
59
+ if (fs.existsSync(workflowDest)) {
60
+ console.log(chalk_1.default.yellow(' ⚠ .github/workflows/context-gen.yml already exists, skipping'));
61
+ }
62
+ else {
63
+ fs.copyFileSync(templateSrc, workflowDest);
64
+ console.log(chalk_1.default.green(' ✓ Created .github/workflows/context-gen.yml'));
65
+ }
66
+ // 2. context-generator Agent 복사
67
+ const agentSrc = path.join(getTemplatesDir(), 'agents', 'context-generator.md');
68
+ const agentDest = path.join(cwd, '.claude', 'agents', 'context-generator.md');
69
+ fs.mkdirSync(path.dirname(agentDest), { recursive: true });
70
+ if (fs.existsSync(agentDest)) {
71
+ console.log(chalk_1.default.yellow(' ⚠ .claude/agents/context-generator.md already exists, skipping'));
72
+ }
73
+ else {
74
+ fs.copyFileSync(agentSrc, agentDest);
75
+ console.log(chalk_1.default.green(' ✓ Created .claude/agents/context-generator.md'));
76
+ }
77
+ // 3. ContextGeneration Skill 복사
78
+ const skillSrc = path.join(getTemplatesDir(), 'skills', 'ContextGeneration', 'SKILL.md');
79
+ const skillDest = path.join(cwd, '.claude', 'skills', 'ContextGeneration', 'SKILL.md');
80
+ fs.mkdirSync(path.dirname(skillDest), { recursive: true });
81
+ if (fs.existsSync(skillDest)) {
82
+ console.log(chalk_1.default.yellow(' ⚠ .claude/skills/ContextGeneration/SKILL.md already exists, skipping'));
83
+ }
84
+ else {
85
+ fs.copyFileSync(skillSrc, skillDest);
86
+ console.log(chalk_1.default.green(' ✓ Created .claude/skills/ContextGeneration/SKILL.md'));
87
+ }
88
+ // 4. .claude/context/codebase/ 디렉토리 + stub INDEX.md
89
+ const codebaseDirPath = path.join(cwd, '.claude', 'context', 'codebase');
90
+ const codebaseIndex = path.join(codebaseDirPath, 'INDEX.md');
91
+ fs.mkdirSync(codebaseDirPath, { recursive: true });
92
+ if (fs.existsSync(codebaseIndex)) {
93
+ console.log(chalk_1.default.yellow(' ⚠ .claude/context/codebase/INDEX.md already exists, skipping'));
94
+ }
95
+ else {
96
+ fs.writeFileSync(codebaseIndex, `---
97
+ name: Codebase Index
98
+ description: 코드베이스 모듈 참조 목록
99
+ ---
100
+
101
+ # Codebase Context Index
102
+
103
+ ## 모듈 목록
104
+
105
+ | 모듈 | 설명 | 문서 |
106
+ |------|------|------|
107
+ `);
108
+ console.log(chalk_1.default.green(' ✓ Created .claude/context/codebase/INDEX.md'));
109
+ }
110
+ // 5. .claude/context/business/ 디렉토리 + stub INDEX.md
111
+ const businessDirPath = path.join(cwd, '.claude', 'context', 'business');
112
+ const businessIndex = path.join(businessDirPath, 'INDEX.md');
113
+ fs.mkdirSync(businessDirPath, { recursive: true });
114
+ if (fs.existsSync(businessIndex)) {
115
+ console.log(chalk_1.default.yellow(' ⚠ .claude/context/business/INDEX.md already exists, skipping'));
116
+ }
117
+ else {
118
+ fs.writeFileSync(businessIndex, `---
119
+ name: Business Index
120
+ description: 비즈니스 도메인 참조 목록
121
+ ---
122
+
123
+ # Business Context Index
124
+
125
+ ## 프로젝트 개요
126
+
127
+ <!-- 프로젝트가 해결하는 문제와 대상 사용자를 작성하세요 -->
128
+
129
+ ## 도메인 목록
130
+
131
+ | 도메인 | 설명 | 문서 |
132
+ |--------|------|------|
133
+ `);
134
+ console.log(chalk_1.default.green(' ✓ Created .claude/context/business/INDEX.md'));
135
+ }
136
+ // 6. 안내 메시지
137
+ console.log(chalk_1.default.bold('\n✅ Context auto-generation setup complete!\n'));
138
+ console.log(chalk_1.default.cyan('Next steps:'));
139
+ console.log(chalk_1.default.cyan(' 1. Add CLAUDE_CODE_OAUTH_TOKEN to your repository secrets'));
140
+ console.log(chalk_1.default.cyan(' → Settings > Secrets and variables > Actions > New repository secret'));
141
+ console.log(chalk_1.default.cyan(' 2. Create a PR to trigger context auto-generation'));
142
+ console.log('');
143
+ }
@@ -57,10 +57,10 @@ function askQuestion(question) {
57
57
  });
58
58
  }
59
59
  /**
60
- * Get the source .claude directory path (from package installation)
60
+ * Get the source templates/project directory path (from package installation)
61
61
  */
62
- function getSourceClaudeDir() {
63
- return path.resolve(__dirname, '..', '.claude');
62
+ function getSourceProjectDir() {
63
+ return path.resolve(__dirname, '..', 'templates', 'project');
64
64
  }
65
65
  /**
66
66
  * Get the project .claude directory path (current working directory)
@@ -101,7 +101,7 @@ function createProjectEnv(destDir, config) {
101
101
  * Copy a project-specific file from package source to project directory
102
102
  */
103
103
  function copyProjectFile(srcRelative, destDir) {
104
- const srcPath = path.join(getSourceClaudeDir(), srcRelative);
104
+ const srcPath = path.join(getSourceProjectDir(), srcRelative);
105
105
  const destPath = path.join(destDir, srcRelative);
106
106
  if (!fs.existsSync(srcPath)) {
107
107
  console.log(chalk_1.default.yellow(` ⚠ 소스 파일 없음: ${srcRelative}`));
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Validate template directory structure
3
+ */
4
+ export declare function validateTemplates(): Promise<void>;