jun-claude-code 0.0.11 → 0.0.12

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 (44) hide show
  1. package/README.md +104 -83
  2. package/dist/cli.js +18 -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 +121 -0
  8. package/dist/init-project.js +4 -4
  9. package/package.json +2 -2
  10. package/templates/global/agents/context-generator.md +66 -0
  11. package/{.claude → templates/global}/agents/context-manager.md +1 -1
  12. package/{.claude → templates/global}/agents/explore.md +1 -1
  13. package/{.claude → templates/global}/agents/simple-code-writer.md +1 -1
  14. package/{.claude → templates/global}/hooks/skill-forced.sh +2 -12
  15. package/templates/global/skills/ContextGeneration/SKILL.md +152 -0
  16. package/templates/project/workflows/context-gen.yml +52 -0
  17. /package/{.claude → templates/global}/CLAUDE.md +0 -0
  18. /package/{.claude → templates/global}/agents/architect.md +0 -0
  19. /package/{.claude → templates/global}/agents/code-reviewer.md +0 -0
  20. /package/{.claude → templates/global}/agents/code-writer.md +0 -0
  21. /package/{.claude → templates/global}/agents/context-collector.md +0 -0
  22. /package/{.claude → templates/global}/agents/designer.md +0 -0
  23. /package/{.claude → templates/global}/agents/director.md +0 -0
  24. /package/{.claude → templates/global}/agents/git-manager.md +0 -0
  25. /package/{.claude → templates/global}/agents/impact-analyzer.md +0 -0
  26. /package/{.claude → templates/global}/agents/qa-tester.md +0 -0
  27. /package/{.claude → templates/global}/agents/task-planner.md +0 -0
  28. /package/{.claude → templates/global}/hooks/workflow-enforced.sh +0 -0
  29. /package/{.claude → templates/global}/settings.json +0 -0
  30. /package/{.claude → templates/global}/skills/Backend/SKILL.md +0 -0
  31. /package/{.claude → templates/global}/skills/Coding/SKILL.md +0 -0
  32. /package/{.claude → templates/global}/skills/Director/SKILL.md +0 -0
  33. /package/{.claude → templates/global}/skills/Documentation/SKILL.md +0 -0
  34. /package/{.claude → templates/global}/skills/Git/SKILL.md +0 -0
  35. /package/{.claude → templates/global}/skills/Git/git.md +0 -0
  36. /package/{.claude → templates/global}/skills/Git/pr-apply.md +0 -0
  37. /package/{.claude → templates/global}/skills/Git/pr-review.md +0 -0
  38. /package/{.claude → templates/global}/skills/React/SKILL.md +0 -0
  39. /package/{.claude → templates/global}/skills/React/react-hook-form.md +0 -0
  40. /package/{.claude → templates/global}/skills/React/tailwind-styled.md +0 -0
  41. /package/{.claude → templates/global}/skills/React/tanstack-router.md +0 -0
  42. /package/{.claude → templates/project}/agents/project-task-manager.md +0 -0
  43. /package/{.claude → templates/project}/hooks/task-loader.sh +0 -0
  44. /package/{.claude → templates/project}/project.env.example +0 -0
package/README.md CHANGED
@@ -1,140 +1,161 @@
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
23
-
24
- # 강제 덮어쓰기 (확인 없이 모든 파일 복사)
25
- jun-claude-code --force
26
- ```
5
+ ## 포함 내용
27
6
 
28
- ## 포함된 설정
7
+ ### Agents (`templates/global/agents/`)
29
8
 
30
- ### Agents (`.claude/agents/`)
9
+ 작업별 전문 Subagent 15종. 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 문서 관리 |
26
+ | `context-generator` | Context 자동 생성 |
27
+ | `project-task-manager` | GitHub Project 태스크 관리 |
45
28
 
46
- ### Skills (`.claude/skills/`)
29
+ ### Skills (`templates/global/skills/`)
47
30
 
48
31
  | Skill | 설명 |
49
32
  |-------|------|
50
33
  | `Coding` | 공통 코딩 원칙 (SRP, 응집도, 가독성) |
51
- | `Git` | Git 커밋/PR 규칙 |
34
+ | `Git` | Git 커밋/PR 규칙, PR 리뷰, 피드백 적용 |
52
35
  | `Backend` | 백엔드 개발 원칙 (레이어, TypeORM) |
36
+ | `React` | React 개발 (TanStack Router, React Hook Form, Tailwind) |
37
+ | `Documentation` | .claude 문서 작성 가이드 |
38
+ | `Director` | 디렉터 Agent 운영 스킬 |
39
+ | `ContextGeneration` | Context 자동 생성 스킬 |
53
40
 
54
- ### Hooks (`.claude/hooks/`)
41
+ ### Hooks (`templates/global/hooks/`)
55
42
 
56
- - 워크플로우 순서 강제 프로토콜
57
- - Skill/Agent 평가 프로토콜
43
+ | Hook | 설명 |
44
+ |------|------|
45
+ | `workflow-enforced.sh` | 워크플로우 순서 강제 프로토콜 |
46
+ | `skill-forced.sh` | Skill/Agent 평가 프로토콜 |
47
+ | `task-loader.sh` | GitHub Project 태스크 조회 |
58
48
 
59
- ## 커스터마이징
49
+ ### Workflow
60
50
 
61
- 설치 `~/.claude/` 디렉토리에서 필요에 맞게 수정하세요.
51
+ Planning -> Validation -> Implementation -> Review 순서의 작업 워크플로우와 Context 절약 원칙(Subagent 위임 규칙)을 정의합니다.
62
52
 
63
- ```
64
- ~/.claude/
65
- ├── CLAUDE.md # 작업 가이드
66
- ├── agents/ # Agent 정의 수정/추가
67
- ├── skills/ # Skill 가이드 수정/추가
68
- ├── hooks/ # 자동 실행 스크립트
69
- └── context/ # 프로젝트별 Context (직접 추가)
53
+ ## 설치
54
+
55
+ ```bash
56
+ # npx로 바로 실행
57
+ npx jun-claude-code
58
+
59
+ # 또는 전역 설치
60
+ npm install -g jun-claude-code
70
61
  ```
71
62
 
72
- ### 프로젝트별 설정
63
+ ## 사용법
73
64
 
74
- 프로젝트 루트에 `.claude/` 폴더를 만들어 프로젝트별 설정을 추가할 수 있습니다.
65
+ ### 기본 명령어: 설정 복사
75
66
 
67
+ `templates/global` 설정 파일을 `~/.claude`로 복사합니다.
68
+
69
+ ```bash
70
+ jun-claude-code
76
71
  ```
77
- your-project/
78
- ├── .claude/
79
- │ ├── context/ # 프로젝트 아키텍처, 도메인 지식
80
- │ └── skills/ # 프로젝트 전용 스킬
81
- └── CLAUDE.md # 프로젝트 설명
82
- ```
83
72
 
84
- ### GitHub Project 연동
73
+ | 옵션 | 설명 |
74
+ |------|------|
75
+ | `--dry-run`, `-d` | 실제 복사 없이 복사될 파일 목록만 확인 |
76
+ | `--force`, `-f` | 확인 없이 모든 파일 덮어쓰기 |
77
+
78
+ ### `init-project`: GitHub Project 연동
85
79
 
86
- `init-project` 커맨드로 GitHub Project 태스크 관리를 프로젝트에 연동할 수 있습니다.
80
+ 프로젝트 디렉토리에서 GitHub Project 태스크 관리를 설정합니다.
87
81
 
88
82
  ```bash
89
- # 프로젝트 루트에서 실행
90
83
  jun-claude-code init-project
