@yeongjaeyou/claude-code-config 0.1.1 → 0.1.2

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 (2) hide show
  1. package/bin/cli.js +143 -13
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -8,6 +8,9 @@ const readline = require('readline');
8
8
  const pkg = require('../package.json');
9
9
  const args = process.argv.slice(2);
10
10
 
11
+ // 설치 대상 폴더 (사용자 데이터가 아닌 것들만)
12
+ const INSTALL_FOLDERS = ['commands', 'agents', 'skills'];
13
+
11
14
  // 옵션 파싱
12
15
  const isGlobal = args.includes('--global') || args.includes('-g');
13
16
  const showHelp = args.includes('--help') || args.includes('-h');
@@ -35,6 +38,14 @@ Claude Code Config v${pkg.version}
35
38
  예시:
36
39
  npx @yeongjaeyou/claude-code-config # 현재 프로젝트에 설치
37
40
  npx @yeongjaeyou/claude-code-config --global # 전역 설치
41
+
42
+ 설치되는 폴더:
43
+ - commands/ : 슬래시 커맨드
44
+ - agents/ : 커스텀 에이전트
45
+ - skills/ : 스킬 (재사용 가능한 도구 모음)
46
+
47
+ 참고:
48
+ --global 설치 시 기존 사용자 데이터(settings.json, history.jsonl 등)는 보존됩니다.
38
49
  `);
39
50
  process.exit(0);
40
51
  }
@@ -52,8 +63,8 @@ const dest = isGlobal
52
63
  function askQuestion(question) {
53
64
  // 비대화형 환경 감지 (CI/CD, 파이프라인 등)
54
65
  if (!process.stdin.isTTY) {
55
- console.log('비대화형 환경이 감지되었습니다. 기본값(Y)을 사용합니다.');
56
- return Promise.resolve('');
66
+ console.log('비대화형 환경이 감지되었습니다. 기본값(merge)을 사용합니다.');
67
+ return Promise.resolve('merge');
57
68
  }
58
69
 
59
70
  const rl = readline.createInterface({
@@ -69,6 +80,91 @@ function askQuestion(question) {
69
80
  });
70
81
  }
71
82
 
83
+ /**
84
+ * 기존 설치 폴더 확인
85
+ * @returns {string[]} - 존재하는 폴더 목록
86
+ */
87
+ function checkExistingFolders() {
88
+ const existing = [];
89
+ for (const folder of INSTALL_FOLDERS) {
90
+ const folderPath = path.join(dest, folder);
91
+ if (fs.existsSync(folderPath)) {
92
+ existing.push(folder);
93
+ }
94
+ }
95
+ return existing;
96
+ }
97
+
98
+ /**
99
+ * 폴더 복사 (재귀적)
100
+ * @param {string} src - 소스 경로
101
+ * @param {string} dst - 대상 경로
102
+ * @param {boolean} mergeMode - 병합 모드 여부
103
+ */
104
+ function copyFolder(src, dst, mergeMode = false) {
105
+ if (!fs.existsSync(src)) {
106
+ return;
107
+ }
108
+
109
+ // 대상 폴더 생성
110
+ if (!fs.existsSync(dst)) {
111
+ try {
112
+ fs.mkdirSync(dst, { recursive: true });
113
+ } catch (err) {
114
+ throw new Error(`폴더 생성 실패: ${dst} - ${err.message}`);
115
+ }
116
+ }
117
+
118
+ const entries = fs.readdirSync(src, { withFileTypes: true });
119
+
120
+ for (const entry of entries) {
121
+ const srcPath = path.join(src, entry.name);
122
+ const dstPath = path.join(dst, entry.name);
123
+
124
+ if (entry.isDirectory()) {
125
+ copyFolder(srcPath, dstPath, mergeMode);
126
+ } else {
127
+ // 병합 모드에서는 기존 파일 유지
128
+ if (mergeMode && fs.existsSync(dstPath)) {
129
+ continue;
130
+ }
131
+ try {
132
+ fs.copyFileSync(srcPath, dstPath);
133
+ } catch (err) {
134
+ throw new Error(`파일 복사 실패: ${srcPath} -> ${dstPath} - ${err.message}`);
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * 설치 대상 폴더만 선택적으로 복사
142
+ * @param {string} mode - 'merge' | 'overwrite'
143
+ */
144
+ function installFolders(mode) {
145
+ const mergeMode = mode === 'merge';
146
+
147
+ for (const folder of INSTALL_FOLDERS) {
148
+ const srcFolder = path.join(source, folder);
149
+ const dstFolder = path.join(dest, folder);
150
+
151
+ if (!fs.existsSync(srcFolder)) {
152
+ continue;
153
+ }
154
+
155
+ // 덮어쓰기 모드에서는 기존 폴더 삭제 후 복사
156
+ if (!mergeMode && fs.existsSync(dstFolder)) {
157
+ try {
158
+ fs.rmSync(dstFolder, { recursive: true });
159
+ } catch (err) {
160
+ throw new Error(`폴더 삭제 실패: ${dstFolder} - ${err.message}`);
161
+ }
162
+ }
163
+
164
+ copyFolder(srcFolder, dstFolder, mergeMode);
165
+ }
166
+ }
167
+
72
168
  /**
73
169
  * 메인 함수
74
170
  */
@@ -93,24 +189,58 @@ async function main() {
93
189
  console.log(`설치 경로: ${dest}`);
94
190
  console.log('');
95
191
 
96
- // 대상 폴더가 이미 존재하는 경우
97
- if (fs.existsSync(dest)) {
98
- console.log('기존 .claude/ 폴더가 발견되었습니다.');
192
+ // 대상 폴더 생성 (없으면)
193
+ if (!fs.existsSync(dest)) {
194
+ try {
195
+ fs.mkdirSync(dest, { recursive: true });
196
+ } catch (err) {
197
+ console.error(`오류: 대상 폴더를 생성할 수 없습니다: ${dest}`);
198
+ console.error(`상세: ${err.message}`);
199
+ process.exit(1);
200
+ }
201
+ }
202
+
203
+ // 기존 설치 폴더 확인
204
+ const existingFolders = checkExistingFolders();
205
+ let installMode = 'overwrite';
99
206
 
100
- const answer = await askQuestion('덮어쓰시겠습니까? (Y/n): ');
207
+ if (existingFolders.length > 0) {
208
+ console.log('기존 설치 폴더가 발견되었습니다:');
209
+ existingFolders.forEach(folder => {
210
+ console.log(` - ${folder}/`);
211
+ });
212
+ console.log('');
101
213
 
102
- // 빈 값(Enter)이거나 y/Y면 덮어쓰기
103
- if (answer === '' || answer === 'y') {
104
- fs.rmSync(dest, { recursive: true });
105
- console.log('기존 폴더를 삭제했습니다.');
106
- } else {
214
+ if (isGlobal) {
215
+ console.log('(사용자 데이터는 보존됩니다: settings.json, history.jsonl 등)');
216
+ console.log('');
217
+ }
218
+
219
+ console.log('설치 옵션:');
220
+ console.log(' [m] merge - 새 파일만 추가 (기존 파일 유지)');
221
+ console.log(' [o] overwrite - 위 폴더들만 덮어쓰기');
222
+ console.log(' [c] cancel - 설치 취소');
223
+ console.log('');
224
+
225
+ const answer = await askQuestion('선택하세요 (m/o/c) [기본: m]: ');
226
+
227
+ if (answer === 'c' || answer === 'cancel') {
107
228
  console.log('설치가 취소되었습니다.');
108
229
  process.exit(0);
230
+ } else if (answer === 'o' || answer === 'overwrite') {
231
+ installMode = 'overwrite';
232
+ console.log('');
233
+ console.log('덮어쓰기 모드로 설치합니다...');
234
+ } else {
235
+ // 기본값: merge (빈 값, 'm', 'merge' 등)
236
+ installMode = 'merge';
237
+ console.log('');
238
+ console.log('병합 모드로 설치합니다 (기존 파일 유지)...');
109
239
  }
110
240
  }
111
241
 
112
- // 폴더 복사
113
- fs.cpSync(source, dest, { recursive: true });
242
+ // 폴더 설치
243
+ installFolders(installMode);
114
244
 
115
245
  console.log('');
116
246
  console.log('.claude/ 폴더가 성공적으로 설치되었습니다!');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeongjaeyou/claude-code-config",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Claude Code CLI custom commands, agents, and skills",
5
5
  "bin": {
6
6
  "claude-code-config": "./bin/cli.js"