make bmad support for opencode
This commit is contained in:
parent
2b247ea385
commit
df6c9eeb7a
|
|
@ -46,3 +46,4 @@ test-project-install/*
|
|||
sample-project/*
|
||||
flattened-codebase.xml
|
||||
*.stats.md
|
||||
dist/
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const { program } = require('commander');
|
||||
const path = require('node:path');
|
||||
const fs = require('node:fs').promises;
|
||||
const yaml = require('js-yaml');
|
||||
const chalk = require('chalk').default || require('chalk');
|
||||
const inquirer = require('inquirer').default || require('inquirer');
|
||||
const semver = require('semver');
|
||||
const https = require('node:https');
|
||||
const { program } = require("commander");
|
||||
const path = require("node:path");
|
||||
const fs = require("node:fs").promises;
|
||||
const yaml = require("js-yaml");
|
||||
const chalk = require("chalk").default || require("chalk");
|
||||
const inquirer = require("inquirer").default || require("inquirer");
|
||||
const semver = require("semver");
|
||||
const https = require("node:https");
|
||||
|
||||
// Handle both execution contexts (from root via npx or from installer directory)
|
||||
let version;
|
||||
|
|
@ -15,20 +15,22 @@ let installer;
|
|||
let packageName;
|
||||
try {
|
||||
// Try installer context first (when run from tools/installer/)
|
||||
version = require('../package.json').version;
|
||||
packageName = require('../package.json').name;
|
||||
installer = require('../lib/installer');
|
||||
version = require("../package.json").version;
|
||||
packageName = require("../package.json").name;
|
||||
installer = require("../lib/installer");
|
||||
} catch (error) {
|
||||
// Fall back to root context (when run via npx from GitHub)
|
||||
console.log(`Installer context not found (${error.message}), trying root context...`);
|
||||
console.log(
|
||||
`Installer context not found (${error.message}), trying root context...`,
|
||||
);
|
||||
try {
|
||||
version = require('../../../package.json').version;
|
||||
installer = require('../../../tools/installer/lib/installer');
|
||||
version = require("../../../package.json").version;
|
||||
installer = require("../../../tools/installer/lib/installer");
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'Error: Could not load required modules. Please ensure you are running from the correct directory.',
|
||||
"Error: Could not load required modules. Please ensure you are running from the correct directory.",
|
||||
);
|
||||
console.error('Debug info:', {
|
||||
console.error("Debug info:", {
|
||||
__dirname,
|
||||
cwd: process.cwd(),
|
||||
error: error.message,
|
||||
|
|
@ -39,21 +41,23 @@ try {
|
|||
|
||||
program
|
||||
.version(version)
|
||||
.description('BMad Method installer - Universal AI agent framework for any domain');
|
||||
.description(
|
||||
"BMad Method installer - Universal AI agent framework for any domain",
|
||||
);
|
||||
|
||||
program
|
||||
.command('install')
|
||||
.description('Install BMad Method agents and tools')
|
||||
.option('-f, --full', 'Install complete BMad Method')
|
||||
.option('-x, --expansion-only', 'Install only expansion packs (no bmad-core)')
|
||||
.option('-d, --directory <path>', 'Installation directory')
|
||||
.command("install")
|
||||
.description("Install BMad Method agents and tools")
|
||||
.option("-f, --full", "Install complete BMad Method")
|
||||
.option("-x, --expansion-only", "Install only expansion packs (no bmad-core)")
|
||||
.option("-d, --directory <path>", "Installation directory")
|
||||
.option(
|
||||
'-i, --ide <ide...>',
|
||||
'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, codex, codex-web, auggie-cli, iflow-cli, other)',
|
||||
"-i, --ide <ide...>",
|
||||
"Configure for specific IDE(s) - can specify multiple (opencode, cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, codex, codex-web, auggie-cli, iflow-cli, other)",
|
||||
)
|
||||
.option(
|
||||
'-e, --expansion-packs <packs...>',
|
||||
'Install specific expansion packs (can specify multiple)',
|
||||
"-e, --expansion-packs <packs...>",
|
||||
"Install specific expansion packs (can specify multiple)",
|
||||
)
|
||||
.action(async (options) => {
|
||||
try {
|
||||
|
|
@ -66,59 +70,65 @@ program
|
|||
}
|
||||
} else {
|
||||
// Direct mode
|
||||
let installType = 'full';
|
||||
if (options.expansionOnly) installType = 'expansion-only';
|
||||
let installType = "full";
|
||||
if (options.expansionOnly) installType = "expansion-only";
|
||||
|
||||
const config = {
|
||||
installType,
|
||||
directory: options.directory || '.',
|
||||
ides: (options.ide || []).filter((ide) => ide !== 'other'),
|
||||
directory: options.directory || ".",
|
||||
ides: (options.ide || []).filter((ide) => ide !== "other"),
|
||||
expansionPacks: options.expansionPacks || [],
|
||||
};
|
||||
await installer.install(config);
|
||||
process.exit(0);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Installation failed:'), error.message);
|
||||
console.error(chalk.red("Installation failed:"), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('update')
|
||||
.description('Update existing BMad installation')
|
||||
.option('--force', 'Force update, overwriting modified files')
|
||||
.option('--dry-run', 'Show what would be updated without making changes')
|
||||
.command("update")
|
||||
.description("Update existing BMad installation")
|
||||
.option("--force", "Force update, overwriting modified files")
|
||||
.option("--dry-run", "Show what would be updated without making changes")
|
||||
.action(async () => {
|
||||
try {
|
||||
await installer.update();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Update failed:'), error.message);
|
||||
console.error(chalk.red("Update failed:"), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
// Command to check if updates are available
|
||||
program
|
||||
.command('update-check')
|
||||
.description('Check for BMad Update')
|
||||
.command("update-check")
|
||||
.description("Check for BMad Update")
|
||||
.action(async () => {
|
||||
console.log('Checking for updates...');
|
||||
console.log("Checking for updates...");
|
||||
|
||||
// Make HTTP request to npm registry for latest version info
|
||||
const req = https.get(`https://registry.npmjs.org/${packageName}/latest`, (res) => {
|
||||
const req = https.get(
|
||||
`https://registry.npmjs.org/${packageName}/latest`,
|
||||
(res) => {
|
||||
// Check for HTTP errors (non-200 status codes)
|
||||
if (res.statusCode !== 200) {
|
||||
console.error(chalk.red(`Update check failed: Received status code ${res.statusCode}`));
|
||||
console.error(
|
||||
chalk.red(
|
||||
`Update check failed: Received status code ${res.statusCode}`,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Accumulate response data chunks
|
||||
let data = '';
|
||||
res.on('data', (chunk) => (data += chunk));
|
||||
let data = "";
|
||||
res.on("data", (chunk) => (data += chunk));
|
||||
|
||||
// Process complete response
|
||||
res.on('end', () => {
|
||||
res.on("end", () => {
|
||||
try {
|
||||
// Parse npm registry response and extract version
|
||||
const latest = JSON.parse(data).version;
|
||||
|
|
@ -126,68 +136,76 @@ program
|
|||
// Compare versions using semver
|
||||
if (semver.gt(latest, version)) {
|
||||
console.log(
|
||||
chalk.bold.blue(`⚠️ ${packageName} update available: ${version} → ${latest}`),
|
||||
chalk.bold.blue(
|
||||
`! ${packageName} update available: ${version} → ${latest}`,
|
||||
),
|
||||
);
|
||||
console.log(chalk.bold.blue('\nInstall latest by running:'));
|
||||
console.log(chalk.bold.magenta(` npm install ${packageName}@latest`));
|
||||
console.log(chalk.dim(' or'));
|
||||
console.log(chalk.bold.blue("\nInstall latest by running:"));
|
||||
console.log(
|
||||
chalk.bold.magenta(` npm install ${packageName}@latest`),
|
||||
);
|
||||
console.log(chalk.dim(" or"));
|
||||
console.log(chalk.bold.magenta(` npx ${packageName}@latest`));
|
||||
} else {
|
||||
console.log(chalk.bold.blue(`✨ ${packageName} is up to date`));
|
||||
}
|
||||
} catch (error) {
|
||||
// Handle JSON parsing errors
|
||||
console.error(chalk.red('Failed to parse npm registry data:'), error.message);
|
||||
console.error(
|
||||
chalk.red("Failed to parse npm registry data:"),
|
||||
error.message,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Handle network/connection errors
|
||||
req.on('error', (error) => {
|
||||
console.error(chalk.red('Update check failed:'), error.message);
|
||||
req.on("error", (error) => {
|
||||
console.error(chalk.red("Update check failed:"), error.message);
|
||||
});
|
||||
|
||||
// Set 30 second timeout to prevent hanging
|
||||
req.setTimeout(30_000, () => {
|
||||
req.destroy();
|
||||
console.error(chalk.red('Update check timed out'));
|
||||
console.error(chalk.red("Update check timed out"));
|
||||
});
|
||||
});
|
||||
|
||||
program
|
||||
.command('list:expansions')
|
||||
.description('List available expansion packs')
|
||||
.command("list:expansions")
|
||||
.description("List available expansion packs")
|
||||
.action(async () => {
|
||||
try {
|
||||
await installer.listExpansionPacks();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
console.error(chalk.red("Error:"), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('status')
|
||||
.description('Show installation status')
|
||||
.command("status")
|
||||
.description("Show installation status")
|
||||
.action(async () => {
|
||||
try {
|
||||
await installer.showStatus();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
console.error(chalk.red("Error:"), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('flatten')
|
||||
.description('Flatten codebase to XML format')
|
||||
.option('-i, --input <path>', 'Input directory to flatten', process.cwd())
|
||||
.option('-o, --output <path>', 'Output file path', 'flattened-codebase.xml')
|
||||
.command("flatten")
|
||||
.description("Flatten codebase to XML format")
|
||||
.option("-i, --input <path>", "Input directory to flatten", process.cwd())
|
||||
.option("-o, --output <path>", "Output file path", "flattened-codebase.xml")
|
||||
.action(async (options) => {
|
||||
try {
|
||||
await installer.flatten(options);
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Flatten failed:'), error.message);
|
||||
console.error(chalk.red("Flatten failed:"), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
|
@ -205,7 +223,9 @@ async function promptInstallation() {
|
|||
`),
|
||||
);
|
||||
|
||||
console.log(chalk.bold.magenta('🚀 Universal AI Agent Framework for Any Domain'));
|
||||
console.log(
|
||||
chalk.bold.magenta("🚀 Universal AI Agent Framework for Any Domain"),
|
||||
);
|
||||
console.log(chalk.bold.blue(`✨ Installer v${version}\n`));
|
||||
|
||||
const answers = {};
|
||||
|
|
@ -213,13 +233,14 @@ async function promptInstallation() {
|
|||
// Ask for installation directory first
|
||||
const { directory } = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'directory',
|
||||
message: 'Enter the full path to your project directory where BMad should be installed:',
|
||||
default: path.resolve('.'),
|
||||
type: "input",
|
||||
name: "directory",
|
||||
message:
|
||||
"Enter the full path to your project directory where BMad should be installed:",
|
||||
default: path.resolve("."),
|
||||
validate: (input) => {
|
||||
if (!input.trim()) {
|
||||
return 'Please enter a valid project path';
|
||||
return "Please enter a valid project path";
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
|
@ -241,14 +262,21 @@ async function promptInstallation() {
|
|||
const choices = [];
|
||||
|
||||
// Load core config to get short-title
|
||||
const coreConfigPath = path.join(__dirname, '..', '..', '..', 'bmad-core', 'core-config.yaml');
|
||||
const coreConfig = yaml.load(await fs.readFile(coreConfigPath, 'utf8'));
|
||||
const coreShortTitle = coreConfig['short-title'] || 'BMad Agile Core System';
|
||||
const coreConfigPath = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"bmad-core",
|
||||
"core-config.yaml",
|
||||
);
|
||||
const coreConfig = yaml.load(await fs.readFile(coreConfigPath, "utf8"));
|
||||
const coreShortTitle = coreConfig["short-title"] || "BMad Agile Core System";
|
||||
|
||||
// Add BMad core option
|
||||
let bmadOptionText;
|
||||
if (state.type === 'v4_existing') {
|
||||
const currentVersion = state.manifest?.version || 'unknown';
|
||||
if (state.type === "v4_existing") {
|
||||
const currentVersion = state.manifest?.version || "unknown";
|
||||
const newVersion = version; // Always use package.json version
|
||||
const versionInfo =
|
||||
currentVersion === newVersion
|
||||
|
|
@ -261,7 +289,7 @@ async function promptInstallation() {
|
|||
|
||||
choices.push({
|
||||
name: bmadOptionText,
|
||||
value: 'bmad-core',
|
||||
value: "bmad-core",
|
||||
checked: true,
|
||||
});
|
||||
|
||||
|
|
@ -271,7 +299,7 @@ async function promptInstallation() {
|
|||
let packOptionText;
|
||||
|
||||
if (existing) {
|
||||
const currentVersion = existing.manifest?.version || 'unknown';
|
||||
const currentVersion = existing.manifest?.version || "unknown";
|
||||
const newVersion = pack.version;
|
||||
const versionInfo =
|
||||
currentVersion === newVersion
|
||||
|
|
@ -292,13 +320,14 @@ async function promptInstallation() {
|
|||
// Ask what to install
|
||||
const { selectedItems } = await inquirer.prompt([
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'selectedItems',
|
||||
message: 'Select what to install/update (use space to select, enter to continue):',
|
||||
type: "checkbox",
|
||||
name: "selectedItems",
|
||||
message:
|
||||
"Select what to install/update (use space to select, enter to continue):",
|
||||
choices: choices,
|
||||
validate: (selected) => {
|
||||
if (selected.length === 0) {
|
||||
return 'Please select at least one item to install';
|
||||
return "Please select at least one item to install";
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
|
@ -306,20 +335,27 @@ async function promptInstallation() {
|
|||
]);
|
||||
|
||||
// Process selections
|
||||
answers.installType = selectedItems.includes('bmad-core') ? 'full' : 'expansion-only';
|
||||
answers.expansionPacks = selectedItems.filter((item) => item !== 'bmad-core');
|
||||
answers.installType = selectedItems.includes("bmad-core")
|
||||
? "full"
|
||||
: "expansion-only";
|
||||
answers.expansionPacks = selectedItems.filter((item) => item !== "bmad-core");
|
||||
|
||||
// Ask sharding questions if installing BMad core
|
||||
if (selectedItems.includes('bmad-core')) {
|
||||
console.log(chalk.cyan('\n📋 Document Organization Settings'));
|
||||
console.log(chalk.dim('Configure how your project documentation should be organized.\n'));
|
||||
if (selectedItems.includes("bmad-core")) {
|
||||
console.log(chalk.cyan("\n📋 Document Organization Settings"));
|
||||
console.log(
|
||||
chalk.dim(
|
||||
"Configure how your project documentation should be organized.\n",
|
||||
),
|
||||
);
|
||||
|
||||
// Ask about PRD sharding
|
||||
const { prdSharded } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'prdSharded',
|
||||
message: 'Will the PRD (Product Requirements Document) be sharded into multiple files?',
|
||||
type: "confirm",
|
||||
name: "prdSharded",
|
||||
message:
|
||||
"Will the PRD (Product Requirements Document) be sharded into multiple files?",
|
||||
default: true,
|
||||
},
|
||||
]);
|
||||
|
|
@ -328,9 +364,10 @@ async function promptInstallation() {
|
|||
// Ask about architecture sharding
|
||||
const { architectureSharded } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'architectureSharded',
|
||||
message: 'Will the architecture documentation be sharded into multiple files?',
|
||||
type: "confirm",
|
||||
name: "architectureSharded",
|
||||
message:
|
||||
"Will the architecture documentation be sharded into multiple files?",
|
||||
default: true,
|
||||
},
|
||||
]);
|
||||
|
|
@ -338,36 +375,40 @@ async function promptInstallation() {
|
|||
|
||||
// Show warning if architecture sharding is disabled
|
||||
if (!architectureSharded) {
|
||||
console.log(chalk.yellow.bold('\n⚠️ IMPORTANT: Architecture Sharding Disabled'));
|
||||
console.log(
|
||||
chalk.yellow.bold("\n! IMPORTANT: Architecture Sharding Disabled"),
|
||||
);
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'With architecture sharding disabled, you should still create the files listed',
|
||||
"With architecture sharding disabled, you should still create the files listed",
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'in devLoadAlwaysFiles (like coding-standards.md, tech-stack.md, source-tree.md)',
|
||||
"in devLoadAlwaysFiles (like coding-standards.md, tech-stack.md, source-tree.md)",
|
||||
),
|
||||
);
|
||||
console.log(chalk.yellow('as these are used by the dev agent at runtime.'));
|
||||
console.log(
|
||||
chalk.yellow("as these are used by the dev agent at runtime."),
|
||||
);
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'\nAlternatively, you can remove these files from the devLoadAlwaysFiles list',
|
||||
"\nAlternatively, you can remove these files from the devLoadAlwaysFiles list",
|
||||
),
|
||||
);
|
||||
console.log(chalk.yellow('in your core-config.yaml after installation.'));
|
||||
console.log(chalk.yellow("in your core-config.yaml after installation."));
|
||||
|
||||
const { acknowledge } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'acknowledge',
|
||||
message: 'Do you acknowledge this requirement and want to proceed?',
|
||||
type: "confirm",
|
||||
name: "acknowledge",
|
||||
message: "Do you acknowledge this requirement and want to proceed?",
|
||||
default: false,
|
||||
},
|
||||
]);
|
||||
|
||||
if (!acknowledge) {
|
||||
console.log(chalk.red('Installation cancelled.'));
|
||||
console.log(chalk.red("Installation cancelled."));
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
|
@ -378,38 +419,39 @@ async function promptInstallation() {
|
|||
let ideSelectionComplete = false;
|
||||
|
||||
while (!ideSelectionComplete) {
|
||||
console.log(chalk.cyan('\n🛠️ IDE Configuration'));
|
||||
console.log(chalk.cyan("\n🛠 IDE Configuration"));
|
||||
console.log(
|
||||
chalk.bold.yellow.bgRed(
|
||||
' ⚠️ IMPORTANT: This is a MULTISELECT! Use SPACEBAR to toggle each IDE! ',
|
||||
" ! IMPORTANT: This is a MULTISELECT! Use SPACEBAR to toggle each IDE! ",
|
||||
),
|
||||
);
|
||||
console.log(chalk.bold.magenta('🔸 Use arrow keys to navigate'));
|
||||
console.log(chalk.bold.magenta('🔸 Use SPACEBAR to select/deselect IDEs'));
|
||||
console.log(chalk.bold.magenta('🔸 Press ENTER when finished selecting\n'));
|
||||
console.log(chalk.bold.magenta("🔸 Use arrow keys to navigate"));
|
||||
console.log(chalk.bold.magenta("🔸 Use SPACEBAR to select/deselect IDEs"));
|
||||
console.log(chalk.bold.magenta("🔸 Press ENTER when finished selecting\n"));
|
||||
|
||||
const ideResponse = await inquirer.prompt([
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'ides',
|
||||
type: "checkbox",
|
||||
name: "ides",
|
||||
message:
|
||||
'Which IDE(s) do you want to configure? (Select with SPACEBAR, confirm with ENTER):',
|
||||
"Which IDE(s) do you want to configure? (Select with SPACEBAR, confirm with ENTER):",
|
||||
choices: [
|
||||
{ name: 'Cursor', value: 'cursor' },
|
||||
{ name: 'Claude Code', value: 'claude-code' },
|
||||
{ name: 'iFlow CLI', value: 'iflow-cli' },
|
||||
{ name: 'Windsurf', value: 'windsurf' },
|
||||
{ name: 'Trae', value: 'trae' }, // { name: 'Trae', value: 'trae'}
|
||||
{ name: 'Roo Code', value: 'roo' },
|
||||
{ name: 'Kilo Code', value: 'kilo' },
|
||||
{ name: 'Cline', value: 'cline' },
|
||||
{ name: 'Gemini CLI', value: 'gemini' },
|
||||
{ name: 'Qwen Code', value: 'qwen-code' },
|
||||
{ name: 'Crush', value: 'crush' },
|
||||
{ name: 'Github Copilot', value: 'github-copilot' },
|
||||
{ name: 'Auggie CLI (Augment Code)', value: 'auggie-cli' },
|
||||
{ name: 'Codex CLI', value: 'codex' },
|
||||
{ name: 'Codex Web', value: 'codex-web' },
|
||||
{ name: "Open Code", value: "opencode" },
|
||||
{ name: "Cursor", value: "cursor" },
|
||||
{ name: "Claude Code", value: "claude-code" },
|
||||
{ name: "iFlow CLI", value: "iflow-cli" },
|
||||
{ name: "Windsurf", value: "windsurf" },
|
||||
{ name: "Trae", value: "trae" }, // { name: 'Trae', value: 'trae'}
|
||||
{ name: "Roo Code", value: "roo" },
|
||||
{ name: "Kilo Code", value: "kilo" },
|
||||
{ name: "Cline", value: "cline" },
|
||||
{ name: "Gemini CLI", value: "gemini" },
|
||||
{ name: "Qwen Code", value: "qwen-code" },
|
||||
{ name: "Crush", value: "crush" },
|
||||
{ name: "Github Copilot", value: "github-copilot" },
|
||||
{ name: "Auggie CLI (Augment Code)", value: "auggie-cli" },
|
||||
{ name: "Codex CLI", value: "codex" },
|
||||
{ name: "Codex Web", value: "codex-web" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
|
@ -420,10 +462,10 @@ async function promptInstallation() {
|
|||
if (ides.length === 0) {
|
||||
const { confirmNoIde } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirmNoIde',
|
||||
type: "confirm",
|
||||
name: "confirmNoIde",
|
||||
message: chalk.red(
|
||||
'⚠️ You have NOT selected any IDEs. This means NO IDE integration will be set up. Is this correct?',
|
||||
"! You have NOT selected any IDEs. This means NO IDE integration will be set up. Is this correct?",
|
||||
),
|
||||
default: false,
|
||||
},
|
||||
|
|
@ -432,7 +474,7 @@ async function promptInstallation() {
|
|||
if (!confirmNoIde) {
|
||||
console.log(
|
||||
chalk.bold.red(
|
||||
'\n🔄 Returning to IDE selection. Remember to use SPACEBAR to select IDEs!\n',
|
||||
"\n🔄 Returning to IDE selection. Remember to use SPACEBAR to select IDEs!\n",
|
||||
),
|
||||
);
|
||||
continue; // Go back to IDE selection only
|
||||
|
|
@ -446,32 +488,36 @@ async function promptInstallation() {
|
|||
answers.ides = ides;
|
||||
|
||||
// Configure GitHub Copilot immediately if selected
|
||||
if (ides.includes('github-copilot')) {
|
||||
console.log(chalk.cyan('\n🔧 GitHub Copilot Configuration'));
|
||||
if (ides.includes("github-copilot")) {
|
||||
console.log(chalk.cyan("\n🔧 GitHub Copilot Configuration"));
|
||||
console.log(
|
||||
chalk.dim('BMad works best with specific VS Code settings for optimal agent experience.\n'),
|
||||
chalk.dim(
|
||||
"BMad works best with specific VS Code settings for optimal agent experience.\n",
|
||||
),
|
||||
);
|
||||
|
||||
const { configChoice } = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'configChoice',
|
||||
message: chalk.yellow('How would you like to configure GitHub Copilot settings?'),
|
||||
type: "list",
|
||||
name: "configChoice",
|
||||
message: chalk.yellow(
|
||||
"How would you like to configure GitHub Copilot settings?",
|
||||
),
|
||||
choices: [
|
||||
{
|
||||
name: 'Use recommended defaults (fastest setup)',
|
||||
value: 'defaults',
|
||||
name: "Use recommended defaults (fastest setup)",
|
||||
value: "defaults",
|
||||
},
|
||||
{
|
||||
name: 'Configure each setting manually (customize to your preferences)',
|
||||
value: 'manual',
|
||||
name: "Configure each setting manually (customize to your preferences)",
|
||||
value: "manual",
|
||||
},
|
||||
{
|
||||
name: "Skip settings configuration (I'll configure manually later)",
|
||||
value: 'skip',
|
||||
value: "skip",
|
||||
},
|
||||
],
|
||||
default: 'defaults',
|
||||
default: "defaults",
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
@ -479,28 +525,30 @@ async function promptInstallation() {
|
|||
}
|
||||
|
||||
// Configure Auggie CLI (Augment Code) immediately if selected
|
||||
if (ides.includes('auggie-cli')) {
|
||||
console.log(chalk.cyan('\n📍 Auggie CLI Location Configuration'));
|
||||
console.log(chalk.dim('Choose where to install BMad agents for Auggie CLI access.\n'));
|
||||
if (ides.includes("auggie-cli")) {
|
||||
console.log(chalk.cyan("\n📍 Auggie CLI Location Configuration"));
|
||||
console.log(
|
||||
chalk.dim("Choose where to install BMad agents for Auggie CLI access.\n"),
|
||||
);
|
||||
|
||||
const { selectedLocations } = await inquirer.prompt([
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'selectedLocations',
|
||||
message: 'Select Auggie CLI command locations:',
|
||||
type: "checkbox",
|
||||
name: "selectedLocations",
|
||||
message: "Select Auggie CLI command locations:",
|
||||
choices: [
|
||||
{
|
||||
name: 'User Commands (Global): Available across all your projects (user-wide)',
|
||||
value: 'user',
|
||||
name: "User Commands (Global): Available across all your projects (user-wide)",
|
||||
value: "user",
|
||||
},
|
||||
{
|
||||
name: 'Workspace Commands (Project): Stored in repository, shared with team',
|
||||
value: 'workspace',
|
||||
name: "Workspace Commands (Project): Stored in repository, shared with team",
|
||||
value: "workspace",
|
||||
},
|
||||
],
|
||||
validate: (selected) => {
|
||||
if (selected.length === 0) {
|
||||
return 'Please select at least one location';
|
||||
return "Please select at least one location";
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
|
@ -513,41 +561,47 @@ async function promptInstallation() {
|
|||
// Ask for web bundles installation
|
||||
const { includeWebBundles } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'includeWebBundles',
|
||||
type: "confirm",
|
||||
name: "includeWebBundles",
|
||||
message:
|
||||
'Would you like to include pre-built web bundles? (standalone files for ChatGPT, Claude, Gemini)',
|
||||
"Would you like to include pre-built web bundles? (standalone files for ChatGPT, Claude, Gemini)",
|
||||
default: false,
|
||||
},
|
||||
]);
|
||||
|
||||
if (includeWebBundles) {
|
||||
console.log(chalk.cyan('\n📦 Web bundles are standalone files perfect for web AI platforms.'));
|
||||
console.log(
|
||||
chalk.dim(' You can choose different teams/agents than your IDE installation.\n'),
|
||||
chalk.cyan(
|
||||
"\n📦 Web bundles are standalone files perfect for web AI platforms.",
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
chalk.dim(
|
||||
" You can choose different teams/agents than your IDE installation.\n",
|
||||
),
|
||||
);
|
||||
|
||||
const { webBundleType } = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'webBundleType',
|
||||
message: 'What web bundles would you like to include?',
|
||||
type: "list",
|
||||
name: "webBundleType",
|
||||
message: "What web bundles would you like to include?",
|
||||
choices: [
|
||||
{
|
||||
name: 'All available bundles (agents, teams, expansion packs)',
|
||||
value: 'all',
|
||||
name: "All available bundles (agents, teams, expansion packs)",
|
||||
value: "all",
|
||||
},
|
||||
{
|
||||
name: 'Specific teams only',
|
||||
value: 'teams',
|
||||
name: "Specific teams only",
|
||||
value: "teams",
|
||||
},
|
||||
{
|
||||
name: 'Individual agents only',
|
||||
value: 'agents',
|
||||
name: "Individual agents only",
|
||||
value: "agents",
|
||||
},
|
||||
{
|
||||
name: 'Custom selection',
|
||||
value: 'custom',
|
||||
name: "Custom selection",
|
||||
value: "custom",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -556,21 +610,21 @@ async function promptInstallation() {
|
|||
answers.webBundleType = webBundleType;
|
||||
|
||||
// If specific teams, let them choose which teams
|
||||
if (webBundleType === 'teams' || webBundleType === 'custom') {
|
||||
if (webBundleType === "teams" || webBundleType === "custom") {
|
||||
const teams = await installer.getAvailableTeams();
|
||||
const { selectedTeams } = await inquirer.prompt([
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'selectedTeams',
|
||||
message: 'Select team bundles to include:',
|
||||
type: "checkbox",
|
||||
name: "selectedTeams",
|
||||
message: "Select team bundles to include:",
|
||||
choices: teams.map((t) => ({
|
||||
name: `${t.icon || '📋'} ${t.name}: ${t.description}`,
|
||||
name: `${t.icon || "📋"} ${t.name}: ${t.description}`,
|
||||
value: t.id,
|
||||
checked: webBundleType === 'teams', // Check all if teams-only mode
|
||||
checked: webBundleType === "teams", // Check all if teams-only mode
|
||||
})),
|
||||
validate: (answer) => {
|
||||
if (answer.length === 0) {
|
||||
return 'You must select at least one team.';
|
||||
return "You must select at least one team.";
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
|
@ -580,12 +634,12 @@ async function promptInstallation() {
|
|||
}
|
||||
|
||||
// If custom selection, also ask about individual agents
|
||||
if (webBundleType === 'custom') {
|
||||
if (webBundleType === "custom") {
|
||||
const { includeIndividualAgents } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'includeIndividualAgents',
|
||||
message: 'Also include individual agent bundles?',
|
||||
type: "confirm",
|
||||
name: "includeIndividualAgents",
|
||||
message: "Also include individual agent bundles?",
|
||||
default: true,
|
||||
},
|
||||
]);
|
||||
|
|
@ -594,13 +648,13 @@ async function promptInstallation() {
|
|||
|
||||
const { webBundlesDirectory } = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'webBundlesDirectory',
|
||||
message: 'Enter directory for web bundles:',
|
||||
type: "input",
|
||||
name: "webBundlesDirectory",
|
||||
message: "Enter directory for web bundles:",
|
||||
default: `${answers.directory}/web-bundles`,
|
||||
validate: (input) => {
|
||||
if (!input.trim()) {
|
||||
return 'Please enter a valid directory path';
|
||||
return "Please enter a valid directory path";
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -85,6 +85,17 @@ ide-configurations:
|
|||
# 2. Type @agent-name (e.g., "@dev", "@pm", "@architect")
|
||||
# 3. The agent will adopt that persona for the conversation
|
||||
# 4. Rules are stored in .clinerules/ directory in your project
|
||||
opencode:
|
||||
name: Opencode CLI
|
||||
rule-dir: .opencode/
|
||||
format: multi-file
|
||||
command-suffix: .md
|
||||
instructions: |
|
||||
# To use BMad agents with the Opencode CLI:
|
||||
# 1. The installer creates a `agent` and `command` folder in `.opencode/`.
|
||||
# 2. This adds custom commands for each agent and task.
|
||||
# 3. Type /BMad:agents:<agent-name> (e.g., "/BMad:agents:dev", "/BMad:agents:pm") or /BMad:tasks:<task-name> (e.g., "/BMad:tasks:create-doc").
|
||||
# 4. The agent will adopt that persona for the conversation or preform the task.
|
||||
gemini:
|
||||
name: Gemini CLI
|
||||
rule-dir: .gemini/commands/BMad/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue