claude-flow-novice 1.3.1 → 1.3.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.
@@ -0,0 +1,618 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { LanguageDetector } from './language-detector.js';
4
+
5
+ /**
6
+ * CLAUDE.md Generator System
7
+ *
8
+ * Auto-generates CLAUDE.md files with language-specific best practices
9
+ * Uses templates and intelligent substitution for contextual configurations
10
+ */
11
+ export class ClaudeMdGenerator {
12
+ constructor(projectPath = process.cwd(), options = {}) {
13
+ this.projectPath = projectPath;
14
+ this.options = {
15
+ preserveCustomSections: true,
16
+ backupExisting: true,
17
+ templatePath: options.templatePath || path.join(process.cwd(), 'src', 'templates', 'claude-md-templates'),
18
+ preferencesPath: options.preferencesPath || path.join(process.cwd(), '.claude-flow-novice', 'preferences'),
19
+ ...options
20
+ };
21
+
22
+ this.detector = new LanguageDetector(projectPath);
23
+ this.detectionResults = null;
24
+ this.templates = {};
25
+ this.userPreferences = {};
26
+ }
27
+
28
+ /**
29
+ * Main generation method
30
+ */
31
+ async generateClaudeMd() {
32
+ console.log('🚀 Starting CLAUDE.md generation...');
33
+
34
+ try {
35
+ // Step 1: Detect project languages and frameworks
36
+ this.detectionResults = await this.detector.detectProject();
37
+ console.log(`✅ Detected primary type: ${this.detectionResults.projectType}`);
38
+
39
+ // Step 2: Load templates and user preferences
40
+ await Promise.all([
41
+ this.loadTemplates(),
42
+ this.loadUserPreferences()
43
+ ]);
44
+
45
+ // Step 3: Check for existing CLAUDE.md
46
+ const existingContent = await this.loadExistingClaudeMd();
47
+
48
+ // Step 4: Generate new content
49
+ const newContent = await this.generateContent();
50
+
51
+ // Step 5: Merge with existing if needed
52
+ const finalContent = existingContent
53
+ ? await this.mergeWithExisting(existingContent, newContent)
54
+ : newContent;
55
+
56
+ // Step 6: Write the file
57
+ await this.writeClaudeMd(finalContent);
58
+
59
+ console.log('✅ CLAUDE.md generation completed successfully');
60
+ return finalContent;
61
+
62
+ } catch (error) {
63
+ console.error(`❌ Generation failed: ${error.message}`);
64
+ throw error;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Load all template files
70
+ */
71
+ async loadTemplates() {
72
+ const templateFiles = [
73
+ 'base-template.md',
74
+ 'javascript-template.md',
75
+ 'typescript-template.md',
76
+ 'python-template.md',
77
+ 'react-template.md',
78
+ 'express-template.md',
79
+ 'django-template.md',
80
+ 'flask-template.md',
81
+ 'nextjs-template.md'
82
+ ];
83
+
84
+ for (const template of templateFiles) {
85
+ const templatePath = path.join(this.options.templatePath, template);
86
+ try {
87
+ const content = await fs.readFile(templatePath, 'utf8');
88
+ const name = template.replace('-template.md', '');
89
+ this.templates[name] = content;
90
+ } catch (error) {
91
+ console.warn(`Template ${template} not found, skipping...`);
92
+ }
93
+ }
94
+
95
+ console.log(`📄 Loaded ${Object.keys(this.templates).length} templates`);
96
+ }
97
+
98
+ /**
99
+ * Load user preferences and language configs
100
+ */
101
+ async loadUserPreferences() {
102
+ try {
103
+ const prefsPath = path.join(this.options.preferencesPath, 'generation.json');
104
+ const content = await fs.readFile(prefsPath, 'utf8');
105
+ this.userPreferences = JSON.parse(content);
106
+ } catch (error) {
107
+ // Use defaults if no preferences found
108
+ this.userPreferences = {
109
+ autoGenerate: true,
110
+ includeFrameworkSpecific: true,
111
+ includeBestPractices: true,
112
+ includeTestingPatterns: true,
113
+ includeDeploymentGuidelines: false
114
+ };
115
+ }
116
+
117
+ console.log('⚙️ User preferences loaded');
118
+ }
119
+
120
+ /**
121
+ * Load existing CLAUDE.md if it exists
122
+ */
123
+ async loadExistingClaudeMd() {
124
+ const claudeMdPath = path.join(this.projectPath, 'CLAUDE.md');
125
+
126
+ try {
127
+ const content = await fs.readFile(claudeMdPath, 'utf8');
128
+
129
+ // Create backup if requested
130
+ if (this.options.backupExisting) {
131
+ const backupPath = claudeMdPath + `.backup.${Date.now()}`;
132
+ await fs.writeFile(backupPath, content);
133
+ console.log(`📋 Created backup: ${path.basename(backupPath)}`);
134
+ }
135
+
136
+ return content;
137
+ } catch (error) {
138
+ console.log('📝 No existing CLAUDE.md found, creating new one');
139
+ return null;
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Generate new CLAUDE.md content based on detection results
145
+ */
146
+ async generateContent() {
147
+ const { projectType, languages, frameworks, metadata } = this.detectionResults;
148
+
149
+ // Start with base template
150
+ let content = this.templates.base || this.getDefaultBaseTemplate();
151
+
152
+ // Apply template substitutions
153
+ const substitutions = this.buildSubstitutions();
154
+ content = this.applySubstitutions(content, substitutions);
155
+
156
+ // Add language-specific sections
157
+ content = await this.addLanguageSpecificSections(content);
158
+
159
+ // Add framework-specific sections
160
+ content = await this.addFrameworkSpecificSections(content);
161
+
162
+ // Add concurrent execution patterns
163
+ content = await this.addConcurrentExecutionPatterns(content);
164
+
165
+ // Add best practices
166
+ if (this.userPreferences.includeBestPractices) {
167
+ content = await this.addBestPractices(content);
168
+ }
169
+
170
+ // Add testing patterns
171
+ if (this.userPreferences.includeTestingPatterns) {
172
+ content = await this.addTestingPatterns(content);
173
+ }
174
+
175
+ return content;
176
+ }
177
+
178
+ /**
179
+ * Build template substitution variables
180
+ */
181
+ buildSubstitutions() {
182
+ const { projectType, languages, frameworks, metadata } = this.detectionResults;
183
+
184
+ return {
185
+ PROJECT_TYPE: projectType || 'unknown',
186
+ PRIMARY_LANGUAGE: metadata.primaryLanguage || 'javascript',
187
+ PRIMARY_FRAMEWORK: metadata.primaryFramework || 'none',
188
+ PROJECT_NAME: metadata.projectName || path.basename(this.projectPath),
189
+ PACKAGE_MANAGER: metadata.packageManager || 'npm',
190
+ BUILD_TOOLS: Object.keys(metadata.buildTools || {}).join(', ') || 'none',
191
+ LANGUAGES_LIST: Object.keys(languages).join(', '),
192
+ FRAMEWORKS_LIST: Object.keys(frameworks).join(', '),
193
+ TIMESTAMP: new Date().toISOString().split('T')[0],
194
+ DIRECTORIES: (metadata.directories || []).join(', ')
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Apply template variable substitutions
200
+ */
201
+ applySubstitutions(content, substitutions) {
202
+ let result = content;
203
+
204
+ for (const [key, value] of Object.entries(substitutions)) {
205
+ const placeholder = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
206
+ result = result.replace(placeholder, value);
207
+ }
208
+
209
+ return result;
210
+ }
211
+
212
+ /**
213
+ * Add language-specific sections
214
+ */
215
+ async addLanguageSpecificSections(content) {
216
+ const { languages } = this.detectionResults;
217
+ let result = content;
218
+
219
+ for (const [language, confidence] of Object.entries(languages)) {
220
+ if (confidence > 0.3 && this.templates[language]) {
221
+ const languageSection = `\n\n## ${language.charAt(0).toUpperCase() + language.slice(1)} Configuration\n\n`;
222
+ result += languageSection + this.templates[language];
223
+ }
224
+ }
225
+
226
+ return result;
227
+ }
228
+
229
+ /**
230
+ * Add framework-specific sections
231
+ */
232
+ async addFrameworkSpecificSections(content) {
233
+ const { frameworks } = this.detectionResults;
234
+ let result = content;
235
+
236
+ for (const [framework, confidence] of Object.entries(frameworks)) {
237
+ if (confidence > 0.4 && this.templates[framework]) {
238
+ const frameworkSection = `\n\n## ${framework.charAt(0).toUpperCase() + framework.slice(1)} Framework Configuration\n\n`;
239
+ result += frameworkSection + this.templates[framework];
240
+ }
241
+ }
242
+
243
+ return result;
244
+ }
245
+
246
+ /**
247
+ * Add concurrent execution patterns based on detected languages
248
+ */
249
+ async addConcurrentExecutionPatterns(content) {
250
+ const { languages, frameworks } = this.detectionResults;
251
+ let patterns = '\n\n## 🚀 Concurrent Execution Patterns\n\n';
252
+
253
+ // JavaScript/TypeScript patterns
254
+ if (languages.javascript || languages.typescript) {
255
+ patterns += this.getJavaScriptConcurrentPatterns();
256
+ }
257
+
258
+ // Python patterns
259
+ if (languages.python) {
260
+ patterns += this.getPythonConcurrentPatterns();
261
+ }
262
+
263
+ // React patterns
264
+ if (frameworks.react || frameworks.nextjs) {
265
+ patterns += this.getReactConcurrentPatterns();
266
+ }
267
+
268
+ // API patterns
269
+ if (frameworks.express || frameworks.flask || frameworks.django || frameworks.fastapi) {
270
+ patterns += this.getApiConcurrentPatterns();
271
+ }
272
+
273
+ return content + patterns;
274
+ }
275
+
276
+ /**
277
+ * Add best practices section
278
+ */
279
+ async addBestPractices(content) {
280
+ const { projectType, languages, frameworks } = this.detectionResults;
281
+ let practices = '\n\n## 📋 Best Practices\n\n';
282
+
283
+ // General practices
284
+ practices += `### General Development\n`;
285
+ practices += `- **Modular Design**: Keep files under 500 lines\n`;
286
+ practices += `- **Environment Safety**: Never hardcode secrets\n`;
287
+ practices += `- **Test-First**: Write tests before implementation\n`;
288
+ practices += `- **Clean Architecture**: Separate concerns\n`;
289
+ practices += `- **Documentation**: Keep updated\n\n`;
290
+
291
+ // Language-specific practices
292
+ if (languages.javascript || languages.typescript) {
293
+ practices += this.getJavaScriptBestPractices();
294
+ }
295
+
296
+ if (languages.python) {
297
+ practices += this.getPythonBestPractices();
298
+ }
299
+
300
+ return content + practices;
301
+ }
302
+
303
+ /**
304
+ * Add testing patterns section
305
+ */
306
+ async addTestingPatterns(content) {
307
+ const { languages, frameworks } = this.detectionResults;
308
+ let testing = '\n\n## 🧪 Testing Patterns\n\n';
309
+
310
+ if (languages.javascript || languages.typescript) {
311
+ if (frameworks.react || frameworks.nextjs) {
312
+ testing += this.getReactTestingPatterns();
313
+ } else {
314
+ testing += this.getJavaScriptTestingPatterns();
315
+ }
316
+ }
317
+
318
+ if (languages.python) {
319
+ testing += this.getPythonTestingPatterns();
320
+ }
321
+
322
+ return content + testing;
323
+ }
324
+
325
+ /**
326
+ * Merge new content with existing CLAUDE.md
327
+ */
328
+ async mergeWithExisting(existing, generated) {
329
+ console.log('🔄 Merging with existing CLAUDE.md...');
330
+
331
+ // Extract custom sections from existing file
332
+ const customSections = this.extractCustomSections(existing);
333
+
334
+ // Combine generated content with preserved custom sections
335
+ let merged = generated;
336
+
337
+ if (customSections.length > 0) {
338
+ merged += '\n\n## Custom Configuration\n\n';
339
+ merged += '<!-- Preserved from existing CLAUDE.md -->\n';
340
+ merged += customSections.join('\n\n');
341
+ }
342
+
343
+ return merged;
344
+ }
345
+
346
+ /**
347
+ * Extract custom sections that should be preserved
348
+ */
349
+ extractCustomSections(content) {
350
+ const customSections = [];
351
+ const lines = content.split('\n');
352
+ let inCustomSection = false;
353
+ let currentSection = [];
354
+
355
+ for (const line of lines) {
356
+ // Look for custom markers or sections not in our templates
357
+ if (line.includes('<!-- CUSTOM') || line.includes('# Custom') || line.includes('## Custom')) {
358
+ inCustomSection = true;
359
+ currentSection = [line];
360
+ } else if (inCustomSection && line.startsWith('#')) {
361
+ // End of custom section
362
+ customSections.push(currentSection.join('\n'));
363
+ inCustomSection = false;
364
+ currentSection = [];
365
+ } else if (inCustomSection) {
366
+ currentSection.push(line);
367
+ }
368
+ }
369
+
370
+ // Add final section if we ended in a custom section
371
+ if (currentSection.length > 0) {
372
+ customSections.push(currentSection.join('\n'));
373
+ }
374
+
375
+ return customSections;
376
+ }
377
+
378
+ /**
379
+ * Write the final CLAUDE.md file
380
+ */
381
+ async writeClaudeMd(content) {
382
+ const claudeMdPath = path.join(this.projectPath, 'CLAUDE.md');
383
+ await fs.writeFile(claudeMdPath, content);
384
+ console.log(`📄 Written CLAUDE.md (${content.length} characters)`);
385
+ }
386
+
387
+ // Template pattern methods
388
+ getJavaScriptConcurrentPatterns() {
389
+ return `### JavaScript/TypeScript Patterns\n\n` +
390
+ `\`\`\`javascript\n` +
391
+ `// ✅ CORRECT: Batch all operations in single message\n` +
392
+ `[Single Message]:\n` +
393
+ ` Task("Frontend Developer", "Build React components with hooks", "coder")\n` +
394
+ ` Task("Backend Developer", "Create Express API endpoints", "backend-dev")\n` +
395
+ ` Task("Test Engineer", "Write Jest tests with >80% coverage", "tester")\n` +
396
+ ` \n` +
397
+ ` // Batch file operations\n` +
398
+ ` Write("src/components/App.jsx")\n` +
399
+ ` Write("src/api/server.js")\n` +
400
+ ` Write("tests/App.test.js")\n` +
401
+ `\`\`\`\n\n`;
402
+ }
403
+
404
+ getPythonConcurrentPatterns() {
405
+ return `### Python Patterns\n\n` +
406
+ `\`\`\`python\n` +
407
+ `# ✅ CORRECT: Parallel agent execution\n` +
408
+ `[Single Message]:\n` +
409
+ ` Task("Django Developer", "Build models and views with DRF", "backend-dev")\n` +
410
+ ` Task("Frontend Developer", "Create React frontend with API integration", "coder")\n` +
411
+ ` Task("Test Engineer", "Write pytest tests with fixtures", "tester")\n` +
412
+ ` \n` +
413
+ ` # Batch Python operations\n` +
414
+ ` Write("apps/models.py")\n` +
415
+ ` Write("apps/views.py")\n` +
416
+ ` Write("tests/test_models.py")\n` +
417
+ `\`\`\`\n\n`;
418
+ }
419
+
420
+ getReactConcurrentPatterns() {
421
+ return `### React Development Patterns\n\n` +
422
+ `\`\`\`javascript\n` +
423
+ `// React-specific concurrent patterns\n` +
424
+ `[Single Message]:\n` +
425
+ ` Task("Component Developer", "Build reusable components with TypeScript", "coder")\n` +
426
+ ` Task("State Manager", "Implement Redux/Context state management", "coder")\n` +
427
+ ` Task("Test Engineer", "Write React Testing Library tests", "tester")\n` +
428
+ ` Task("Style Developer", "Create responsive CSS/Styled Components", "coder")\n` +
429
+ `\`\`\`\n\n`;
430
+ }
431
+
432
+ getApiConcurrentPatterns() {
433
+ return `### API Development Patterns\n\n` +
434
+ `\`\`\`bash\n` +
435
+ `# API-focused concurrent execution\n` +
436
+ `[Single Message]:\n` +
437
+ ` Task("API Developer", "Build RESTful endpoints with validation", "backend-dev")\n` +
438
+ ` Task("Database Designer", "Design schema and migrations", "code-analyzer")\n` +
439
+ ` Task("Security Engineer", "Implement authentication and authorization", "reviewer")\n` +
440
+ ` Task("API Tester", "Create integration and unit tests", "tester")\n` +
441
+ ` Task("Documentation Writer", "Generate OpenAPI/Swagger docs", "researcher")\n` +
442
+ `\`\`\`\n\n`;
443
+ }
444
+
445
+ getJavaScriptBestPractices() {
446
+ return `### JavaScript/TypeScript\n` +
447
+ `- **ES6+ Features**: Use modern JavaScript syntax\n` +
448
+ `- **Type Safety**: Prefer TypeScript for larger projects\n` +
449
+ `- **Async/Await**: Use async/await over Promise chains\n` +
450
+ `- **Error Handling**: Implement proper error boundaries\n` +
451
+ `- **Code Splitting**: Lazy load components and routes\n\n`;
452
+ }
453
+
454
+ getPythonBestPractices() {
455
+ return `### Python\n` +
456
+ `- **PEP 8**: Follow Python style guidelines\n` +
457
+ `- **Type Hints**: Use type annotations for clarity\n` +
458
+ `- **Virtual Environments**: Always use venv or conda\n` +
459
+ `- **Docstrings**: Document all functions and classes\n` +
460
+ `- **Error Handling**: Use specific exception types\n\n`;
461
+ }
462
+
463
+ getReactTestingPatterns() {
464
+ return `### React Testing\n\n` +
465
+ `\`\`\`javascript\n` +
466
+ `import { render, screen, fireEvent } from '@testing-library/react';\n` +
467
+ `import userEvent from '@testing-library/user-event';\n` +
468
+ `\n` +
469
+ `// Component testing pattern\n` +
470
+ `describe('Component', () => {\n` +
471
+ ` test('renders and handles interaction', async () => {\n` +
472
+ ` const user = userEvent.setup();\n` +
473
+ ` render(<Component />);\n` +
474
+ ` \n` +
475
+ ` const button = screen.getByRole('button');\n` +
476
+ ` await user.click(button);\n` +
477
+ ` \n` +
478
+ ` expect(screen.getByText(/result/i)).toBeInTheDocument();\n` +
479
+ ` });\n` +
480
+ `});\n` +
481
+ `\`\`\`\n\n`;
482
+ }
483
+
484
+ getJavaScriptTestingPatterns() {
485
+ return `### JavaScript Testing\n\n` +
486
+ `\`\`\`javascript\n` +
487
+ `// Jest testing patterns\n` +
488
+ `describe('API Module', () => {\n` +
489
+ ` beforeEach(() => {\n` +
490
+ ` jest.clearAllMocks();\n` +
491
+ ` });\n` +
492
+ `\n` +
493
+ ` test('handles async operations', async () => {\n` +
494
+ ` const result = await apiCall();\n` +
495
+ ` expect(result).toEqual(expectedResult);\n` +
496
+ ` });\n` +
497
+ `});\n` +
498
+ `\`\`\`\n\n`;
499
+ }
500
+
501
+ getPythonTestingPatterns() {
502
+ return `### Python Testing\n\n` +
503
+ `\`\`\`python\n` +
504
+ `import pytest\n` +
505
+ `from unittest.mock import patch, MagicMock\n` +
506
+ `\n` +
507
+ `class TestAPI:\n` +
508
+ ` @pytest.fixture\n` +
509
+ ` def client(self):\n` +
510
+ ` return TestClient()\n` +
511
+ `\n` +
512
+ ` def test_endpoint(self, client):\n` +
513
+ ` response = client.get("/api/endpoint")\n` +
514
+ ` assert response.status_code == 200\n` +
515
+ ` assert response.json()["status"] == "success"\n` +
516
+ `\`\`\`\n\n`;
517
+ }
518
+
519
+ /**
520
+ * Default base template if none is provided
521
+ */
522
+ getDefaultBaseTemplate() {
523
+ return `# Claude Code Configuration - {{PROJECT_TYPE}} Development Environment
524
+
525
+ ## 🚨 CRITICAL: CONCURRENT EXECUTION & FILE MANAGEMENT
526
+
527
+ **ABSOLUTE RULES**:
528
+ 1. ALL operations MUST be concurrent/parallel in a single message
529
+ 2. **NEVER save working files, text/mds and tests to the root folder**
530
+ 3. ALWAYS organize files in appropriate subdirectories
531
+ 4. **USE CLAUDE CODE'S TASK TOOL** for spawning agents concurrently, not just MCP
532
+
533
+ ### ⚡ GOLDEN RULE: "1 MESSAGE = ALL RELATED OPERATIONS"
534
+
535
+ **MANDATORY PATTERNS:**
536
+ - **TodoWrite**: ALWAYS batch ALL todos in ONE call (5-10+ todos minimum)
537
+ - **Task tool (Claude Code)**: ALWAYS spawn ALL agents in ONE message with full instructions
538
+ - **File operations**: ALWAYS batch ALL reads/writes/edits in ONE message
539
+ - **Bash commands**: ALWAYS batch ALL terminal operations in ONE message
540
+ - **Memory operations**: ALWAYS batch ALL memory store/retrieve in ONE message
541
+
542
+ ## Project Overview
543
+
544
+ **Project Type**: {{PROJECT_TYPE}}
545
+ **Primary Language**: {{PRIMARY_LANGUAGE}}
546
+ **Primary Framework**: {{PRIMARY_FRAMEWORK}}
547
+ **Package Manager**: {{PACKAGE_MANAGER}}
548
+ **Build Tools**: {{BUILD_TOOLS}}
549
+
550
+ **Detected Languages**: {{LANGUAGES_LIST}}
551
+ **Detected Frameworks**: {{FRAMEWORKS_LIST}}
552
+
553
+ *Auto-generated on {{TIMESTAMP}}*
554
+
555
+ ## File Organization Rules
556
+
557
+ **NEVER save to root folder. Use these directories:**
558
+ - \`/src\` - Source code files
559
+ - \`/tests\` - Test files
560
+ - \`/docs\` - Documentation and markdown files
561
+ - \`/config\` - Configuration files
562
+ - \`/scripts\` - Utility scripts
563
+ - \`/examples\` - Example code
564
+ `;
565
+ }
566
+
567
+ /**
568
+ * Save generation preferences
569
+ */
570
+ async savePreferences(preferences) {
571
+ const prefsDir = path.join(this.options.preferencesPath);
572
+ const prefsFile = path.join(prefsDir, 'generation.json');
573
+
574
+ // Ensure directory exists
575
+ await fs.mkdir(prefsDir, { recursive: true });
576
+
577
+ // Merge with existing preferences
578
+ const updatedPrefs = { ...this.userPreferences, ...preferences };
579
+ await fs.writeFile(prefsFile, JSON.stringify(updatedPrefs, null, 2));
580
+
581
+ this.userPreferences = updatedPrefs;
582
+ console.log('⚙️ Preferences saved');
583
+ }
584
+
585
+ /**
586
+ * Update CLAUDE.md for specific language/framework addition
587
+ */
588
+ async updateForNewTechnology(technology, type = 'framework') {
589
+ console.log(`🔄 Updating CLAUDE.md for new ${type}: ${technology}`);
590
+
591
+ // Re-detect to get updated information
592
+ this.detectionResults = await this.detector.detectProject();
593
+
594
+ // Load existing content
595
+ const existing = await this.loadExistingClaudeMd();
596
+ if (!existing) {
597
+ return this.generateClaudeMd();
598
+ }
599
+
600
+ // Generate new sections for the technology
601
+ let newSection = '';
602
+ if (type === 'framework' && this.templates[technology]) {
603
+ newSection = `\n\n## ${technology.charAt(0).toUpperCase() + technology.slice(1)} Framework Configuration\n\n`;
604
+ newSection += this.templates[technology];
605
+ } else if (type === 'language' && this.templates[technology]) {
606
+ newSection = `\n\n## ${technology.charAt(0).toUpperCase() + technology.slice(1)} Configuration\n\n`;
607
+ newSection += this.templates[technology];
608
+ }
609
+
610
+ if (newSection) {
611
+ const updatedContent = existing + newSection;
612
+ await this.writeClaudeMd(updatedContent);
613
+ console.log(`✅ Added ${technology} section to CLAUDE.md`);
614
+ }
615
+ }
616
+ }
617
+
618
+ export default ClaudeMdGenerator;