@nclamvn/vibecode-cli 2.0.0 → 2.2.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.
Files changed (53) hide show
  1. package/.vibecode/learning/fixes.json +1 -0
  2. package/.vibecode/learning/preferences.json +1 -0
  3. package/README.md +310 -49
  4. package/SESSION_NOTES.md +154 -0
  5. package/bin/vibecode.js +235 -2
  6. package/package.json +5 -2
  7. package/src/agent/decomposition.js +476 -0
  8. package/src/agent/index.js +391 -0
  9. package/src/agent/memory.js +542 -0
  10. package/src/agent/orchestrator.js +917 -0
  11. package/src/agent/self-healing.js +516 -0
  12. package/src/commands/agent.js +349 -0
  13. package/src/commands/ask.js +230 -0
  14. package/src/commands/assist.js +413 -0
  15. package/src/commands/build.js +345 -4
  16. package/src/commands/debug.js +565 -0
  17. package/src/commands/docs.js +167 -0
  18. package/src/commands/git.js +1024 -0
  19. package/src/commands/go.js +635 -0
  20. package/src/commands/learn.js +294 -0
  21. package/src/commands/migrate.js +341 -0
  22. package/src/commands/plan.js +8 -2
  23. package/src/commands/refactor.js +205 -0
  24. package/src/commands/review.js +126 -1
  25. package/src/commands/security.js +229 -0
  26. package/src/commands/shell.js +486 -0
  27. package/src/commands/templates.js +397 -0
  28. package/src/commands/test.js +194 -0
  29. package/src/commands/undo.js +281 -0
  30. package/src/commands/watch.js +556 -0
  31. package/src/commands/wizard.js +322 -0
  32. package/src/config/constants.js +5 -1
  33. package/src/config/templates.js +146 -15
  34. package/src/core/backup.js +325 -0
  35. package/src/core/error-analyzer.js +237 -0
  36. package/src/core/fix-generator.js +195 -0
  37. package/src/core/iteration.js +226 -0
  38. package/src/core/learning.js +295 -0
  39. package/src/core/session.js +18 -2
  40. package/src/core/test-runner.js +281 -0
  41. package/src/debug/analyzer.js +329 -0
  42. package/src/debug/evidence.js +228 -0
  43. package/src/debug/fixer.js +348 -0
  44. package/src/debug/image-analyzer.js +304 -0
  45. package/src/debug/index.js +378 -0
  46. package/src/debug/verifier.js +346 -0
  47. package/src/index.js +102 -0
  48. package/src/providers/claude-code.js +12 -7
  49. package/src/templates/index.js +724 -0
  50. package/src/ui/__tests__/error-translator.test.js +390 -0
  51. package/src/ui/dashboard.js +364 -0
  52. package/src/ui/error-translator.js +775 -0
  53. package/src/utils/image.js +222 -0
