package-installer-cli 1.2.0 → 1.3.0

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.
@@ -5,37 +5,56 @@ import chalk from 'chalk';
5
5
  import ora from 'ora';
6
6
  import fs from 'fs-extra';
7
7
  import path from 'path';
8
- import { displaySuccessMessage } from '../utils/dashboard.js';
8
+ import { createStandardHelp } from '../utils/helpFormatter.js';
9
9
  /**
10
10
  * Display help for clean command
11
11
  */
12
12
  export function showCleanHelp() {
13
- console.clear();
14
- console.log(chalk.hex('#9c88ff')('🧹 CLEAN COMMAND HELP\n'));
15
- console.log(chalk.hex('#00d2d3')('Usage:'));
16
- console.log(chalk.white(' pi clean [options]'));
17
- console.log(chalk.white(' pi cleanup [options]') + chalk.gray(' (alias)\n'));
18
- console.log(chalk.hex('#00d2d3')('Description:'));
19
- console.log(chalk.white(' Clean development artifacts, caches, and temporary files'));
20
- console.log(chalk.white(' Safely removes common build outputs and dependency caches\n'));
21
- console.log(chalk.hex('#00d2d3')('Options:'));
22
- console.log(chalk.white(' --node-modules') + chalk.gray(' Clean node_modules directories'));
23
- console.log(chalk.white(' --build') + chalk.gray(' Clean build/dist directories'));
24
- console.log(chalk.white(' --cache') + chalk.gray(' Clean package manager caches'));
25
- console.log(chalk.white(' --logs') + chalk.gray(' Clean log files'));
26
- console.log(chalk.white(' --all') + chalk.gray(' Clean everything (safe)'));
27
- console.log(chalk.white(' --deep') + chalk.gray(' Deep clean (includes lock files)'));
28
- console.log(chalk.white(' --dry-run') + chalk.gray(' Preview what would be cleaned'));
29
- console.log(chalk.white(' -h, --help') + chalk.gray(' Show this help message\n'));
30
- console.log(chalk.hex('#00d2d3')('Examples:'));
31
- console.log(chalk.gray(' # Clean build directories'));
32
- console.log(chalk.white(' pi clean --build\n'));
33
- console.log(chalk.gray(' # Clean node_modules'));
34
- console.log(chalk.white(' pi clean --node-modules\n'));
35
- console.log(chalk.gray(' # Preview clean operation'));
36
- console.log(chalk.white(' pi clean --all --dry-run\n'));
37
- console.log(chalk.gray(' # Deep clean with lock files'));
38
- console.log(chalk.white(' pi clean --deep\n'));
13
+ const helpConfig = {
14
+ commandName: 'Clean',
15
+ emoji: '🧹',
16
+ description: 'Clean development artifacts, caches, and temporary files.\nSafely removes common build outputs, dependency caches, and temporary files to free up disk space and clean your project.',
17
+ usage: [
18
+ 'clean [options]',
19
+ 'cleanup [options] # alias'
20
+ ],
21
+ options: [
22
+ { flag: '--node-modules', description: 'Clean node_modules directories' },
23
+ { flag: '--build', description: 'Clean build/dist directories' },
24
+ { flag: '--cache', description: 'Clean package manager caches' },
25
+ { flag: '--logs', description: 'Clean log files and debug outputs' },
26
+ { flag: '--all', description: 'Clean everything (safe operation)' },
27
+ { flag: '--deep', description: 'Deep clean (includes lock files)' },
28
+ { flag: '--dry-run', description: 'Preview what would be cleaned' },
29
+ { flag: '-h, --help', description: 'Show this help message' }
30
+ ],
31
+ examples: [
32
+ { command: 'clean --build', description: 'Clean build directories only' },
33
+ { command: 'clean --node-modules', description: 'Clean node_modules directories' },
34
+ { command: 'clean --all --dry-run', description: 'Preview what would be cleaned' },
35
+ { command: 'clean --deep', description: 'Deep clean with lock files' },
36
+ { command: 'clean --cache', description: 'Clean package manager caches' },
37
+ { command: 'cleanup --all', description: 'Use alias command' }
38
+ ],
39
+ additionalSections: [
40
+ {
41
+ title: 'Clean Targets',
42
+ items: [
43
+ 'Build Outputs: dist, build, .next, out, target',
44
+ 'Dependencies: node_modules, .pnpm-store',
45
+ 'Caches: .cache, .npm, .yarn, __pycache__',
46
+ 'Logs: *.log, npm-debug.log, yarn-error.log',
47
+ 'Temp Files: .DS_Store, Thumbs.db, *.tmp'
48
+ ]
49
+ }
50
+ ],
51
+ tips: [
52
+ 'Always use --dry-run first to preview changes',
53
+ 'Deep clean removes lock files and requires dependency reinstall',
54
+ 'Use --cache to clean package manager caches for more space'
55
+ ]
56
+ };
57
+ createStandardHelp(helpConfig);
39
58
  }
