index.ts•9.27 kB
#!/usr/bin/env node
import { Command } from "commander";
import inquirer from "inquirer";
import chalk from "chalk";
import ora from "ora";
import fs from "fs-extra";
import path from "path";
const program = new Command();
// ASCII Art Banner
const banner = `
╦ ╦╦╔╗ ╔═╗ ╔═╗╔═╗╔╦╗╦╔╗╔╔═╗
╚╗╔╝║╠╩╗║╣ ║ ║ ║ ║║║║║║║ ╦
╚╝ ╩╚═╝╚═╝ ╚═╝╚═╝═╩╝╩╝╚╝╚═╝
${chalk.gray("Conversation-Driven Development Framework")}
`;
program
.name("vibecoding")
.description("VibeCoding - Rapid MVP/POC Development through Conversation")
.version("1.0.0");
// Init command
program
.command("init")
.description("Initialize a new VibeCoding project")
.option("-n, --name <name>", "Project name")
.option("-d, --description <description>", "Project description")
.action(async (options) => {
console.log(chalk.cyan(banner));
let { name, description } = options;
// Interactive prompts if not provided via flags
if (!name || !description) {
const answers = await inquirer.prompt([
{
type: "input",
name: "name",
message: "Project name:",
default: path.basename(process.cwd()),
when: !name,
},
{
type: "input",
name: "description",
message: "Project description:",
default: "A VibeCoding project",
when: !description,
},
]);
name = name || answers.name;
description = description || answers.description;
}
const spinner = ora("Initializing VibeCoding project...").start();
try {
// Check if already initialized
if (fs.existsSync(".vibecoding")) {
spinner.fail("VibeCoding project already initialized in this directory");
process.exit(1);
}
// Create directory structure
const dirs = [
".vibecoding/config",
".vibecoding/context",
".vibecoding/conversations",
"vibe-services",
"0_discovery/conversations",
"0_discovery/clarifications",
"0_discovery/requirements",
"1_design/architecture",
"1_design/api-contracts",
"1_design/flow-diagrams",
"2_implementation/src",
"2_implementation/tests",
"2_implementation/scripts",
"3_validation/test-reports",
"3_validation/quality-metrics",
"3_validation/benchmarks",
"4_deployment/environments",
"4_deployment/ci-cd",
"4_deployment/monitoring",
"knowledge-base/patterns",
"knowledge-base/solutions",
"knowledge-base/retrospectives",
];
for (const dir of dirs) {
fs.ensureDirSync(dir);
}
// Create config file
const config = {
version: "1.0.0",
projectName: name,
description: description,
services: {
contextManager: {
enabled: true,
persistentStorage: ".vibecoding/context",
sessionTimeout: 86400,
maxHistorySize: 1000,
},
codeGenerator: {
enabled: true,
aiProvider: "anthropic",
model: "claude-3-sonnet",
temperature: 0.7,
},
dependencyTracker: {
enabled: true,
autoUpdate: true,
vulnerabilityScanning: true,
},
testValidator: {
enabled: true,
coverage: {
threshold: 80,
enforceThreshold: false,
},
},
docGenerator: {
enabled: true,
autoGenerate: true,
formats: ["markdown", "html", "pdf"],
},
deploymentManager: {
enabled: true,
environments: ["development", "staging", "production"],
cicdProvider: "github-actions",
},
},
workflow: {
phases: ["discovery", "design", "implementation", "validation", "deployment"],
autoProgressTracking: true,
},
knowledgeBase: {
autoCapture: true,
categories: ["patterns", "solutions", "retrospectives"],
},
};
fs.writeJsonSync(".vibecoding/config/vibe.config.json", config, { spaces: 2 });
// Create README
const readme = `# ${name}
${description}
## VibeCoding Project
This project uses VibeCoding - a conversation-driven development framework for rapid MVP/POC creation.
### Quick Start
\`\`\`bash
# Start a conversation-driven development session
vibecoding chat
# Check project status
vibecoding status
# Generate documentation
vibecoding docs
\`\`\`
### Project Structure
- \`0_discovery/\` - Requirement gathering and clarifications
- \`1_design/\` - Architecture and API design
- \`2_implementation/\` - Source code and tests
- \`3_validation/\` - Test reports and quality metrics
- \`4_deployment/\` - Deployment configurations
- \`knowledge-base/\` - Patterns and solutions
### Services
All VibeCoding services are configured in \`.vibecoding/config/vibe.config.json\`.
`;
fs.writeFileSync("README.md", readme);
spinner.succeed(`VibeCoding project "${name}" initialized successfully!`);
console.log("\n" + chalk.green("✓") + " Created project structure");
console.log(chalk.green("✓") + " Generated configuration");
console.log(chalk.green("✓") + " Created README.md");
console.log("\n" + chalk.cyan("Next steps:"));
console.log(" 1. Run " + chalk.yellow("vibecoding chat") + " to start development");
console.log(" 2. Run " + chalk.yellow("vibecoding status") + " to check project status");
} catch (error) {
spinner.fail("Failed to initialize project");
console.error(error);
process.exit(1);
}
});
// Chat command
program
.command("chat")
.description("Start a conversation-driven development session")
.action(async () => {
console.log(chalk.cyan(banner));
// Check if initialized
if (!fs.existsSync(".vibecoding")) {
console.error(chalk.red("Error: Not a VibeCoding project. Run 'vibecoding init' first."));
process.exit(1);
}
console.log(chalk.green("Starting VibeCoding conversation session...\n"));
// This would integrate with the actual MCP services
console.log(chalk.yellow("🤖 VibeCoding Assistant:") + " Hello! I'm ready to help you build your project.");
console.log(" What would you like to work on today?\n");
const phases = ["Discovery", "Design", "Implementation", "Validation", "Deployment"];
const { phase } = await inquirer.prompt([
{
type: "list",
name: "phase",
message: "Which phase would you like to focus on?",
choices: phases,
},
]);
console.log(`\n${chalk.green("Selected:")} ${phase} phase`);
console.log(chalk.gray("(Full conversation interface would be implemented here)"));
});
// Status command
program
.command("status")
.description("Check project status")
.action(async () => {
console.log(chalk.cyan(banner));
if (!fs.existsSync(".vibecoding")) {
console.error(chalk.red("Error: Not a VibeCoding project."));
process.exit(1);
}
const config = fs.readJsonSync(".vibecoding/config/vibe.config.json");
console.log(chalk.bold("Project:") + ` ${config.projectName}`);
console.log(chalk.bold("Description:") + ` ${config.description}\n`);
console.log(chalk.bold("Services Status:"));
for (const [service, settings] of Object.entries(config.services)) {
const status = (settings as any).enabled ? chalk.green("✓ Enabled") : chalk.red("✗ Disabled");
console.log(` ${service}: ${status}`);
}
console.log("\n" + chalk.bold("Workflow Phases:"));
config.workflow.phases.forEach((phase: string, index: number) => {
console.log(` ${index + 1}. ${phase}`);
});
});
// Docs command
program
.command("docs")
.description("Generate project documentation")
.option("-f, --format <format>", "Output format (markdown|html|pdf)", "markdown")
.action(async (options) => {
const spinner = ora("Generating documentation...").start();
try {
// Placeholder for documentation generation
await new Promise(resolve => setTimeout(resolve, 2000));
spinner.succeed(`Documentation generated in ${options.format} format`);
console.log(chalk.green("✓") + ` Documentation saved to docs/`);
} catch (error) {
spinner.fail("Failed to generate documentation");
console.error(error);
}
});
// Service command
program
.command("service <action> <name>")
.description("Manage VibeCoding services (start|stop|restart)")
.action(async (action, name) => {
console.log(`${action}ing service: ${name}...`);
// Service management logic would go here
});
// Parse arguments
program.parse(process.argv);
// Show help if no command provided
if (!process.argv.slice(2).length) {
console.log(chalk.cyan(banner));
program.outputHelp();
}