@@ -0,0 +1,205 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════════
2
+ // VIBECODE CLI - Refactor Command
3
+ // Phase K4: AI-Powered Refactoring
4
+ // ═══════════════════════════════════════════════════════════════════════════════
5
+
6
+ import { spawn } from 'child_process';
7
+ import fs from 'fs/promises';
8
+ import path from 'path';
9
+ import chalk from 'chalk';
10
+ import inquirer from 'inquirer';
11
+ import { BackupManager } from '../core/backup.js';
12
+
13
+ export async function refactorCommand(targetPath, options = {}) {
14
+ const cwd = process.cwd();
15
+
16
+ // Interactive mode
17
+ if (!targetPath && !options.type) {
18
+ return interactiveRefactor(cwd);
19
+ }
20
+
21
+ return performRefactor(cwd, targetPath || 'src/', options);
22
+ }
23
+
24
+ async function interactiveRefactor(cwd) {
25
+ console.log(chalk.cyan(`
26
+ ╭────────────────────────────────────────────────────────────────────╮
27
+ │ 🔄 AI REFACTORING │
28
+ │ │
29
+ │ Improve code quality with AI-powered refactoring │
30
+ │ │
31
+ ╰────────────────────────────────────────────────────────────────────╯
32
+ `));
33
+
34
+ const { refactorType } = await inquirer.prompt([{
35
+ type: 'list',
36
+ name: 'refactorType',
37
+ message: 'What type of refactoring?',
38
+ choices: [
39
+ { name: '🧹 Clean Code - Improve readability', value: 'clean' },
40
+ { name: '🔄 DRY - Remove duplication', value: 'dry' },
41
+ { name: '⚡ Performance - Optimize slow code', value: 'performance' },
42
+ { name: '🏗️ Architecture - Better structure', value: 'architecture' },
43
+ { name: '📦 Modularize - Split large files', value: 'modularize' },
44
+ { name: '🆕 Modernize - Update to modern syntax', value: 'modernize' },
45
+ { name: '🎯 Custom - Describe your own', value: 'custom' },
46
+ { name: '👋 Exit', value: 'exit' }
47
+ ]
48
+ }]);
49
+
50
+ if (refactorType === 'exit') return;
51
+
52
+ const { targetPath } = await inquirer.prompt([{
53
+ type: 'input',
54
+ name: 'targetPath',
55
+ message: 'Path to refactor:',
56
+ default: 'src/'
57
+ }]);
58
+
59
+ let customDescription = '';
60
+ if (refactorType === 'custom') {
61
+ const { desc } = await inquirer.prompt([{
62
+ type: 'input',
63
+ name: 'desc',
64
+ message: 'Describe the refactoring:'
65
+ }]);
66
+ customDescription = desc;
67
+ }
68
+
69
+ return performRefactor(cwd, targetPath, { type: refactorType, description: customDescription });
70
+ }
71
+
72
+ async function performRefactor(cwd, targetPath, options) {
73
+ const refactorType = options.type || 'clean';
74
+
75
+ // Create backup first
76
+ console.log(chalk.gray('\n Creating backup before refactoring...\n'));
77
+ const backup = new BackupManager(cwd);
78
+ await backup.createBackup(`refactor-${refactorType}`);
79
+
80
+ const prompts = {
81
+ clean: `
82
+ # Clean Code Refactoring
83
+
84
+ Improve code readability:
85
+ - Better variable/function names (descriptive, consistent)
86
+ - Simplify complex conditions (extract to named variables/functions)
87
+ - Extract magic numbers to named constants
88
+ - Add meaningful comments where logic is complex
89
+ - Improve code formatting and consistency
90
+ - Follow language conventions and style guides
91
+ - Remove dead code and unused imports
92
+ `,
93
+ dry: `
94
+ # DRY Refactoring (Don't Repeat Yourself)
95
+
96
+ Remove code duplication:
97
+ - Identify repeated code patterns (3+ occurrences)
98
+ - Extract common logic to reusable functions
99
+ - Create utility modules for shared functionality
100
+ - Use generics/templates where appropriate
101
+ - Consolidate similar functions with parameters
102
+ - Create higher-order functions for common patterns
103
+ `,
104
+ performance: `
105
+ # Performance Optimization
106
+
107
+ Optimize for speed and efficiency:
108
+ - Replace O(n²) with O(n) where possible
109
+ - Add memoization for expensive computations
110
+ - Optimize database queries (N+1 problem)
111
+ - Implement lazy loading for large data
112
+ - Use efficient data structures (Map/Set vs Array)
113
+ - Remove unnecessary re-renders (React)
114
+ - Add proper caching strategies
115
+ - Optimize loops and iterations
116
+ `,
117
+ architecture: `
118
+ # Architecture Refactoring
119
+
120
+ Improve code structure:
121
+ - Apply SOLID principles
122
+ - Implement proper separation of concerns
123
+ - Use dependency injection where appropriate
124
+ - Apply appropriate design patterns
125
+ - Improve module boundaries
126
+ - Better error handling structure
127
+ - Create clear interfaces between modules
128
+ - Reduce coupling, increase cohesion
129
+ `,
130
+ modularize: `
131
+ # Modularization
132
+
133
+ Split large files and improve organization:
134
+ - Break large files (>300 lines) into smaller modules
135
+ - One component/class per file
136
+ - Group related functionality in folders
137
+ - Create proper index files for exports
138
+ - Improve import structure
139
+ - Separate concerns (UI, logic, data)
140
+ - Create feature-based folder structure
141
+ `,
142
+ modernize: `
143
+ # Modernize Code
144
+
145
+ Update to modern syntax and practices:
146
+ - ES6+ features (arrow functions, destructuring, spread)
147
+ - async/await instead of callbacks/Promise chains
148
+ - Optional chaining (?.) and nullish coalescing (??)
149
+ - Modern array methods (map, filter, reduce)
150
+ - Template literals instead of string concatenation
151
+ - const/let instead of var
152
+ - TypeScript improvements (if TS project)
153
+ - Modern React patterns (hooks, functional components)
154
+ `,
155
+ custom: `
156
+ # Custom Refactoring
157
+
158
+ ${options.description || 'Improve the code based on best practices.'}
159
+ `
160
+ };
161
+
162
+ const prompt = `
163
+ ${prompts[refactorType]}
164
+
165
+ ## Target Path: ${targetPath}
166
+
167
+ ## Instructions:
168
+ 1. Analyze the code in the target path
169
+ 2. Apply the refactoring described above
170
+ 3. Preserve all functionality (don't break anything!)
171
+ 4. Make minimal changes to achieve the goal
172
+ 5. Add comments explaining significant changes
173
+
174
+ ## Safety:
175
+ - Run tests after refactoring if available
176
+ - Keep backward compatibility
177
+ - Don't change public APIs without good reason
178
+
179
+ Perform the refactoring now.
180
+ `;
181
+
182
+ const promptFile = path.join(cwd, '.vibecode', 'refactor-prompt.md');
183
+ await fs.mkdir(path.dirname(promptFile), { recursive: true });
184
+ await fs.writeFile(promptFile, prompt);
185
+
186
+ console.log(chalk.yellow(` Refactoring (${refactorType})...\n`));
187
+
188
+ await runClaudeCode(prompt, cwd);
189
+
190
+ console.log(chalk.green('\n✅ Refactoring complete!'));
191
+ console.log(chalk.gray(' • Run tests to verify changes'));
192
+ console.log(chalk.gray(' • Use `vibecode undo` to revert if needed\n'));
193
+ }
194
+
195
+ async function runClaudeCode(prompt, cwd) {
196
+ return new Promise((resolve) => {
197
+ const child = spawn('claude', ['-p', prompt, '--dangerously-skip-permissions'], {
198
+ cwd,
199
+ stdio: 'inherit'
200
+ });
201
+
202
+ child.on('close', resolve);
203
+ child.on('error', () => resolve());
204
+ });
205
+ }
@@ -1,11 +1,13 @@
1
1
  // ═══════════════════════════════════════════════════════════════════════════════