40
59
  /**
41
60
  * Main clean command function
@@ -46,63 +65,62 @@ export async function cleanCommand(options = {}) {
46
65
  showCleanHelp();
47
66
  return;
48
67
  }
49
- // Blue gradient banner with "CLEANER" on next line
50
68
  console.clear();
51
- const banner = `\n${chalk.bgHex('#00c6ff').hex('#fff').bold(' PROJECT ')}${chalk.bgHex('#0072ff').hex('#fff').bold(' CLEAN ')}\n${chalk.bgHex('#00c6ff').hex('#fff').bold(' ER ')}\n`;
52
- console.log(banner);
69
+ console.log(chalk.hex('#ffa502')('🧹 Project Cleaner\n'));
53
70
  const projectPath = process.cwd();
54
- // Improved flag logic
55
- const cleanTargets = [];
56
- if (options['all']) {
57
- cleanTargets.push('node-modules', 'build', 'cache', 'logs');
58
- if (options['deep'])
59
- cleanTargets.push('lock-files');
60
- }
61
- else {
62
- if (options['node-modules'])
63
- cleanTargets.push('node-modules');
64
- if (options['build'])
65
- cleanTargets.push('build');
66
- if (options['cache'])
67
- cleanTargets.push('cache');
68
- if (options['logs'])
69
- cleanTargets.push('logs');
70
- if (options['deep'])
71
- cleanTargets.push('lock-files');
72
- }
73
- if (cleanTargets.length === 0) {
74
- console.log(chalk.yellow('No clean targets specified. Use --help for options.'));
71
+ const isDryRun = options['dryRun'] || options['dry-run'];
72
+ // Determine what to clean based on flags
73
+ const targets = determineCleanTargets(options);
74
+ if (targets.length === 0) {
75
+ console.log(chalk.yellow('⚠️ No clean targets specified. Use --help for available options.'));
76
+ console.log(chalk.gray('💡 Tip: Use --all for a safe clean of common artifacts'));
75
77
  return;
76
78
  }
77
- if (options['dry-run']) {
78
- console.log(chalk.yellow('🔍 DRY RUN - Showing what would be cleaned:\n'));
79
+ if (isDryRun) {
80
+ console.log(chalk.cyan('🔍 DRY RUN - Preview of what would be cleaned:\n'));
81
+ }
82
+ else {
83
+ console.log(chalk.cyan('🧹 Starting cleanup process...\n'));
79
84
  }
80
- const spinner = ora(chalk.hex('#9c88ff')('🧹 Cleaning project...')).start();
85
+ const spinner = ora(chalk.hex('#ffa502')(isDryRun ? 'Analyzing files...' : 'Cleaning project...')).start();
81
86
  try {
82
- let totalCleaned = 0;
87
+ let totalSize = 0;
83
88
  const results = [];
84
- for (const target of cleanTargets) {
85
- // ...existing code for cleaning each target...
86
- // Simulate cleaning for dry-run
87
- const size = 1024 * Math.floor(Math.random() * 10 + 1); // Dummy size
88
- if (size > 0) {
89
- totalCleaned += size;
90
- results.push(`${target}: ${size} bytes`);
89
+ let itemsCleaned = 0;
90
+ for (const target of targets) {
91
+ spinner.text = `${isDryRun ? 'Analyzing' : 'Cleaning'} ${target.name}...`;
92
+ const targetSize = await cleanTarget(projectPath, target, isDryRun);
93
+ if (targetSize > 0) {
94
+ totalSize += targetSize;
95
+ itemsCleaned++;
96
+ results.push(`${target.name}: ${formatFileSize(targetSize)}`);
91
97
  }
92
98
  }
93
99
  spinner.stop();
94
- if (totalCleaned > 0) {
95
- displaySuccessMessage(options['dry-run'] ? 'Clean preview completed!' : 'Project cleaned successfully!', [
96
- `Total ${options['dry-run'] ? 'would be' : ''} cleaned: ${totalCleaned} bytes`,
97
- ...results
98
- ]);
100
+ if (totalSize > 0) {
101
+ const action = isDryRun ? 'would be cleaned' : 'cleaned';
102
+ console.log(chalk.green(`\n✅ ${isDryRun ? 'Analysis' : 'Cleanup'} completed!`));
103
+ console.log(chalk.white(`📊 Total ${action}: ${chalk.bold(formatFileSize(totalSize))}`));
104
+ console.log(chalk.white(`📁 Items ${action}: ${chalk.bold(itemsCleaned)}`));
105
+ if (results.length > 0) {
106
+ console.log(chalk.cyan('\n📋 Breakdown:'));
107
+ results.forEach(result => {
108
+ console.log(chalk.gray(` • ${result}`));
109
+ });
110
+ }
111
+ if (isDryRun) {
112
+ console.log(chalk.yellow('\n💡 Run without --dry-run to actually clean these files'));
113
+ }
114
+ else {
115
+ console.log(chalk.green('\n🎉 Project successfully cleaned!'));
116
+ }
99
117
  }
100
118
  else {
101
- console.log(chalk.yellow('✨ Nothing to clean - project is already tidy!'));
119
+ console.log(chalk.green('✨ Nothing to clean - project is already tidy!'));
102
120
  }
103
121
  }
104
122
  catch (error) {
105
- spinner.fail(chalk.red('❌ Failed to clean project'));
123
+ spinner.fail(chalk.red(isDryRun ? '❌ Failed to analyze files' : '❌ Failed to clean project'));
106
124
  console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
107
125
  process.exit(1);
108
126
  }
@@ -112,49 +130,59 @@ export async function cleanCommand(options = {}) {
112
130
  */
