```typescript
#!/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";
// ============================================
// Setup
// ============================================
const program = new Command();
const version = "1.0.0";
program
.name("my-cli")
.description("A cool CLI tool built with TypeScript")
.version(version);
// ============================================
// Commands
// ============================================
program
.command("init")
.description("Initialize a new project")
.option("-f, --force", "Overwrite existing files")
.action(async (options) => {
console.log(chalk.blue("🚀 Initializing project..."));
// Interactive prompts
const answers = await inquirer.prompt([
{
type: "input",
name: "projectName",
message: "What is the name of your project?",
default: "my-app",
},
{
type: "list",
name: "template",
message: "Which template would you like to use?",
choices: ["React", "Vue", "Node.js API"],
},
{
type: "confirm",
name: "typescript",
message: "Use TypeScript?",
default: true,
},
]);
const targetDir = path.resolve(process.cwd(), answers.projectName);
// Check if exists
if (fs.existsSync(targetDir) && !options.force) {
console.error(
chalk.red("Error: Directory already exists. Use -f to overwrite."),
);
process.exit(1);
}
// Spinner
const spinner = ora("Creating project structure...").start();
try {
await new Promise((resolve) => setTimeout(resolve, 1500)); // Simulate work
// In reality: await fs.copy(templateDir, targetDir)
if (options.force) {
spinner.text = "Overwriting existing files...";
}
spinner.succeed(
chalk.green(`Successfully created project ${answers.projectName}!`),
);
console.log("\nNext steps:");
console.log(` cd ${answers.projectName}`);
console.log(" npm install");
console.log(" npm start\n");
} catch (error) {
spinner.fail("Failed to create project");
console.error(error);
}
});
program
.command("generate <type> [name]")
.description("Generate a new component or file")
.action((type, name) => {
if (!["component", "hook", "page"].includes(type)) {
console.error(
chalk.red(
`Invalid type: ${type}. Must be one of: component, hook, page`,
),
);
process.exit(1);
}
if (!name) {
console.error(chalk.red("Name is required"));
process.exit(1);
}
console.log(`Generating ${type}: ${chalk.cyan(name)}`);
// Logic to generate file...
});
// ============================================
// Run
// ============================================
program.parse(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp();
}
```