#!/usr/bin/env node import { program } from 'commander'; import chalk from 'chalk'; import prompts from 'prompts'; import ora from 'ora'; import fs from 'fs-extra'; import path from 'path'; import { fileURLToPath } from 'url'; import { execSync } from 'child_process'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const TEMPLATE_DIR = path.join(__dirname, 'template'); async function main() { console.log(chalk.bold.cyan('\n🤖 Create Agentic App\n')); program .name('create-agentic-app') .description('Scaffold a new agentic AI application') .argument('[project-directory]', 'Project directory name (use "." for current directory)') .parse(process.argv); const args = program.args; let projectDir = args[0] || '.'; // Resolve the target directory const targetDir = path.resolve(process.cwd(), projectDir); const projectName = projectDir === '.' ? path.basename(targetDir) : projectDir; // Check if directory exists and is not empty if (fs.existsSync(targetDir)) { const files = fs.readdirSync(targetDir); if (files.length > 0 && projectDir !== '.') { const { proceed } = await prompts({ type: 'confirm', name: 'proceed', message: `Directory "${projectDir}" is not empty. Continue anyway?`, initial: false }); if (!proceed) { console.log(chalk.yellow('Cancelled.')); process.exit(0); } } } // Prompt for package manager const { packageManager } = await prompts({ type: 'select', name: 'packageManager', message: 'Which package manager do you want to use?', choices: [ { title: 'pnpm (recommended)', value: 'pnpm' }, { title: 'npm', value: 'npm' }, { title: 'yarn', value: 'yarn' } ], initial: 0 }); if (!packageManager) { console.log(chalk.yellow('Cancelled.')); process.exit(0); } console.log(); const spinner = ora('Creating project...').start(); try { // Create target directory if it doesn't exist fs.ensureDirSync(targetDir); // Copy template files spinner.text = 'Copying template files...'; await fs.copy(TEMPLATE_DIR, targetDir, { overwrite: false, errorOnExist: false, filter: (src) => { // Skip node_modules, .next, and other build artifacts const relativePath = path.relative(TEMPLATE_DIR, src); return !relativePath.includes('node_modules') && !relativePath.includes('.next') && !relativePath.includes('.git') && !relativePath.includes('pnpm-lock.yaml') && !relativePath.includes('package-lock.json') && !relativePath.includes('yarn.lock') && !relativePath.includes('tsconfig.tsbuildinfo'); } }); // Copy .env.example to .env if it doesn't exist const envExamplePath = path.join(targetDir, 'env.example'); const envPath = path.join(targetDir, '.env'); if (fs.existsSync(envExamplePath) && !fs.existsSync(envPath)) { spinner.text = 'Setting up environment file...'; await fs.copy(envExamplePath, envPath); } // Update package.json name if not current directory if (projectDir !== '.') { const packageJsonPath = path.join(targetDir, 'package.json'); if (fs.existsSync(packageJsonPath)) { const packageJson = await fs.readJson(packageJsonPath); packageJson.name = projectName; await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 }); } } spinner.succeed(chalk.green('Project created successfully!')); // Install dependencies console.log(); const installSpinner = ora(`Installing dependencies with ${packageManager}...`).start(); try { const installCmd = packageManager === 'yarn' ? 'yarn install' : `${packageManager} install`; execSync(installCmd, { cwd: targetDir, stdio: 'pipe' }); installSpinner.succeed(chalk.green('Dependencies installed!')); } catch (error) { installSpinner.fail(chalk.red('Failed to install dependencies')); console.log(chalk.yellow(`\nPlease run "${packageManager} install" manually.\n`)); } // Display next steps console.log(); console.log(chalk.bold.green('✨ Your agentic app is ready!\n')); console.log(chalk.bold('Next steps:\n')); if (projectDir !== '.') { console.log(chalk.cyan(` cd ${projectDir}`)); } console.log(chalk.cyan(' 1. Update the .env file with your API keys and database credentials')); console.log(chalk.cyan(` 2. Start the database: docker compose up -d`)); console.log(chalk.cyan(` 3. Run database migrations: ${packageManager} run db:migrate`)); console.log(chalk.cyan(` 4. Start the development server: ${packageManager} run dev`)); console.log(); console.log(chalk.gray('For more information, check out the README.md file.\n')); } catch (error) { spinner.fail(chalk.red('Failed to create project')); console.error(error); process.exit(1); } } main().catch(console.error);