2
2
  // VIBECODE CLI - Review Command
3
+ // Phase K1: AI Code Review
3
4
  // ═══════════════════════════════════════════════════════════════════════════════
4
5
 
5
6
  import chalk from 'chalk';
6
7
  import ora from 'ora';
7
8
  import path from 'path';
8
- import { exec } from 'child_process';
9
+ import fs from 'fs/promises';
10
+ import { exec, spawn } from 'child_process';
9
11
  import { promisify } from 'util';
10
12
  import inquirer from 'inquirer';
11
13
  import { workspaceExists, getProjectName } from '../core/workspace.js';
@@ -26,6 +28,10 @@ import { printBox, printError, printSuccess, printWarning, printNextStep } from
26
28
  const execAsync = promisify(exec);
27
29
 
28
30
  export async function reviewCommand(options = {}) {
31
+ // K1: AI-powered code review
32
+ if (options.ai) {
33
+ return aiCodeReview(options);
34
+ }
29
35
  const spinner = ora('Starting review...').start();
30
36
 
31
37
  try {
@@ -288,3 +294,122 @@ async function checkGitStatus() {
288
294
  return { clean: true, message: 'Git not available' };
289
295
  }
290
296
  }
297
+
298
+ // ═══════════════════════════════════════════════════════════════════════════════
299
+ // K1: AI CODE REVIEW
300
+ // ═══════════════════════════════════════════════════════════════════════════════
301
+
302
+ async function aiCodeReview(options) {
303
+ const cwd = process.cwd();
304
+
305
+ console.log(chalk.cyan(`
306
+ ╭────────────────────────────────────────────────────────────────────╮
307
+ │ 🔍 AI CODE REVIEW │
308
+ │ │
309
+ │ Analyzing codebase for: │
310
+ │ • Code quality & best practices │
311
+ │ • Potential bugs & edge cases │
312
+ │ • Performance concerns │
313
+ │ • Security vulnerabilities │
314
+ │ • Maintainability issues │
315
+ │ │
316
+ ╰────────────────────────────────────────────────────────────────────╯
317
+ `));
318
+
319
+ // Gather codebase context
320
+ const files = await gatherSourceFiles(cwd, options.path);
321
+
322
+ console.log(chalk.gray(` Found ${files.length} files to review\n`));
323
+
324
+ const prompt = `
325
+ # AI Code Review Request
326
+
327
+ ## Project: ${path.basename(cwd)}
328
+
329
+ ## Files to Review:
330
+ ${files.map(f => `- ${f}`).join('\n')}
331
+
332
+ ## Review Criteria:
333
+ 1. **Code Quality**: Clean code, readability, naming conventions
334
+ 2. **Best Practices**: Design patterns, DRY, SOLID principles
335
+ 3. **Potential Bugs**: Edge cases, null checks, error handling
336
+ 4. **Performance**: Inefficient loops, memory leaks, N+1 queries
337
+ 5. **Security**: Input validation, XSS, SQL injection, auth issues
338
+ 6. **Maintainability**: Modularity, testability, documentation
339
+
340
+ ## Output Format:
341
+ For each issue found, provide:
342
+ - **Severity**: Critical / High / Medium / Low
343
+ - **Category**: Bug / Performance / Security / Quality / Maintainability
344
+ - **File**: path/to/file.ts
345
+ - **Line**: (if applicable)
346
+ - **Issue**: Description
347
+ - **Suggestion**: How to fix
348
+
349
+ ## Summary:
350
+ End with overall score (A-F) and top 3 priorities.
351
+
352
+ Review the codebase now.
353
+ `;
354
+
355
+ // Write prompt
356
+ const promptFile = path.join(cwd, '.vibecode', 'review-prompt.md');
357
+ await fs.mkdir(path.dirname(promptFile), { recursive: true });
358
+ await fs.writeFile(promptFile, prompt);
359
+
360
+ // Run Claude Code
361
+ console.log(chalk.gray(' Analyzing with Claude Code...\n'));
362
+
363
+ await runClaudeCode(prompt, cwd);
364
+
365
+ // Save report
366
+ const reportDir = path.join(cwd, '.vibecode', 'reports');
367
+ await fs.mkdir(reportDir, { recursive: true });
368
+ const reportFile = path.join(reportDir, `review-${Date.now()}.md`);
369
+
370
+ console.log(chalk.green(`\n✅ Review complete!`));
371
+ console.log(chalk.gray(` Report saved to: .vibecode/reports/\n`));
372
+ }
373
+
374
+ async function gatherSourceFiles(cwd, targetPath) {
375
+ const files = [];
376
+ const extensions = ['.js', '.ts', '.tsx', '.jsx', '.py', '.go', '.rs', '.vue', '.svelte'];
377
+ const ignoreDirs = ['node_modules', '.git', 'dist', 'build', '.next', 'coverage', '.vibecode', '__pycache__'];
378
+
379
+ const scanDir = targetPath ? path.join(cwd, targetPath) : cwd;
380
+
381
+ async function scan(dir) {
382
+ try {
383
+ const entries = await fs.readdir(dir, { withFileTypes: true });
384
+
385
+ for (const entry of entries) {
386
+ if (entry.name.startsWith('.')) continue;
387
+ if (ignoreDirs.includes(entry.name)) continue;
388
+
389
+ const fullPath = path.join(dir, entry.name);
390
+ const relativePath = path.relative(cwd, fullPath);
391
+
392
+ if (entry.isDirectory()) {
393
+ await scan(fullPath);
394
+ } else if (extensions.some(ext => entry.name.endsWith(ext))) {
395
+ files.push(relativePath);
396
+ }
397
+ }
398
+ } catch {}
399
+ }
400
+
401
+ await scan(scanDir);
402
+ return files.slice(0, 50); // Limit files
403
+ }
404
+
405
+ async function runClaudeCode(prompt, cwd) {
406
+ return new Promise((resolve) => {
407
+ const child = spawn('claude', ['-p', prompt, '--dangerously-skip-permissions'], {
408
+ cwd,
409
+ stdio: 'inherit'
410
+ });
411
+
412
+ child.on('close', resolve);
413
+ child.on('error', () => resolve());
414
+ });
415
+ }
@@ -0,0 +1,229 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════════
2
+ // VIBECODE CLI - Security Command
3
+ // Phase K5: AI Security Audit
4
+ // ═══════════════════════════════════════════════════════════════════════════════
5
+
6
+ import { spawn, exec } from 'child_process';
7
+ import { promisify } from 'util';
8
+ import fs from 'fs/promises';
9
+ import path from 'path';
10
+ import chalk from 'chalk';
11
+
12
+ const execAsync = promisify(exec);
13
+
14
+ export async function securityCommand(options = {}) {
15
+ const cwd = process.cwd();
16
+
17
+ console.log(chalk.cyan(`
18
+ ╭────────────────────────────────────────────────────────────────────╮
19
+ │ 🔒 SECURITY AUDIT │
20
+ │ │
21
+ │ Scanning for vulnerabilities... │
22
+ │ │
23
+ ╰────────────────────────────────────────────────────────────────────╯
24
+ `));
25
+
26
+ const results = {
27
+ npmAudit: null,
28
+ secretsScan: [],
29
+ timestamp: new Date().toISOString()
30
+ };
31
+
32
+ // 1. Run npm audit
33
+ console.log(chalk.gray('\n [1/3] Running npm audit...\n'));
34
+ try {
35
+ const { stdout } = await execAsync('npm audit --json', { cwd, timeout: 60000 });
36
+ results.npmAudit = JSON.parse(stdout);
37
+ console.log(chalk.green(' ✓ npm audit complete'));
38
+ } catch (error) {
39
+ try {
40
+ if (error.stdout) {
41
+ results.npmAudit = JSON.parse(error.stdout);
42
+ const vulns = results.npmAudit?.metadata?.vulnerabilities;
43
+ if (vulns) {
44
+ const total = vulns.critical + vulns.high + vulns.moderate + vulns.low;
45
+ if (total > 0) {
46
+ console.log(chalk.yellow(` ⚠ Found ${total} vulnerabilities`));
47
+ } else {
48
+ console.log(chalk.green(' ✓ No vulnerabilities found'));
49
+ }
50
+ }
51
+ }
52
+ } catch {
53
+ results.npmAudit = { error: 'npm audit failed or not applicable' };
54
+ console.log(chalk.gray(' - npm audit not applicable'));
55
+ }
56
+ }
57
+
58
+ // 2. Scan for secrets
59
+ console.log(chalk.gray('\n [2/3] Scanning for exposed secrets...\n'));
60
+ results.secretsScan = await scanForSecrets(cwd);
61
+ if (results.secretsScan.length > 0) {
62
+ console.log(chalk.red(` ⚠ Found ${results.secretsScan.length} potential secrets!`));
63
+ for (const secret of results.secretsScan.slice(0, 5)) {
64
+ console.log(chalk.gray(` - ${secret.file}: ${secret.type}`));
65
+ }
66
+ } else {
67
+ console.log(chalk.green(' ✓ No exposed secrets detected'));
68
+ }
69
+
70
+ // 3. AI security analysis
71
+ console.log(chalk.gray('\n [3/3] AI security analysis...\n'));
72
+
73
+ const vulnSummary = results.npmAudit?.metadata?.vulnerabilities;
74
+ const npmSummary = vulnSummary
75
+ ? `Critical: ${vulnSummary.critical}, High: ${vulnSummary.high}, Moderate: ${vulnSummary.moderate}, Low: ${vulnSummary.low}`
76
+ : 'npm audit not available';
77
+
78
+ const prompt = `
79
+ # Security Audit Request
80
+
81
+ ## Project: ${path.basename(cwd)}
82
+
83
+ ## NPM Audit Results:
84
+ ${npmSummary}
85
+
86
+ ## Potential Secrets Found:
87
+ ${results.secretsScan.map(s => `- ${s.file}: ${s.type}`).join('\n') || 'None detected'}
88
+
89
+ ## Security Analysis Required:
90
+ Analyze the codebase for security vulnerabilities:
91
+
92
+ 1. **Authentication Issues**
93
+ - Weak password handling
94
+ - Missing auth checks on protected routes
95
+ - Insecure session management
96
+ - JWT vulnerabilities
97
+
98
+ 2. **Input Validation**
99
+ - SQL injection risks
100
+ - XSS vulnerabilities
101
+ - Command injection
102
+ - Path traversal
103
+ - ReDoS (regex denial of service)
104
+
105
+ 3. **Data Exposure**
106
+ - Sensitive data in logs
107
+ - Exposed API keys in code
108
+ - Insecure data storage
109
+ - PII handling issues
110
+
111
+ 4. **Configuration Issues**
112
+ - CORS misconfiguration
113
+ - Missing security headers
114
+ - Debug mode in production
115
+ - Insecure defaults
116
+
117
+ 5. **Dependencies**
118
+ - Known vulnerable packages
119
+ - Outdated dependencies
120
+ - Unnecessary dependencies
121
+
122
+ ## Output Format:
123
+ For each vulnerability found:
124
+ - **Severity**: Critical / High / Medium / Low
125
+ - **Category**: Auth / Injection / Exposure / Config / Dependency
126
+ - **Location**: File and line number
127
+ - **Description**: What's the issue
128
+ - **Remediation**: How to fix it
129
+
130
+ End with a security score (A-F) and priority fixes.
131
+ `;
132
+
133
+ const promptFile = path.join(cwd, '.vibecode', 'security-prompt.md');
134
+ await fs.mkdir(path.dirname(promptFile), { recursive: true });
135
+ await fs.writeFile(promptFile, prompt);
136
+
137
+ await runClaudeCode(prompt, cwd);
138
+
139
+ // Save report
140
+ const reportPath = path.join(cwd, '.vibecode', 'reports', `security-${Date.now()}.json`);
141
+ await fs.mkdir(path.dirname(reportPath), { recursive: true });
142
+ await fs.writeFile(reportPath, JSON.stringify(results, null, 2));
143
+
144
+ console.log(chalk.green('\n✅ Security audit complete!'));
145
+ console.log(chalk.gray(` Report saved to: .vibecode/reports/\n`));
146
+
147
+ // Auto-fix option
148
+ if (options.fix) {
149
+ console.log(chalk.yellow('\n Attempting auto-fix...\n'));
150
+ try {
151
+ await execAsync('npm audit fix', { cwd });
152
+ console.log(chalk.green(' ✓ npm audit fix completed\n'));
153
+ } catch {
154
+ console.log(chalk.gray(' - npm audit fix not applicable\n'));
155
+ }
156
+ }
157
+ }
158
+
159
+ async function scanForSecrets(cwd) {
160
+ const secrets = [];
161
+ const patterns = [
162
+ { regex: /(['"])?(api[_-]?key|apikey)(['"])?\s*[:=]\s*(['"])[a-zA-Z0-9]{20,}(['"])/gi, type: 'API Key' },
163
+ { regex: /(['"])?(secret|password|passwd|pwd)(['"])?\s*[:=]\s*(['"])[^'"]{8,}(['"])/gi, type: 'Password/Secret' },
164
+ { regex: /(['"])?(aws[_-]?access[_-]?key[_-]?id)(['"])?\s*[:=]\s*(['"])[A-Z0-9]{20}(['"])/gi, type: 'AWS Access Key' },
165
+ { regex: /(['"])?(aws[_-]?secret)(['"])?\s*[:=]\s*(['"])[a-zA-Z0-9/+=]{40}(['"])/gi, type: 'AWS Secret Key' },
166
+ { regex: /(['"])?(private[_-]?key)(['"])?\s*[:=]\s*(['"])-----BEGIN/gi, type: 'Private Key' },
167
+ { regex: /(['"])?(auth[_-]?token|bearer)(['"])?\s*[:=]\s*(['"])[a-zA-Z0-9._-]{20,}(['"])/gi, type: 'Auth Token' },
168
+ { regex: /(['"])?(github[_-]?token)(['"])?\s*[:=]\s*(['"])gh[ps]_[a-zA-Z0-9]{36}(['"])/gi, type: 'GitHub Token' },
169
+ { regex: /(['"])?(stripe[_-]?key)(['"])?\s*[:=]\s*(['"])sk_[a-zA-Z0-9]{24,}(['"])/gi, type: 'Stripe Key' }
170
+ ];
171
+
172
+ const files = await getAllSourceFiles(cwd);
173
+
174
+ for (const file of files) {
175
+ try {
176
+ const content = await fs.readFile(path.join(cwd, file), 'utf-8');
177
+
178
+ for (const { regex, type } of patterns) {
179
+ regex.lastIndex = 0; // Reset regex state
180
+ if (regex.test(content)) {
181
+ secrets.push({ file, type });
182
+ break; // One type per file is enough
183
+ }
184
+ }
185
+ } catch {}
186
+ }
187
+
188
+ return secrets;
189
+ }
190
+
191
+ async function getAllSourceFiles(cwd) {
192
+ const files = [];
193
+ const extensions = ['.js', '.ts', '.jsx', '.tsx', '.json', '.env', '.yaml', '.yml', '.py', '.go'];
194
+ const ignoreDirs = ['node_modules', '.git', 'dist', 'build', '.next', 'coverage'];
195
+
196
+ async function scan(dir) {
197
+ try {
198
+ const entries = await fs.readdir(dir, { withFileTypes: true });
199
+
200
+ for (const entry of entries) {
201
+ if (entry.name.startsWith('.') && entry.name !== '.env') continue;
202
+ if (ignoreDirs.includes(entry.name)) continue;
203
+
204
+ const fullPath = path.join(dir, entry.name);
205
+
206
+ if (entry.isDirectory()) {
207
+ await scan(fullPath);
208
+ } else if (extensions.some(ext => entry.name.endsWith(ext))) {
209
+ files.push(path.relative(cwd, fullPath));
210
+ }
211
+ }
212
+ } catch {}
213
+ }
214
+
215
+ await scan(cwd);
216
+ return files.slice(0, 100);
217
+ }
218
+
219
+ async function runClaudeCode(prompt, cwd) {
220
+ return new Promise((resolve) => {
221
+ const child = spawn('claude', ['-p', prompt, '--dangerously-skip-permissions'], {
222
+ cwd,
223
+ stdio: 'inherit'
224
+ });
225
+
226
+ child.on('close', resolve);
227
+ child.on('error', () => resolve());
228
+ });
229
+ }