@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.
- package/bin/cli.js +143 -13
- 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('비대화형 환경이 감지되었습니다. 기본값(
|
|
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
|
-
|
|
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
|
-
|
|
207
|
+
if (existingFolders.length > 0) {
|
|
208
|
+
console.log('기존 설치 폴더가 발견되었습니다:');
|
|
209
|
+
existingFolders.forEach(folder => {
|
|
210
|
+
console.log(` - ${folder}/`);
|
|
211
|
+
});
|
|
212
|
+
console.log('');
|
|
101
213
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
242
|
+
// 폴더 설치
|
|
243
|
+
installFolders(installMode);
|
|
114
244
|
|
|
115
245
|
console.log('');
|
|
116
246
|
console.log('.claude/ 폴더가 성공적으로 설치되었습니다!');
|