113
131
  function determineCleanTargets(options) {
114
132
  const targets = [];
115
- if (options.all || options.nodeModules) {
133
+ // Handle --node-modules flag
134
+ if (options.all || options['nodeModules'] || options['node-modules']) {
116
135
  targets.push({
117
136
  name: 'node_modules',
118
- patterns: ['**/node_modules'],
137
+ patterns: ['node_modules', '**/node_modules'],
119
138
  description: 'Node.js dependencies'
120
139
  });
121
140
  }
141
+ // Handle --build flag
122
142
  if (options.all || options.build) {
123
143
  targets.push({
124
144
  name: 'build outputs',
125
- patterns: ['dist', 'build', '.next', 'out', 'target/debug', 'target/release'],
145
+ patterns: ['dist', 'build', '.next', 'out', 'target/debug', 'target/release', '.output', '.nuxt'],
126
146
  description: 'Build outputs and compiled files'
127
147
  });
128
148
  }
149
+ // Handle --cache flag
129
150
  if (options.all || options.cache) {
130
151
  targets.push({
131
- name: 'caches',
132
- patterns: ['.cache', '.npm', '.yarn', '.pnpm-store', '__pycache__'],
152
+ name: 'package manager caches',
153
+ patterns: ['.cache', '.npm', '.yarn', '.pnpm-store', '.pnpm', '__pycache__', '.pytest_cache', 'target/debug/deps', 'target/release/deps'],
133
154
  description: 'Package manager and build caches'
134
155
  });
135
156
  }
157
+ // Handle --logs flag
136
158
  if (options.all || options.logs) {
137
159
  targets.push({
138
- name: 'logs',
139
- patterns: ['*.log', 'logs/**', '.log'],
140
- description: 'Log files'
160
+ name: 'log files',
161
+ patterns: ['*.log', 'logs', 'log', '*.log.*', 'npm-debug.log*', 'yarn-debug.log*', 'yarn-error.log*'],
162
+ description: 'Log files and debug outputs'
141
163
  });
142
164
  }
165
+ // Handle --deep flag (includes lock files)
143
166
  if (options.deep) {
144
167
  targets.push({
145
- name: 'lock files',
146
- patterns: ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'Cargo.lock'],
168
+ name: 'dependency lock files',
169
+ patterns: ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'Cargo.lock', 'Pipfile.lock', 'poetry.lock'],
147
170
  description: 'Dependency lock files (requires reinstall)'
148
171
  });
149
- }
150
- // Default to safe clean if no options specified
151
- if (targets.length === 0) {
172
+ // Add more aggressive cleaning for deep clean
152
173
  targets.push({
153
- name: 'build outputs',
154
- patterns: ['dist', 'build', '.next', 'out'],
155
- description: 'Build outputs (safe to clean)'
174
+ name: 'temporary files',
175
+ patterns: ['.tmp', 'tmp', '.temp', 'temp', '.DS_Store', 'Thumbs.db', '*.tmp', '*.temp'],
176
+ description: 'Temporary files and system artifacts'
156
177
  });
157
178
  }
