#!/usr/bin/env node import fs from "fs"; import path from "path"; import readline from "readline"; import { ROOT_FOLDER } from "./constants.mjs"; const PLUGINS_DIR = path.join(ROOT_FOLDER, "plugins"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); function prompt(question) { return new Promise((resolve) => { rl.question(question, resolve); }); } function parseArgs() { const args = process.argv.slice(2); const out = { name: undefined, tags: undefined }; for (let i = 0; i < args.length; i++) { const a = args[i]; if (a === "--name" || a === "-n") { out.name = args[i + 1]; i++; } else if (a.startsWith("--name=")) { out.name = a.split("=")[1]; } else if (a === "--tags" || a === "-t") { out.tags = args[i + 1]; i++; } else if (a.startsWith("--tags=")) { out.tags = a.split("=")[1]; } else if (!a.startsWith("-") && !out.name) { // first positional -> name out.name = a; } else if (!a.startsWith("-") && out.name && !out.tags) { // second positional -> tags out.tags = a; } } if (Array.isArray(out.tags)) { out.tags = out.tags.join(","); } return out; } async function createPlugin() { try { console.log("šŸ”Œ Plugin Creator"); console.log("This tool will help you create a new plugin.\n"); const parsed = parseArgs(); // Get plugin ID let pluginId = parsed.name; if (!pluginId) { pluginId = await prompt("Plugin ID (lowercase, hyphens only): "); } if (!pluginId) { console.error("āŒ Plugin ID is required"); process.exit(1); } if (!/^[a-z0-9-]+$/.test(pluginId)) { console.error( "āŒ Plugin ID must contain only lowercase letters, numbers, and hyphens" ); process.exit(1); } const pluginDir = path.join(PLUGINS_DIR, pluginId); // Check if plugin already exists if (fs.existsSync(pluginDir)) { console.log( `āš ļø Plugin ${pluginId} already exists at ${pluginDir}` ); console.log("šŸ’” Please edit that plugin instead or choose a different ID."); process.exit(1); } // Get display name const defaultDisplayName = pluginId .split("-") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(" "); let displayName = await prompt( `Display name (default: ${defaultDisplayName}): ` ); if (!displayName.trim()) { displayName = defaultDisplayName; } // Get description const defaultDescription = `A plugin for ${displayName.toLowerCase()}.`; let description = await prompt( `Description (default: ${defaultDescription}): ` ); if (!description.trim()) { description = defaultDescription; } // Get tags let tags = []; let tagInput = parsed.tags; if (!tagInput) { tagInput = await prompt( "Tags (comma-separated, or press Enter for defaults): " ); } if (tagInput && tagInput.toString().trim()) { tags = tagInput .toString() .split(",") .map((tag) => tag.trim()) .filter((tag) => tag); } else { tags = pluginId.split("-").slice(0, 3); } // Create directory structure const githubPluginDir = path.join(pluginDir, ".github", "plugin"); fs.mkdirSync(githubPluginDir, { recursive: true }); // Generate plugin.json const pluginJson = { name: pluginId, description, version: "1.0.0", author: { name: "Awesome Copilot Community" }, repository: "https://github.com/github/awesome-copilot", license: "MIT", tags, items: [], }; fs.writeFileSync( path.join(githubPluginDir, "plugin.json"), JSON.stringify(pluginJson, null, 2) + "\n" ); // Generate README.md const readmeContent = `# ${displayName} Plugin ${description} ## Installation \`\`\`bash copilot plugin install ${pluginId}@awesome-copilot \`\`\` ## What's Included _Add your plugin contents here._ ## Source This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). ## License MIT `; fs.writeFileSync(path.join(pluginDir, "README.md"), readmeContent); console.log(`\nāœ… Created plugin: ${pluginDir}`); console.log("\nšŸ“ Next steps:"); console.log(`1. Add agents, prompts, or instructions to plugins/${pluginId}/`); console.log(`2. Update plugins/${pluginId}/.github/plugin/plugin.json to list your items`); console.log(`3. Edit plugins/${pluginId}/README.md to describe your plugin`); console.log("4. Run 'npm run build' to regenerate documentation"); } catch (error) { console.error(`āŒ Error creating plugin: ${error.message}`); process.exit(1); } finally { rl.close(); } } createPlugin();