ccsetup 1.0.5 → 1.0.6

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/create-project.js +190 -27
  2. package/package.json +1 -1
@@ -2,44 +2,207 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
+ const readline = require('readline');
5
6
 
6
7
  const projectName = process.argv[2] || '.';
7
8
  const targetDir = path.resolve(process.cwd(), projectName);
8
9
  const templateDir = path.join(__dirname, '..', 'template');
9
10
 
10
- console.log(`Creating Claude Code project in ${targetDir}...`);
11
+ const rl = readline.createInterface({
12
+ input: process.stdin,
13
+ output: process.stdout
14
+ });
11
15
 
12
- if (projectName !== '.') {
13
- if (!fs.existsSync(targetDir)) {
14
- fs.mkdirSync(targetDir, { recursive: true });
15
- }
16
+ function prompt(question) {
17
+ return new Promise((resolve) => {
18
+ rl.question(question, (answer) => {
19
+ resolve(answer.toLowerCase().trim());
20
+ });
21
+ });
16
22
  }
17
23
 
18
- function copyRecursive(src, dest) {
19
- const exists = fs.existsSync(src);
20
- const stats = exists && fs.statSync(src);
21
- const isDirectory = exists && stats.isDirectory();
24
+ function normalizeConflictStrategy(input) {
25
+ const normalized = input.toLowerCase().trim();
26
+
27
+ // Accept abbreviations and variations
28
+ if (normalized === 's' || normalized === 'skip' || normalized === '1') return 'skip';
29
+ if (normalized === 'r' || normalized === 'rename' || normalized === '2') return 'rename';
30
+ if (normalized === 'o' || normalized === 'overwrite' || normalized === '3') return 'overwrite';
22
31
 
23
- if (isDirectory) {
24
- if (!fs.existsSync(dest)) {
25
- fs.mkdirSync(dest, { recursive: true });
32
+ return null;
33
+ }
34
+
35
+ async function main() {
36
+ console.log(`Creating Claude Code project in ${targetDir}...`);
37
+
38
+ if (projectName !== '.') {
39
+ if (!fs.existsSync(targetDir)) {
40
+ fs.mkdirSync(targetDir, { recursive: true });
41
+ }
42
+ }
43
+
44
+ const fileConflicts = [];
45
+ const dirConflicts = [];
46
+ const allItems = [];
47
+
48
+ function scanTemplate(src, dest, relativePath = '') {
49
+ const exists = fs.existsSync(src);
50
+ const stats = exists && fs.statSync(src);
51
+ const isDirectory = exists && stats.isDirectory();
52
+
53
+ if (isDirectory) {
54
+ allItems.push({
55
+ src,
56
+ dest,
57
+ type: 'directory',
58
+ relativePath,
59
+ exists: fs.existsSync(dest)
60
+ });
61
+
62
+ if (fs.existsSync(dest)) {
63
+ dirConflicts.push(relativePath || '.');
64
+ }
65
+
66
+ fs.readdirSync(src).forEach(childItem => {
67
+ scanTemplate(
68
+ path.join(src, childItem),
69
+ path.join(dest, childItem),
70
+ path.join(relativePath, childItem)
71
+ );
72
+ });
73
+ } else {
74
+ allItems.push({
75
+ src,
76
+ dest,
77
+ type: 'file',
78
+ relativePath,
79
+ exists: fs.existsSync(dest)
80
+ });
81
+
82
+ if (fs.existsSync(dest)) {
83
+ fileConflicts.push(relativePath);
84
+ }
85
+ }
86
+ }
87
+
88
+ scanTemplate(templateDir, targetDir);
89
+
90
+ let conflictStrategy = 'skip';
91
+
92
+ if (dirConflicts.length > 0) {
93
+ console.log('\n⚠️ The following directories already exist:');
94
+ dirConflicts.forEach(dir => console.log(` - ${dir}/`));
95
+ }
96
+
97
+ if (fileConflicts.length > 0) {
98
+ console.log('\n⚠️ The following files already exist:');
99
+ fileConflicts.forEach(file => console.log(` - ${file}`));
100
+
101
+ console.log('\n📋 This choice will apply to ALL conflicting files listed above.');
102
+ console.log('\nConflict resolution options:');
103
+ console.log(' 1) skip (s) - Keep your existing files, only copy new files');
104
+ console.log(' 2) rename (r) - Keep your files, save template files with -ccsetup suffix');
105
+ console.log(' 3) overwrite (o) - Replace ALL existing files with template versions');
106
+ console.log('\nExamples: type "skip", "s", or "1" for the first option');
107
+
108
+ const userInput = await prompt('\nYour choice [skip/rename/overwrite or s/r/o]: ');
109
+ conflictStrategy = normalizeConflictStrategy(userInput);
110
+
111
+ if (!conflictStrategy) {
112
+ console.log(`\n❌ Invalid option: "${userInput}". Please use: skip/s/1, rename/r/2, or overwrite/o/3`);
113
+ rl.close();
114
+ process.exit(1);
115
+ }
116
+
117
+ if (conflictStrategy === 'overwrite') {
118
+ const confirm = await prompt('⚠️ Are you sure you want to overwrite existing files? This cannot be undone! (yes/no): ');
119
+ if (confirm !== 'yes') {
120
+ console.log('Operation cancelled.');
121
+ rl.close();
122
+ process.exit(0);
123
+ }
26
124
  }
27
- fs.readdirSync(src).forEach(childItem => {
28
- copyRecursive(path.join(src, childItem), path.join(dest, childItem));
29
- });
30
- } else {
31
- fs.copyFileSync(src, dest);
32
125
  }
33
- }
34
126
 
35
- copyRecursive(templateDir, targetDir);
127
+ const strategyDescriptions = {
128
+ skip: 'Keeping all existing files, copying only new files',
129
+ rename: 'Keeping existing files, saving templates with -ccsetup suffix',
130
+ overwrite: 'Replacing existing files with template versions'
131
+ };
132
+
133
+ console.log(`\n✨ ${strategyDescriptions[conflictStrategy]}...`);
134
+
135
+ let skippedCount = 0;
136
+ let copiedCount = 0;
137
+ let renamedCount = 0;
138
+ let overwrittenCount = 0;
139
+
140
+ for (const item of allItems) {
141
+ if (item.type === 'directory') {
142
+ if (!item.exists && !fs.existsSync(item.dest)) {
143
+ fs.mkdirSync(item.dest, { recursive: true });
144
+ }
145
+ } else {
146
+ if (item.exists) {
147
+ if (conflictStrategy === 'skip') {
148
+ skippedCount++;
149
+ continue;
150
+ } else if (conflictStrategy === 'rename') {
151
+ const ext = path.extname(item.dest);
152
+ const baseName = path.basename(item.dest, ext);
153
+ const dirName = path.dirname(item.dest);
154
+ let newDest = path.join(dirName, `${baseName}-ccsetup${ext}`);
155
+ let counter = 1;
156
+ while (fs.existsSync(newDest)) {
157
+ newDest = path.join(dirName, `${baseName}-ccsetup-${counter}${ext}`);
158
+ counter++;
159
+ }
160
+ fs.copyFileSync(item.src, newDest);
161
+ renamedCount++;
162
+ console.log(` 📄 Created: ${path.relative(targetDir, newDest)}`);
163
+ } else if (conflictStrategy === 'overwrite') {
164
+ fs.copyFileSync(item.src, item.dest);
165
+ overwrittenCount++;
166
+ console.log(` ♻️ Replaced: ${item.relativePath}`);
167
+ }
168
+ } else {
169
+ fs.copyFileSync(item.src, item.dest);
170
+ copiedCount++;
171
+ }
172
+ }
173
+ }
36
174
 
37
- console.log('\n✅ Claude Code project created successfully!');
38
- console.log('\nNext steps:');
39
- if (projectName !== '.') {
40
- console.log(` cd ${projectName}`);
175
+ console.log('\n✅ Claude Code project created successfully!');
176
+
177
+ // Show summary of what happened
178
+ if (fileConflicts.length > 0 || copiedCount > 0) {
179
+ console.log('\n📊 Summary:');
180
+ if (copiedCount > 0) console.log(` ✨ ${copiedCount} new files copied`);
181
+ if (skippedCount > 0) console.log(` ⏭️ ${skippedCount} existing files kept unchanged`);
182
+ if (renamedCount > 0) console.log(` 📄 ${renamedCount} template files saved with -ccsetup suffix`);
183
+ if (overwrittenCount > 0) console.log(` ♻️ ${overwrittenCount} files replaced with template versions`);
184
+ }
185
+
186
+ console.log('\nNext steps:');
187
+ if (projectName !== '.') {
188
+ console.log(` cd ${projectName}`);
189
+ }
190
+ console.log(' 1. Edit CLAUDE.md to add your project-specific instructions');
191
+ console.log(' 2. Update docs/ROADMAP.md with your project goals');
192
+ console.log(' 3. Start creating tickets in the tickets/ directory');
193
+
194
+ if (fileConflicts.length > 0 && conflictStrategy === 'rename') {
195
+ console.log('\n💡 Tip: Review the -ccsetup files to see template examples');
196
+ console.log(' You can compare them with your existing files or copy sections you need');
197
+ }
198
+
199
+ console.log('\nHappy coding with Claude! 🎉');
200
+
201
+ rl.close();
41
202
  }
42
- console.log(' 1. Edit CLAUDE.md to add your project-specific instructions');
43
- console.log(' 2. Update docs/ROADMAP.md with your project goals');
44
- console.log(' 3. Start creating tickets in the tickets/ directory');
45
- console.log('\nHappy coding with Claude! 🎉');
203
+
204
+ main().catch(err => {
205
+ console.error('Error:', err);
206
+ rl.close();
207
+ process.exit(1);
208
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccsetup",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Boilerplate for Claude Code projects with agents, tickets, and plans",
5
5
  "bin": {
6
6
  "ccsetup": "./bin/create-project.js"