179
+ // If no specific options are provided and not --all, show available options
180
+ const hasSpecificOption = options['nodeModules'] || options['node-modules'] ||
181
+ options.build || options.cache || options.logs ||
182
+ options.deep || options.all;
183
+ if (!hasSpecificOption) {
184
+ return []; // Return empty to show help message
185
+ }
158
186
  return targets;
159
187
  }
160
188
  /**
@@ -163,22 +191,132 @@ function determineCleanTargets(options) {
163
191
  async function cleanTarget(projectPath, target, dryRun) {
164
192
  let totalSize = 0;
165
193
  for (const pattern of target.patterns) {
166
- const fullPath = path.join(projectPath, pattern);
167
194
  try {
168
- if (await fs.pathExists(fullPath)) {
169
- const stat = await fs.stat(fullPath);
170
- totalSize += await getDirectorySize(fullPath);
171
- if (!dryRun) {
172
- await fs.remove(fullPath);
195
+ // Handle different pattern types
196
+ if (pattern.includes('*')) {
197
+ // Handle glob patterns
198
+ totalSize += await cleanGlobPattern(projectPath, pattern, dryRun);
199
+ }
200
+ else {
201
+ // Handle direct paths
202
+ const fullPath = path.join(projectPath, pattern);
203
+ if (await fs.pathExists(fullPath)) {
204
+ const size = await getDirectorySize(fullPath);
205
+ totalSize += size;
206
+ if (!dryRun && size > 0) {
207
+ await fs.remove(fullPath);
208
+ }
173
209
  }
174
210
  }
175
211
  }
176
212
  catch (error) {
177
- // Ignore permission errors or non-existent paths
213
+ // Silently ignore permission errors or other filesystem issues
214
+ // This is expected behavior for clean operations
215
+ }
216
+ }
217
+ return totalSize;
218
+ }
219
+ /**
220
+ * Clean files matching a glob pattern
221
+ */
222
+ async function cleanGlobPattern(projectPath, pattern, dryRun) {
223
+ let totalSize = 0;
224
+ try {
225
+ // Import glob dynamically
226
+ const { glob } = await import('glob');
227
+ const matches = await glob(pattern, {
228
+ cwd: projectPath,
229
+ absolute: false,
230
+ dot: true,
231
+ ignore: ['node_modules/node_modules/**'] // Avoid nested node_modules issues
232
+ });
233
+ const matchArray = Array.isArray(matches) ? matches : [matches];
234
+ for (const match of matchArray) {
235
+ if (!match)
236
+ continue;
237
+ const fullPath = path.join(projectPath, match);
238
+ try {
239
+ if (await fs.pathExists(fullPath)) {
240
+ const size = await getDirectorySize(fullPath);
241
+ totalSize += size;
242
+ if (!dryRun && size > 0) {
243
+ await fs.remove(fullPath);
244
+ }
245
+ }
246
+ }
247
+ catch (error) {
248
+ // Skip files that can't be accessed
249
+ }
178
250
  }
179
251
  }
252
+ catch (error) {
253
+ // Fallback to simple directory walking for pattern matching
254
+ totalSize += await fallbackPatternMatch(projectPath, pattern, dryRun);
255
+ }
180
256
  return totalSize;
181
257
  }