91
84
  ```
92
85
 
93
- 실행하면 다음을 인터랙티브로 설정합니다:
94
-
95
- 1. **GitHub Owner** (org 또는 user)
96
- 2. **Project Number**
97
- 3. **Repository** (owner/repo 형식)
86
+ 인터랙티브로 다음을 설정합니다:
87
+ - GitHub Owner (org 또는 user)
88
+ - Project Number
89
+ - Repository (owner/repo 형식)
98
90
 
99
- 설정 완료 프로젝트에 생성되는 파일:
91
+ 설정 후 생성되는 파일:
100
92
 
101
93
  ```
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
94
+ .claude/
95
+ ├── project.env # GitHub Project 환경변수
96
+ ├── settings.json # StartSession hook 설정
97
+ ├── hooks/
98
+ └── task-loader.sh # 태스크 조회 스크립트
99
+ └── agents/
100
+ └── project-task-manager.md # 태스크 관리 Agent
110
101
  ```
111
102
 
112
- #### 수동 설정
103
+ > `read:project` 스코프 필요: `gh auth refresh -s read:project,project`
104
+
105
+ ### `init-context`: Context 자동 생성 설정
113
106
 
114
- `init-project` 대신 직접 `.claude/project.env`를 생성할 수도 있습니다:
107
+ GitHub Actions를 통한 Context 문서 자동 생성을 설정합니다.
115
108
 
116
109
  ```bash
117
- # .claude/project.env
118
- GITHUB_PROJECT_OWNER=your-org
119
- GITHUB_PROJECT_NUMBER=1
120
- GITHUB_PROJECT_REPO=your-org/your-repo
110
+ jun-claude-code init-context
121
111
  ```
122
112
 
123
- #### 필요 권한
113
+ 설정 생성되는 파일:
124
114
 
125
- GitHub Project 접근에 `read:project` 스코프가 필요합니다:
115
+ ```
116
+ .github/workflows/
117
+ └── context-gen.yml # Context 생성 GitHub Actions 워크플로우
118
+
119
+ .claude/context/
120
+ ├── codebase/
121
+ │ └── INDEX.md # 코드베이스 모듈 참조 목록
122
+ └── business/
123
+ └── INDEX.md # 비즈니스 도메인 참조 목록
124
+ ```
126
125
 
127
- ```bash
128
- gh auth refresh -s read:project,project
126
+ > `CLAUDE_CODE_OAUTH_TOKEN`를 GitHub repository secrets에 추가해야 합니다.
127
+
128
+ ## 프로젝트 구조
129
+
130
+ ```
131
+ templates/
132
+ ├── global/ # ~/.claude/에 설치되는 전역 설정
133
+ │ ├── CLAUDE.md # 작업 가이드 (워크플로우, Context 절약 원칙)
134
+ │ ├── agents/ # Subagent 정의 (15종)
135
+ │ ├── skills/ # 스킬 가이드 (코딩, Git, BE, FE 등)
136
+ │ ├── hooks/ # 자동 실행 스크립트 (워크플로우 강제, 스킬 평가)
137
+ │ └── settings.json # Claude Code 전역 설정
138
+ └── project/ # 프로젝트 .claude/에 설치되는 프로젝트별 설정
139
+ ├── agents/ # project-task-manager Agent
140
+ ├── hooks/ # task-loader Hook
141
+ ├── workflows/ # context-gen Workflow
142
+ └── project.env.example
129
143
  ```
130
144
 
131
- ## 핵심 원칙
145
+ ## 커스터마이징
146
+
147
+ 설치 후 `~/.claude/`에서 필요에 맞게 수정할 수 있습니다. 프로젝트별로는 프로젝트 루트에 `.claude/`를 만들어 설정을 추가합니다.
132
148
 
133
- 이 템플릿의 핵심 원칙:
149
+ ```
150
+ your-project/
151
+ ├── .claude/
152
+ │ ├── context/ # 프로젝트 아키텍처, 도메인 지식
153
+ │ └── skills/ # 프로젝트 전용 스킬
154
+ └── CLAUDE.md # 프로젝트 설명
155
+ ```
134
156
 
