ccsetup 1.0.4 → 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.
package/README.md CHANGED
@@ -99,7 +99,6 @@ After setting up your project with `ccsetup`:
99
99
  - Pre-configured project structure for Claude Code
100
100
  - Multiple specialized agents for different tasks
101
101
  - Built-in ticket and planning system
102
- - Git repository initialization
103
102
  - Ready-to-use boilerplate
104
103
 
105
104
  ## Credits
@@ -2,52 +2,207 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { execSync } = require('child_process');
5
+ const readline = require('readline');
6
6
 
7
7
  const projectName = process.argv[2] || '.';
8
8
  const targetDir = path.resolve(process.cwd(), projectName);
9
9
  const templateDir = path.join(__dirname, '..', 'template');
10
10
 
11
- console.log(`Creating Claude Code project in ${targetDir}...`);
11
+ const rl = readline.createInterface({
12
+ input: process.stdin,
13
+ output: process.stdout
14
+ });
12
15
 
13
- if (projectName !== '.') {
14
- if (!fs.existsSync(targetDir)) {
15
- fs.mkdirSync(targetDir, { recursive: true });
16
- }
16
+ function prompt(question) {
17
+ return new Promise((resolve) => {
18
+ rl.question(question, (answer) => {
19
+ resolve(answer.toLowerCase().trim());
20
+ });
21
+ });
17
22
  }
18
23
 
19
- function copyRecursive(src, dest) {
20
- const exists = fs.existsSync(src);
21
- const stats = exists && fs.statSync(src);
22
- 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';
23
31
 
24
- if (isDirectory) {
25
- if (!fs.existsSync(dest)) {
26
- 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 });
27
41
  }
28
- fs.readdirSync(src).forEach(childItem => {
29
- copyRecursive(path.join(src, childItem), path.join(dest, childItem));
30
- });
31
- } else {
32
- fs.copyFileSync(src, dest);
33
42
  }
34
- }
35
43
 
36
- copyRecursive(templateDir, targetDir);
44
+ const fileConflicts = [];
45
+ const dirConflicts = [];
46
+ const allItems = [];
37
47
 
38
- if (fs.existsSync(path.join(targetDir, '.git'))) {
39
- console.log('Git repository already exists, skipping git init...');
40
- } else {
41
- console.log('Initializing git repository...');
42
- execSync('git init', { cwd: targetDir, stdio: 'inherit' });
43
- }
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
+ }
124
+ }
125
+ }
44
126
 
45
- console.log('\n✅ Claude Code project created successfully!');
46
- console.log('\nNext steps:');
47
- if (projectName !== '.') {
48
- console.log(` cd ${projectName}`);
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
+ }
174
+
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();
49
202
  }
50
- console.log(' 1. Edit CLAUDE.md to add your project-specific instructions');
51
- console.log(' 2. Update docs/ROADMAP.md with your project goals');
52
- console.log(' 3. Start creating tickets in the tickets/ directory');
53
- 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.4",
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"