258
+ /**
259
+ * Fallback pattern matching when glob is not available
260
+ */
261
+ async function fallbackPatternMatch(projectPath, pattern, dryRun) {
262
+ let totalSize = 0;
263
+ // Handle common patterns manually
264
+ if (pattern.includes('**')) {
265
+ // Recursive pattern - search directories
266
+ const basePattern = pattern.replace('**/', '').replace('*', '');
267
+ await walkDirectory(projectPath, async (filePath) => {
268
+ if (filePath.includes(basePattern)) {
269
+ try {
270
+ const size = await getDirectorySize(filePath);
271
+ totalSize += size;
272
+ if (!dryRun && size > 0) {
273
+ await fs.remove(filePath);
274
+ }
275
+ }
276
+ catch (error) {
277
+ // Skip on error
278
+ }
279
+ }
280
+ });
281
+ }
282
+ else {
283
+ // Simple pattern
284
+ const simplePattern = pattern.replace('*', '');
285
+ const fullPath = path.join(projectPath, simplePattern);
286
+ if (await fs.pathExists(fullPath)) {
287
+ const size = await getDirectorySize(fullPath);
288
+ totalSize += size;
289
+ if (!dryRun && size > 0) {
290
+ await fs.remove(fullPath);
291
+ }
292
+ }
293
+ }
294
+ return totalSize;
295
+ }
296
+ /**
297
+ * Walk directory recursively
298
+ */
299
+ async function walkDirectory(dir, callback) {
300
+ try {
301
+ const entries = await fs.readdir(dir, { withFileTypes: true });
302
+ for (const entry of entries) {
303
+ const fullPath = path.join(dir, entry.name);
304
+ if (entry.isDirectory()) {
305
+ await callback(fullPath);
306
+ // Recurse into subdirectory (with depth limit to avoid infinite loops)
307
+ if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {
308
+ await walkDirectory(fullPath, callback);
309
+ }
310
+ }
311
+ else {
312
+ await callback(fullPath);
313
+ }
314
+ }
315
+ }
316
+ catch (error) {
317
+ // Skip directories that can't be read
318
+ }
319
+ }
182
320
  /**
183
321
  * Get directory size recursively
184
322
  */
@@ -1,54 +1,74 @@
1
1
  import chalk from 'chalk';
2
- import gradient from 'gradient-string';
3
- import boxen from 'boxen';
4
2
  import path from 'path';
5
3
  import { cloneRepo as cloneRepoUtil } from '../utils/cloneUtils.js';
6
4
  import { CacheManager } from '../utils/cacheUtils.js';
5
+ import { createStandardHelp } from '../utils/helpFormatter.js';
7
6
  /**
8
- * Display help for clone command
7
+ * Display help for clone command using standardized format
9
8
  */