135
- 1. **Context 절약**: Main Agent의 Context Window 보존을 위해 Subagent에 작업 위임
136
- 2. **워크플로우 준수**: Planning Validation Implementation Review
137
- 3. **Git 작업 위임**: 모든 Git 작업은 `git-manager` Agent 사용
157
+ - **context/**: 프로젝트의 사실/배경 정보 (아키텍처, 도메인 모델, API 스펙 등)
158
+ - **skills/**: 프로젝트 고유의 작업 절차 (배포 방법, 테스트 규칙 등)
138
159
 
139
160
  ## License
140
161
 
package/dist/cli.js CHANGED
@@ -36,6 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  const commander_1 = require("commander");
38
38
  const copy_1 = require("./copy");
39
+ const init_context_1 = require("./init-context");
39
40
  const program = new commander_1.Command();
40
41
  program
41
42
  .name('jun-claude-code')
@@ -78,4 +79,21 @@ program
78
79
  process.exit(1);
79
80
  }
80
81
  });
82
+ program
83
+ .command('init-context')
84
+ .description('Setup context auto-generation with GitHub Actions')
85
+ .action(async () => {
86
+ try {
87
+ await (0, init_context_1.initContext)();
88
+ }
89
+ catch (error) {
90
+ if (error instanceof Error) {
91
+ console.error('Error:', error.message);
92
+ }
93
+ else {
94
+ console.error('An unexpected error occurred');
95
+ }
96
+ process.exit(1);
97
+ }
98
+ });
81
99
  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,121 @@
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. .claude/context/codebase/ 디렉토리 + stub INDEX.md
67
+ const codebaseDirPath = path.join(cwd, '.claude', 'context', 'codebase');
68
+ const codebaseIndex = path.join(codebaseDirPath, 'INDEX.md');
69
+ fs.mkdirSync(codebaseDirPath, { recursive: true });
70
+ if (fs.existsSync(codebaseIndex)) {
71
+ console.log(chalk_1.default.yellow(' ⚠ .claude/context/codebase/INDEX.md already exists, skipping'));
72
+ }
73
+ else {
74
+ fs.writeFileSync(codebaseIndex, `---
75
+ name: Codebase Index
76
+ description: 코드베이스 모듈 참조 목록
77
+ ---
78
+
79
+ # Codebase Context Index
80
+
81
+ ## 모듈 목록
82
+
83
+ | 모듈 | 설명 | 문서 |
84
+ |------|------|------|
85
+ `);
86
+ console.log(chalk_1.default.green(' ✓ Created .claude/context/codebase/INDEX.md'));
87
+ }
88
+ // 3. .claude/context/business/ 디렉토리 + stub INDEX.md
89
+ const businessDirPath = path.join(cwd, '.claude', 'context', 'business');
90
+ const businessIndex = path.join(businessDirPath, 'INDEX.md');
91
+ fs.mkdirSync(businessDirPath, { recursive: true });
92
+ if (fs.existsSync(businessIndex)) {
93
+ console.log(chalk_1.default.yellow(' ⚠ .claude/context/business/INDEX.md already exists, skipping'));
94
+ }
95
+ else {
96
+ fs.writeFileSync(businessIndex, `---
97
+ name: Business Index
98
+ description: 비즈니스 도메인 참조 목록
99
+ ---
100
+
101
+ # Business Context Index
102
+
103
+ ## 프로젝트 개요
104
+
105
+ <!-- 프로젝트가 해결하는 문제와 대상 사용자를 작성하세요 -->
106
+
107
+ ## 도메인 목록
108
+
109
+ | 도메인 | 설명 | 문서 |
110
+ |--------|------|------|
111
+ `);
112
+ console.log(chalk_1.default.green(' ✓ Created .claude/context/business/INDEX.md'));
113
+ }
114
+ // 4. 안내 메시지
115
+ console.log(chalk_1.default.bold('\n✅ Context auto-generation setup complete!\n'));
116
+ console.log(chalk_1.default.cyan('Next steps:'));
117
+ console.log(chalk_1.default.cyan(' 1. Add CLAUDE_CODE_OAUTH_TOKEN to your repository secrets'));
118
+ console.log(chalk_1.default.cyan(' → Settings > Secrets and variables > Actions > New repository secret'));
119
+ console.log(chalk_1.default.cyan(' 2. Create a PR to trigger context auto-generation'));
120
+ console.log('');
121
+ }
@@ -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}`));
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "jun-claude-code",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Claude Code configuration template - copy .claude settings to your project",
5
5
  "main": "dist/index.js",
6
6
  "bin": "dist/cli.js",
7
7
  "files": [
8
8
  "dist",
9
- ".claude"
9
+ "templates"
10
10
  ],
11
11
  "scripts": {
12
12
  "build": "tsc",
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: context-generator
3
+ description: GitHub Action에서 PR diff 기반으로 .claude/context/ 문서를 자동 생성/업데이트 (CI 전용)
4
+ keywords: [context, PR, diff, codebase, business, 문서생성]
5
+ model: sonnet
6
+ color: green
7
+ ---
8
+
9
+ # Context Generator Agent
10
+
11
+ PR의 변경 내용을 분석하여 `.claude/context/` 하위에 codebase/business 문서를 자동 생성하고 업데이트합니다.
12
+
13
+ ## 실행 조건
14
+
15
+ - GitHub Action에서 PR 이벤트로 트리거
16
+ - `anthropics/claude-code-action@v1`을 통해 실행
17
+
18
+ ## 프로세스
19
+
20
+ ### 1. Diff 수집
21
+
22
+ ```bash
23
+ git diff HEAD~1 --name-only
24
+ ```
25
+
26
+ 변경된 파일 목록을 수집합니다.
27
+
28
+ ### 2. 모듈 매핑
29
+
30
+ 변경된 파일을 모듈 단위로 그룹화합니다.
31
+ - `src/cli.ts` → `cli` 모듈
32
+ - `src/copy.ts` → `copy-logic` 모듈
33
+ - `.claude/agents/*.md` → `agents` 모듈
34
+
35
+ ### 3. 기존 Context 확인
36
+
37
+ `.claude/context/codebase/`와 `.claude/context/business/`에서 기존 문서를 확인합니다.
38
+ - 기존 문서가 있으면 → 업데이트
39
+ - 기존 문서가 없으면 → 새로 생성
40
+
41
+ ### 4. Codebase Context 생성
42
+
43
+ [ContextGeneration Skill](../../skills/ContextGeneration/SKILL.md)의 Codebase 규칙에 따라:
44
+ - 모듈별 `.md` 파일 생성/업데이트
45
+ - 파일 경로와 함수명만 참조 (원본 코드 포함 금지)
46
+ - `codebase/INDEX.md` 업데이트
47
+
48
+ ### 5. Business Context 생성
49
+
50
+ [ContextGeneration Skill](../../skills/ContextGeneration/SKILL.md)의 Business 규칙에 따라:
51
+ - 기술 용어를 비즈니스 관점으로 변환
52
+ - 도메인별 `.md` 파일 생성/업데이트
53
+ - `business/INDEX.md` 업데이트
54
+
55
+ ### 6. 커밋
56
+
57
+ ```bash
58
+ git add .claude/context/
59
+ git commit -m "docs: update context for PR changes"
60
+ ```
61
+
62
+ ## 제약사항
63
+
64
+ - `.claude/context/**` 경로 변경은 무시 (무한루프 방지)
65
+ - 변경된 파일과 관련된 context만 업데이트 (전체 재생성 금지)
66
+ - 원본 소스 코드를 context 문서에 포함하지 않음
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: context-manager
3
- description: .claude 문서의 파일 구조/포맷 최적화 시 호출. 큰 파일을 INDEX.md + 상세파일로 분리, 중복 제거, 테이블 압축으로 토큰 절약. (스펙 내용의 논리적 정합성 검증은 director 담당)
3
+ description: 기존 .claude/context/ 문서의 구조 최적화 시 호출. 큰 파일을 INDEX.md + 상세파일로 분리, 중복 제거, 테이블 압축으로 토큰 절약 (수동 호출, 스펙 정합성 검증은 director 담당)
4
4
  keywords: [Context관리, 문서정리, 파일분리, 토큰최적화, 구조개선, 문서품질]
5
5
  model: sonnet
6
6
  color: green
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: explore
3
- description: 파일 위치/코드 검색이 필요할 때 호출. Glob/Grep으로 빠른 탐색, 파일 구조 파악. Main Context 오염 없이 결과만 반환.
3
+ description: 파일 위치/코드 검색이 필요할 때 호출. Glob/Grep으로 빠른 탐색, 파일 구조 파악.
4
4
  keywords: [탐색, 검색, 파일찾기, 패턴매칭, 구조파악, Glob, Grep, 빠른검색]
5
5
  model: haiku
6
6
  color: gray
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: simple-code-writer
3
- description: 1-2개 파일의 간단한 코드 수정 시 호출. Main Agent 대신 단순 수정, 설정 변경, 오타 수정 등을 수행.
3
+ description: lint/build 오류, 오타, 설정값 등 간단한 코드 수정 시 호출. 단순 수정, 설정 변경, 오타 수정 수행.
4
4
  keywords: [간단수정, 단순수정, 설정변경, 오타수정, 1-2파일, 소규모수정]
5
5
  model: haiku
6
6
  color: cyan
@@ -25,18 +25,8 @@ Main Agent의 Context Window는 제한적입니다.
25
25
 
26
26
  ### 🚨 필수 위임 작업 (Main Agent 직접 수행 금지)
27
27
 
28
- | 작업 유형 | 사용할 Agent | 이유 |
29
- |----------|-------------|------|
30
- | 코드베이스 탐색/검색 | explore | 파일 내용이 Main Context에 쌓이지 않음 |
31
- | 여러 파일 읽기 | explore / context-collector | 탐색 결과만 요약해서 받음 |
32
- | 패턴/구조 파악 | context-collector | 분석 결과만 받음 |
33
- | 복잡한 계획 수립 | task-planner | 계획 결과만 받음 |
34
- | 영향 분석 | impact-analyzer | 분석 결과만 받음 |
35
- | 코드 리뷰 | code-reviewer | 리뷰 결과만 받음 |
36
- | 테스트/빌드 검증 | qa-tester | 검증 결과만 받음 |
37
- | 단순 수정 (lint/build 오류, 오타, 설정값) | simple-code-writer | Main이 직접 수정하지 않음 |
38
- | 여러 파일 코드 작성 | code-writer / designer | 구현 결과만 받음 |
39
- | Git 작업 | git-manager | 커밋/PR 결과만 받음 |
28
+ 아래 PART 2의 "사용 가능한 Agents" 목록에서 각 Agent description을 확인하고,
29
+ 작업에 적합한 Agent에 위임하세요. 각 Agent의 description에 위임 이유가 포함되어 있습니다.
40
30
 
41
31
  ### ❌ 절대 금지 (Main Agent에서 직접 수행 금지)
42
32
 
@@ -0,0 +1,152 @@
1
+ ---
2
+ name: ContextGeneration
3
+ description: PR 변경 내용을 분석하여 .claude/context/ 문서를 자동 생성하는 규칙
4
+ keywords: [context, codebase, business, PR, 자동생성, 문서화]
5
+ estimated_tokens: ~800
6
+ ---
7
+
8
+ # Context 자동 생성 규칙
9
+
10
+ PR 변경 내용을 분석하여 `.claude/context/` 하위에 codebase/business 문서를 자동 생성합니다.
11
+
12
+ ## Context 디렉토리 구조
13
+
14
+ ```
15
+ .claude/context/
16
+ ├── codebase/
17
+ │ ├── INDEX.md # 모듈 목록 + 경로
18
+ │ └── <module-name>.md # 모듈별 구현 참조
19
+ └── business/
20
+ ├── INDEX.md # 프로젝트 개요 + 도메인 목록
21
+ └── <domain-area>.md # 비즈니스 레벨 요약
22
+ ```
23
+
24
+ ## Codebase Context 규칙
25
+
26
+ ### 파일명
27
+ - **kebab-case** 사용 (예: `cli.md`, `copy-logic.md`, `auth-middleware.md`)
28
+ - 모듈/기능 단위로 분리
29
+
30
+ ### 필수 섹션
31
+
32
+ ```markdown
33
+ ---
34
+ name: <모듈명>
35
+ description: <한 줄 설명>
36
+ keywords: [관련, 키워드]
37
+ ---
38
+
39
+ # <모듈명>
40
+
41
+ <2-3문장 개요>
42
+
43
+ ## 파일 구조
44
+
45
+ | 파일 | 역할 | 핵심 함수/클래스 |
46
+ |------|------|-----------------|
47
+ | src/example.ts | 메인 로직 | mainFunction(), HelperClass |
48
+
49
+ ## 핵심 흐름
50
+
51
+ 1. <진입점> → <처리> → <결과>
52
+ 2. ...
53
+
54
+ ## 관련 Business Context
55
+
56
+ - [<도메인명>](../business/<domain>.md)
57
+ ```
58
+
59
+ ### 금지사항
60
+
61
+ - **원본 코드 포함 절대 금지** (코드 블록으로 소스 코드를 복사하지 않음)
62
+ - 파일 경로와 함수/클래스명만 참조
63
+ - 파일 참조 형식: `| src/copy.ts | 파일 복사 메인 로직 | mergeSettingsJson() |`
64
+
65
+ ## Business Context 규칙
66
+
67
+ ### 파일명
68
+ - **비즈니스 도메인 기준** (예: `configuration-management.md`, `user-authentication.md`)
69
+ - 기술 용어 금지 (예: `settings-json-merge.md` ❌ → `configuration-management.md` ✅)
70
+
71
+ ### 필수 섹션
72
+
73
+ ```markdown
74
+ ---
75
+ name: <도메인명>
76
+ description: <비즈니스 관점 한 줄 설명>
77
+ keywords: [비즈니스, 키워드]
78
+ ---
79
+
80
+ # <도메인명>
81
+
82
+ ## 목적
83
+
84
+ <이 기능이 사용자에게 제공하는 가치>
85
+
86
+ ## 핵심 기능
87
+
88
+ | 기능 | 설명 | 사용자 관점 |
89
+ |------|------|------------|
90
+ | 설정 복사 | 템플릿 설정을 사용자 환경에 적용 | 초기 설정 자동화 |
91
+
92
+ ## 사용자 흐름
93
+
94
+ 1. 사용자가 <동작> → <결과>
95
+ 2. ...
96
+
97
+ ## 관련 Codebase Context
98
+
99
+ - [<모듈명>](../codebase/<module>.md)
100
+ ```
101
+
102
+ ### 변환 규칙
103
+ - Codebase의 기술 용어를 비즈니스 관점으로 변환
104
+ - `mergeSettingsJson()` → "기존 설정을 보존하면서 새 설정 적용"
105
+ - `copyClaudeFiles()` → "템플릿 설정을 사용자 환경에 배포"
106
+
107
+ ## INDEX.md 작성 규칙
108
+
109
+ ### codebase/INDEX.md
110
+
111
+ ```markdown
112
+ ---
113
+ name: Codebase Index
114
+ description: 코드베이스 모듈 참조 목록
115
+ ---
116
+
117
+ # Codebase Context Index
118
+
119
+ ## 모듈 목록
120
+
121
+ | 모듈 | 설명 | 문서 |
122
+ |------|------|------|
123
+ | CLI | 커맨드라인 인터페이스 | [cli.md](./cli.md) |
124
+ ```
125
+
126
+ ### business/INDEX.md
127
+
128
+ ```markdown
129
+ ---
130
+ name: Business Index
131
+ description: 비즈니스 도메인 참조 목록
132
+ ---
133
+
134
+ # Business Context Index
135
+
136
+ ## 프로젝트 개요
137
+
138
+ <프로젝트가 해결하는 문제와 대상 사용자 1-2문장>
139
+
140
+ ## 도메인 목록
141
+
142
+ | 도메인 | 설명 | 문서 |
143
+ |--------|------|------|
144
+ | 설정 관리 | 사용자 설정 배포 및 관리 | [configuration-management.md](./configuration-management.md) |
145
+ ```
146
+
147
+ ## 증분 업데이트 원칙
148
+
149
+ - PR에서 변경된 파일만 해당하는 context 문서를 업데이트
150
+ - 전체 재생성 금지 -- 기존 문서의 변경되지 않은 부분은 유지
151
+ - 새 모듈이 추가되면 INDEX.md에 행 추가
152
+ - 모듈이 삭제되면 INDEX.md에서 해당 행 제거 및 문서 파일 삭제
@@ -0,0 +1,52 @@
1
+ name: Context Auto-Generation
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize]
6
+ paths-ignore:
7
+ - '.claude/context/**'
8
+
9
+ permissions:
10
+ contents: write
11
+ pull-requests: write
12
+ id-token: write
13
+
14
+ jobs:
15
+ generate-context:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Checkout PR branch
19
+ uses: actions/checkout@v4
20
+ with:
21
+ ref: ${{ github.head_ref }}
22
+ fetch-depth: 0
23
+
24
+ - name: Generate context documents
25
+ uses: anthropics/claude-code-action@v1
26
+ with:
27
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
28
+ prompt: |
29
+ 당신은 context-generator 에이전트입니다.
30
+ .claude/agents/context-generator.md의 에이전트 정의와
31
+ .claude/skills/ContextGeneration/SKILL.md의 스킬 가이드를 읽고 정확히 따르세요.
32
+
33
+ PR diff를 분석하고 .claude/context/ 아래에 컨텍스트 문서를 생성/업데이트하세요.
34
+
35
+ 단계:
36
+ 1. `git diff HEAD~1 --name-only`을 실행하여 변경된 파일 목록 가져오기
37
+ 2. 변경된 각 모듈에 대해 .claude/context/codebase/<module>.md 생성 또는 업데이트
38
+ 3. 영향을 받는 각 비즈니스 도메인에 대해 .claude/context/business/<domain>.md 생성 또는 업데이트
39
+ 4. 두 디렉토리의 INDEX.md 파일 업데이트
40
+ 5. "docs: update context for PR changes" 메시지로 변경사항 커밋
41
+
42
+ 중요사항:
43
+ - 컨텍스트 문서에 소스 코드를 포함하지 말고, 파일 경로와 함수 이름만 포함하세요
44
+ - 실제로 변경된 파일에 대해서만 컨텍스트 업데이트
45
+ - ContextGeneration 스킬에 명시된 정확한 형식 따르기
46
+
47
+ - name: Commit and push context changes
48
+ run: |
49
+ git config user.name "github-actions[bot]"
50
+ git config user.email "github-actions[bot]@users.noreply.github.com"
51
+ git add .claude/context/
52
+ git diff --staged --quiet || (git commit -m "docs: context 문서 자동 업데이트" && git push)
File without changes
File without changes
File without changes