@vibe-dev-kit/cli
Version:
Advanced Command-line toolkit that analyzes your codebase and deploys project-aware rules, memories, commands and agents to any AI coding assistant - VDK is the world's first Vibe Development Kit
205 lines (170 loc) • 6.34 kB
JavaScript
/**
* Project Insights Generator
* Generates analytics and insights about projects using VDK
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const colors = {
green: '\x1b[32m',
blue: '\x1b[36m',
yellow: '\x1b[33m',
red: '\x1b[31m',
reset: '\x1b[0m',
bright: '\x1b[1m',
};
function log(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
/**
* Analyze project rules and generate insights
* @param {string} projectPath - Path to project directory
* @returns {Object} Project insights
*/
function generateProjectInsights(projectPath = process.cwd()) {
const rulesPath = path.join(projectPath, '.ai', 'rules');
if (!fs.existsSync(rulesPath)) {
return {
error: 'No VDK rules found. Run `vdk` to set up rules first.',
hasRules: false,
};
}
const insights = {
hasRules: true,
rulesCount: 0,
ruleTypes: {},
technologies: new Set(),
frameworks: new Set(),
languages: new Set(),
lastUpdated: null,
projectSize: 'unknown',
recommendations: [],
};
try {
// Analyze rule files
const ruleFiles = fs.readdirSync(rulesPath).filter((f) => f.endsWith('.mdc'));
insights.rulesCount = ruleFiles.length;
let latestTime = 0;
for (const file of ruleFiles) {
const filePath = path.join(rulesPath, file);
const stats = fs.statSync(filePath);
if (stats.mtime.getTime() > latestTime) {
latestTime = stats.mtime.getTime();
insights.lastUpdated = stats.mtime.toISOString();
}
// Categorize rule types
const content = fs.readFileSync(filePath, 'utf8');
if (file.includes('project-context')) insights.ruleTypes.context = true;
if (
file.includes('framework') ||
content.includes('React') ||
content.includes('Vue') ||
content.includes('Angular')
) {
insights.ruleTypes.framework = true;
// Extract framework info
if (content.includes('React')) insights.frameworks.add('React');
if (content.includes('Vue')) insights.frameworks.add('Vue');
if (content.includes('Angular')) insights.frameworks.add('Angular');
if (content.includes('Next.js')) insights.frameworks.add('Next.js');
if (content.includes('Django')) insights.frameworks.add('Django');
if (content.includes('Express')) insights.frameworks.add('Express');
}
if (
file.includes('language') ||
content.includes('TypeScript') ||
content.includes('Python')
) {
insights.ruleTypes.language = true;
// Extract language info
if (content.includes('TypeScript')) insights.languages.add('TypeScript');
if (content.includes('JavaScript')) insights.languages.add('JavaScript');
if (content.includes('Python')) insights.languages.add('Python');
if (content.includes('Java')) insights.languages.add('Java');
if (content.includes('Go')) insights.languages.add('Go');
}
if (file.includes('common-errors')) insights.ruleTypes.errorHandling = true;
if (file.includes('mcp-configuration')) insights.ruleTypes.mcpConfig = true;
}
// Convert sets to arrays for JSON serialization
insights.technologies = Array.from(insights.technologies);
insights.frameworks = Array.from(insights.frameworks);
insights.languages = Array.from(insights.languages);
// Generate recommendations
if (insights.rulesCount < 3) {
insights.recommendations.push(
'Consider running the setup wizard again to generate more comprehensive rules'
);
}
if (!insights.ruleTypes.errorHandling) {
insights.recommendations.push('Add common error handling patterns to improve AI suggestions');
}
if (!insights.ruleTypes.mcpConfig && insights.frameworks.length > 0) {
insights.recommendations.push('Configure MCP settings for better IDE integration');
}
// Estimate project size based on rule complexity
if (insights.rulesCount >= 5 && insights.frameworks.length >= 2) {
insights.projectSize = 'large';
} else if (insights.rulesCount >= 3 && insights.frameworks.length >= 1) {
insights.projectSize = 'medium';
} else {
insights.projectSize = 'small';
}
} catch (error) {
insights.error = `Failed to analyze rules: ${error.message}`;
}
return insights;
}
/**
* Display insights in a formatted way
* @param {Object} insights - Project insights object
*/
function displayInsights(insights) {
if (!insights.hasRules) {
log('❌ No VDK rules found', 'red');
log(insights.error, 'yellow');
return;
}
log('📊 Project Insights', 'blue');
log('==================', 'blue');
log('');
log(`Rules Count: ${insights.rulesCount}`, 'green');
log(`Project Size: ${insights.projectSize}`, 'green');
log(
`Last Updated: ${insights.lastUpdated ? new Date(insights.lastUpdated).toLocaleDateString() : 'Unknown'}`,
'green'
);
if (insights.languages.length > 0) {
log(`Languages: ${insights.languages.join(', ')}`, 'green');
}
if (insights.frameworks.length > 0) {
log(`Frameworks: ${insights.frameworks.join(', ')}`, 'green');
}
log('');
log('Rule Types:', 'yellow');
if (insights.ruleTypes.context) log(' ✅ Project Context', 'green');
if (insights.ruleTypes.framework) log(' ✅ Framework Rules', 'green');
if (insights.ruleTypes.language) log(' ✅ Language Rules', 'green');
if (insights.ruleTypes.errorHandling) log(' ✅ Error Handling', 'green');
if (insights.ruleTypes.mcpConfig) log(' ✅ MCP Configuration', 'green');
if (insights.recommendations.length > 0) {
log('');
log('💡 Recommendations:', 'yellow');
for (const rec of insights.recommendations) {
log(` • ${rec}`, 'yellow');
}
}
}
// CLI usage
if (import.meta.url === `file://${process.argv[1]}`) {
const projectPath = process.argv[2] || process.cwd();
const insights = generateProjectInsights(projectPath);
if (process.argv.includes('--json')) {
console.log(JSON.stringify(insights, null, 2));
} else {
displayInsights(insights);
}
}
export { displayInsights, generateProjectInsights };