10
9
  export function showCloneHelp() {
11
- const piGradient = gradient(['#00c6ff', '#0072ff']);
12
- const headerGradient = gradient(['#4facfe', '#00f2fe']);
13
- console.log('\n' + boxen(headerGradient('📥 Clone Command Help') + '\n\n' +
14
- chalk.white('Clone any public repository from GitHub, GitLab, BitBucket, or SourceHut.') + '\n' +
15
- chalk.white('Automatically installs dependencies, creates .env files, and tracks usage.') + '\n\n' +
16
- chalk.cyan('Usage:') + '\n' +
17
- chalk.white(` ${piGradient('pi')} ${chalk.hex('#00d2d3')('clone')} <user/repo> [project-name]`) + '\n\n' +
18
- chalk.cyan('Options:') + '\n' +
19
- chalk.gray(' -h, --help Display help for this command') + '\n' +
20
- chalk.gray(' --offline Use cached templates if available') + '\n' +
21
- chalk.gray(' --no-deps Skip dependency installation') + '\n' +
22
- chalk.gray(' --no-git Skip git initialization') + '\n\n' +
23
- chalk.cyan('Examples:') + '\n' +
24
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#00d2d3')('clone')} facebook/react my-react-copy # Clone from GitHub with custom name`) + '\n' +
25
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#00d2d3')('clone')} gitlab:user/project # Clone from GitLab`) + '\n' +
26
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#00d2d3')('clone')} bitbucket:user/repo # Clone from BitBucket`) + '\n' +
27
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#00d2d3')('clone')} sourcehut:user/repo # Clone from SourceHut`) + '\n' +
28
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#00d2d3')('clone')} user/repo ${chalk.hex('#ff6b6b')('--offline')} # Use cached version if available`) + '\n' +
29
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#00d2d3')('clone')} ${chalk.hex('#ff6b6b')('--help')} # Show this help message`) + '\n\n' +
30
- chalk.hex('#00d2d3')('💡 Supported Platforms:') + '\n' +
31
- chalk.hex('#95afc0')(' • GitHub (default): user/repo') + '\n' +
32
- chalk.hex('#95afc0')(' • GitLab: gitlab:user/repo') + '\n' +
33
- chalk.hex('#95afc0')(' • BitBucket: bitbucket:user/repo') + '\n' +
34
- chalk.hex('#95afc0')(' • SourceHut: sourcehut:user/repo') + '\n\n' +
35
- chalk.hex('#ffa502')('⚡ Features:') + '\n' +
36
- chalk.hex('#95afc0')(' • Automatic dependency installation') + '\n' +
37
- chalk.hex('#95afc0')(' • Environment file creation from templates') + '\n' +
38
- chalk.hex('#95afc0')(' • Git repository initialization') + '\n' +
39
- chalk.hex('#95afc0')(' • Usage tracking and history') + '\n' +
40
- chalk.hex('#95afc0')(' • Offline mode with cached templates'), {
41
- padding: 1,
42
- borderStyle: 'round',
43
- borderColor: 'cyan',
44
- backgroundColor: '#0a0a0a'
45
- }));
10
+ const helpConfig = {
11
+ commandName: 'Clone',
12
+ emoji: '📥',
13
+ description: 'Clone any public repository from GitHub, GitLab, BitBucket, or SourceHut.\nAutomatically installs dependencies, creates .env files, and tracks usage.',
14
+ usage: [
15
+ 'clone <user/repo> [project-name] [options]',
16
+ 'clone [options]'
17
+ ],
18
+ options: [
19
+ { flag: '-h, --help', description: 'Display help for this command' },
20
+ { flag: '--offline', description: 'Use cached templates if available' },
21
+ { flag: '--no-deps', description: 'Skip dependency installation' },
22
+ { flag: '--no-git', description: 'Skip git initialization' },
23
+ { flag: '--shallow', description: 'Create shallow clone (faster)' },
24
+ { flag: '--branch <name>', description: 'Clone specific branch' },
25
+ { flag: '--template', description: 'Treat as template repository' }
26
+ ],
27
+ examples: [
28
+ { command: 'clone facebook/react', description: 'Clone from GitHub' },
29
+ { command: 'clone facebook/react my-app', description: 'Clone with custom name' },
30
+ { command: 'clone gitlab:user/project', description: 'Clone from GitLab' },
31
+ { command: 'clone bitbucket:user/repo', description: 'Clone from BitBucket' },
32
+ { command: 'clone sourcehut:user/repo', description: 'Clone from SourceHut' },
33
+ { command: 'clone user/repo --offline', description: 'Use cached version' },
34
+ { command: 'clone user/repo --no-deps', description: 'Skip dependencies' },
35
+ { command: 'clone user/repo --shallow', description: 'Shallow clone' }
36
+ ],
37
+ additionalSections: [
38
+ {
39
+ title: 'Supported Platforms',
40
+ items: [
41
+ 'GitHub (default): user/repo',
42
+ 'GitLab: gitlab:user/repo',
43
+ 'BitBucket: bitbucket:user/repo',
44
+ 'SourceHut: sourcehut:user/repo'
45
+ ]
46
+ },
47
+ {
48
+ title: 'Features',
49
+ items: [
50
+ 'Automatic dependency installation',
51
+ 'Environment file creation from templates',
52
+ 'Git repository initialization',
53
+ 'Usage tracking and history',
54
+ 'Offline mode with cached templates',
55
+ 'Shallow cloning for faster downloads',
56
+ 'Branch-specific cloning'
57
+ ]
58
+ }
59
+ ],
60
+ tips: [
61
+ 'Use --offline flag for cached repositories to work without internet',
62
+ 'Shallow clones are faster but have limited git history'
63
+ ]
64
+ };
65
+ createStandardHelp(helpConfig);
46
66
  }
47
67
  export async function cloneRepo(userRepo, projectName, options = {}) {
48
68
  const startTime = Date.now();
49
69
  const cacheManager = new CacheManager();
50
70
  // Check for help flag
51
- if (userRepo === '--help' || userRepo === '-h') {
71
+ if (options.help || options['-h'] || options['--help']) {
52
72
  showCloneHelp();
53
73
  return;
54
74
  }
@@ -58,12 +78,14 @@ export async function cloneRepo(userRepo, projectName, options = {}) {
58
78
  actualProjectName = path.basename(process.cwd());
59
79
  console.log(chalk.cyan(`Using current directory name: ${chalk.bold(actualProjectName)}`));
60
80
  }
61
- // Parse additional options from arguments
62
- const args = process.argv.slice(3);
81
+ // Configure clone options from passed options
63
82
  const cloneOptions = {
64
- offline: args.includes('--offline'),
65
- noDeps: args.includes('--no-deps'),
66
- noGit: args.includes('--no-git'),
83
+ offline: options.offline || false,
84
+ noDeps: options.noDeps || options['no-deps'] || false,
85
+ noGit: options.noGit || options['no-git'] || false,
86
+ shallow: options.shallow || false,
87
+ branch: options.branch || null,
88
+ template: options.template || false,
67
89
  ...options
68
90
  };
69
91
  try {