Merge branch 'main' into expansion/tdd-methodology
This commit is contained in:
commit
447f78d719
14
README.md
14
README.md
|
|
@ -119,7 +119,7 @@ The BMAD-METHOD™ includes a powerful codebase flattener tool designed to prepa
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- **AI-Optimized Output**: Generates clean XML format specifically designed for AI model consumption
|
- **AI-Optimized Output**: Generates clean XML format specifically designed for AI model consumption
|
||||||
- **Smart Filtering**: Automatically respects `.gitignore` patterns to exclude unnecessary files
|
- **Smart Filtering**: Automatically respects `.gitignore` patterns to exclude unnecessary files, plus optional project-level `.bmad-flattenignore` for additional exclusions
|
||||||
- **Binary File Detection**: Intelligently identifies and excludes binary files, focusing on source code
|
- **Binary File Detection**: Intelligently identifies and excludes binary files, focusing on source code
|
||||||
- **Progress Tracking**: Real-time progress indicators and comprehensive completion statistics
|
- **Progress Tracking**: Real-time progress indicators and comprehensive completion statistics
|
||||||
- **Flexible Output**: Customizable output file location and naming
|
- **Flexible Output**: Customizable output file location and naming
|
||||||
|
|
@ -170,6 +170,18 @@ The generated XML file contains your project's text-based source files in a stru
|
||||||
- File discovery and ignoring
|
- File discovery and ignoring
|
||||||
- Uses `git ls-files` when inside a git repository for speed and correctness; otherwise falls back to a glob-based scan.
|
- Uses `git ls-files` when inside a git repository for speed and correctness; otherwise falls back to a glob-based scan.
|
||||||
- Applies your `.gitignore` plus a curated set of default ignore patterns (e.g., `node_modules`, build outputs, caches, logs, IDE folders, lockfiles, large media/binaries, `.env*`, and previously generated XML outputs).
|
- Applies your `.gitignore` plus a curated set of default ignore patterns (e.g., `node_modules`, build outputs, caches, logs, IDE folders, lockfiles, large media/binaries, `.env*`, and previously generated XML outputs).
|
||||||
|
- Supports an optional `.bmad-flattenignore` file at the project root for additional ignore patterns (gitignore-style). If present, its rules are applied after `.gitignore` and the defaults.
|
||||||
|
|
||||||
|
##### `.bmad-flattenignore` example
|
||||||
|
|
||||||
|
Create a `.bmad-flattenignore` file in the root of your project to exclude files that must remain in git but should not be included in the flattened XML:
|
||||||
|
|
||||||
|
```text
|
||||||
|
seeds/**
|
||||||
|
scripts/private/**
|
||||||
|
**/*.snap
|
||||||
|
```
|
||||||
|
|
||||||
- Binary handling
|
- Binary handling
|
||||||
- Binary files are detected and excluded from the XML content. They are counted in the final summary but not embedded in the output.
|
- Binary files are detected and excluded from the XML content. They are counted in the final summary but not embedded in the output.
|
||||||
- XML format and safety
|
- XML format and safety
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ npx bmad-method install
|
||||||
- **Cline**: VS Code extension with AI features
|
- **Cline**: VS Code extension with AI features
|
||||||
- **Roo Code**: Web-based IDE with agent support
|
- **Roo Code**: Web-based IDE with agent support
|
||||||
- **GitHub Copilot**: VS Code extension with AI peer programming assistant
|
- **GitHub Copilot**: VS Code extension with AI peer programming assistant
|
||||||
|
- **Auggie CLI (Augment Code)**: AI-powered development environment
|
||||||
|
|
||||||
**Note for VS Code Users**: BMAD-METHOD™ assumes when you mention "VS Code" that you're using it with an AI-powered extension like GitHub Copilot, Cline, or Roo. Standard VS Code without AI capabilities cannot run BMad agents. The installer includes built-in support for Cline and Roo.
|
**Note for VS Code Users**: BMAD-METHOD™ assumes when you mention "VS Code" that you're using it with an AI-powered extension like GitHub Copilot, Cline, or Roo. Standard VS Code without AI capabilities cannot run BMad agents. The installer includes built-in support for Cline and Roo.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,13 @@
|
||||||
> Gemini Web's 1M+ token context window or Gemini CLI (when it's working) can analyze your ENTIRE codebase, or critical sections of it, all at once (obviously within reason):
|
> Gemini Web's 1M+ token context window or Gemini CLI (when it's working) can analyze your ENTIRE codebase, or critical sections of it, all at once (obviously within reason):
|
||||||
>
|
>
|
||||||
> - Upload via GitHub URL or use gemini cli in the project folder
|
> - Upload via GitHub URL or use gemini cli in the project folder
|
||||||
> - If working in the web: use `npx bmad-method flatten` to flatten your project into a single file, then upload that file to your web agent.
|
> - If working in the web: use `npx bmad-method flatten` to flatten your project into a single file, then upload that file to your web agent. To exclude additional files that must remain in git but shouldn't be sent to the AI, add a `.bmad-flattenignore` file at the project root (gitignore-style), e.g.:
|
||||||
|
>
|
||||||
|
> ```text
|
||||||
|
> seeds/**
|
||||||
|
> scripts/private/**
|
||||||
|
> **/*.snap
|
||||||
|
> ```
|
||||||
|
|
||||||
## What is Brownfield Development?
|
## What is Brownfield Development?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,9 +154,11 @@ async function parseGitignore(gitignorePath) {
|
||||||
async function loadIgnore(rootDir, extraPatterns = []) {
|
async function loadIgnore(rootDir, extraPatterns = []) {
|
||||||
const ig = ignore();
|
const ig = ignore();
|
||||||
const gitignorePath = path.join(rootDir, '.gitignore');
|
const gitignorePath = path.join(rootDir, '.gitignore');
|
||||||
|
const flattenIgnorePath = path.join(rootDir, '.bmad-flattenignore');
|
||||||
const patterns = [
|
const patterns = [
|
||||||
...(await readIgnoreFile(gitignorePath)),
|
...(await readIgnoreFile(gitignorePath)),
|
||||||
...DEFAULT_PATTERNS,
|
...DEFAULT_PATTERNS,
|
||||||
|
...(await readIgnoreFile(flattenIgnorePath)),
|
||||||
...extraPatterns,
|
...extraPatterns,
|
||||||
];
|
];
|
||||||
// De-duplicate
|
// De-duplicate
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ program
|
||||||
.option('-d, --directory <path>', 'Installation directory')
|
.option('-d, --directory <path>', 'Installation directory')
|
||||||
.option(
|
.option(
|
||||||
'-i, --ide <ide...>',
|
'-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, other)',
|
'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, other)',
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
'-e, --expansion-packs <packs...>',
|
'-e, --expansion-packs <packs...>',
|
||||||
|
|
@ -406,6 +406,9 @@ async function promptInstallation() {
|
||||||
{ name: 'Qwen Code', value: 'qwen-code' },
|
{ name: 'Qwen Code', value: 'qwen-code' },
|
||||||
{ name: 'Crush', value: 'crush' },
|
{ name: 'Crush', value: 'crush' },
|
||||||
{ name: 'Github Copilot', value: 'github-copilot' },
|
{ 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' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
@ -474,6 +477,38 @@ async function promptInstallation() {
|
||||||
answers.githubCopilotConfig = { configChoice };
|
answers.githubCopilotConfig = { configChoice };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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'));
|
||||||
|
|
||||||
|
const { selectedLocations } = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
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: '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 true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
answers.augmentCodeConfig = { selectedLocations };
|
||||||
|
}
|
||||||
|
|
||||||
// Ask for web bundles installation
|
// Ask for web bundles installation
|
||||||
const { includeWebBundles } = await inquirer.prompt([
|
const { includeWebBundles } = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -78,15 +78,15 @@ ide-configurations:
|
||||||
# 4. Rules are stored in .clinerules/ directory in your project
|
# 4. Rules are stored in .clinerules/ directory in your project
|
||||||
gemini:
|
gemini:
|
||||||
name: Gemini CLI
|
name: Gemini CLI
|
||||||
rule-dir: .gemini/bmad-method/
|
rule-dir: .gemini/commands/BMad/
|
||||||
format: single-file
|
format: multi-file
|
||||||
command-suffix: .md
|
command-suffix: .toml
|
||||||
instructions: |
|
instructions: |
|
||||||
# To use BMad agents with the Gemini CLI:
|
# To use BMad agents with the Gemini CLI:
|
||||||
# 1. The installer creates a .gemini/bmad-method/ directory in your project.
|
# 1. The installer creates a `BMad` folder in `.gemini/commands`.
|
||||||
# 2. It concatenates all agent files into a single GEMINI.md file.
|
# 2. This adds custom commands for each agent and task.
|
||||||
# 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
|
# 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 Gemini CLI will automatically have the context for that agent.
|
# 4. The agent will adopt that persona for the conversation or preform the task.
|
||||||
github-copilot:
|
github-copilot:
|
||||||
name: Github Copilot
|
name: Github Copilot
|
||||||
rule-dir: .github/chatmodes/
|
rule-dir: .github/chatmodes/
|
||||||
|
|
@ -122,6 +122,25 @@ ide-configurations:
|
||||||
# 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
|
# 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
|
||||||
# 4. The Qwen Code CLI will automatically have the context for that agent.
|
# 4. The Qwen Code CLI will automatically have the context for that agent.
|
||||||
|
|
||||||
|
auggie-cli:
|
||||||
|
name: Auggie CLI (Augment Code)
|
||||||
|
format: multi-location
|
||||||
|
locations:
|
||||||
|
user:
|
||||||
|
name: User Commands (Global)
|
||||||
|
rule-dir: ~/.augment/commands/bmad/
|
||||||
|
description: Available across all your projects (user-wide)
|
||||||
|
workspace:
|
||||||
|
name: Workspace Commands (Project)
|
||||||
|
rule-dir: ./.augment/commands/bmad/
|
||||||
|
description: Stored in your repository and shared with your team
|
||||||
|
command-suffix: .md
|
||||||
|
instructions: |
|
||||||
|
# To use BMad agents in Auggie CLI (Augment Code):
|
||||||
|
# 1. Type /bmad:agent-name (e.g., "/bmad:dev", "/bmad:pm", "/bmad:architect")
|
||||||
|
# 2. The agent will adopt that persona for the conversation
|
||||||
|
# 3. Commands are available based on your selected location(s)
|
||||||
|
|
||||||
codex:
|
codex:
|
||||||
name: Codex CLI
|
name: Codex CLI
|
||||||
format: project-memory
|
format: project-memory
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ class IdeSetup extends BaseIdeSetup {
|
||||||
case 'qwen-code': {
|
case 'qwen-code': {
|
||||||
return this.setupQwenCode(installDir, selectedAgent);
|
return this.setupQwenCode(installDir, selectedAgent);
|
||||||
}
|
}
|
||||||
|
case 'auggie-cli': {
|
||||||
|
return this.setupAuggieCLI(installDir, selectedAgent, spinner, preConfiguredSettings);
|
||||||
|
}
|
||||||
case 'codex': {
|
case 'codex': {
|
||||||
return this.setupCodex(installDir, selectedAgent, { webEnabled: false });
|
return this.setupCodex(installDir, selectedAgent, { webEnabled: false });
|
||||||
}
|
}
|
||||||
|
|
@ -687,6 +690,7 @@ class IdeSetup extends BaseIdeSetup {
|
||||||
|
|
||||||
async getCoreTaskIds(installDir) {
|
async getCoreTaskIds(installDir) {
|
||||||
const allTaskIds = [];
|
const allTaskIds = [];
|
||||||
|
const glob = require('glob');
|
||||||
|
|
||||||
// Check core tasks in .bmad-core or root only
|
// Check core tasks in .bmad-core or root only
|
||||||
let tasksDir = path.join(installDir, '.bmad-core', 'tasks');
|
let tasksDir = path.join(installDir, '.bmad-core', 'tasks');
|
||||||
|
|
@ -695,7 +699,6 @@ class IdeSetup extends BaseIdeSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await fileManager.pathExists(tasksDir)) {
|
if (await fileManager.pathExists(tasksDir)) {
|
||||||
const glob = require('glob');
|
|
||||||
const taskFiles = glob.sync('*.md', { cwd: tasksDir });
|
const taskFiles = glob.sync('*.md', { cwd: tasksDir });
|
||||||
allTaskIds.push(...taskFiles.map((file) => path.basename(file, '.md')));
|
allTaskIds.push(...taskFiles.map((file) => path.basename(file, '.md')));
|
||||||
}
|
}
|
||||||
|
|
@ -1205,97 +1208,77 @@ class IdeSetup extends BaseIdeSetup {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setupGeminiCli(installDir) {
|
async setupGeminiCli(installDir, selectedAgent) {
|
||||||
const geminiDir = path.join(installDir, '.gemini');
|
const ideConfig = await configLoader.getIdeConfiguration('gemini');
|
||||||
const bmadMethodDir = path.join(geminiDir, 'bmad-method');
|
const bmadCommandsDir = path.join(installDir, ideConfig['rule-dir']);
|
||||||
await fileManager.ensureDirectory(bmadMethodDir);
|
|
||||||
|
|
||||||
// Update logic for existing settings.json
|
const agentCommandsDir = path.join(bmadCommandsDir, 'agents');
|
||||||
const settingsPath = path.join(geminiDir, 'settings.json');
|
const taskCommandsDir = path.join(bmadCommandsDir, 'tasks');
|
||||||
if (await fileManager.pathExists(settingsPath)) {
|
await fileManager.ensureDirectory(agentCommandsDir);
|
||||||
try {
|
await fileManager.ensureDirectory(taskCommandsDir);
|
||||||
const settingsContent = await fileManager.readFile(settingsPath);
|
|
||||||
const settings = JSON.parse(settingsContent);
|
|
||||||
let updated = false;
|
|
||||||
|
|
||||||
// Handle contextFileName property
|
|
||||||
if (settings.contextFileName && Array.isArray(settings.contextFileName)) {
|
|
||||||
const originalLength = settings.contextFileName.length;
|
|
||||||
settings.contextFileName = settings.contextFileName.filter(
|
|
||||||
(fileName) => !fileName.startsWith('agents/'),
|
|
||||||
);
|
|
||||||
if (settings.contextFileName.length !== originalLength) {
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated) {
|
|
||||||
await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
||||||
console.log(
|
|
||||||
chalk.green('✓ Updated .gemini/settings.json - removed agent file references'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(chalk.yellow('Could not update .gemini/settings.json'), error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove old agents directory
|
|
||||||
const agentsDir = path.join(geminiDir, 'agents');
|
|
||||||
if (await fileManager.pathExists(agentsDir)) {
|
|
||||||
await fileManager.removeDirectory(agentsDir);
|
|
||||||
console.log(chalk.green('✓ Removed old .gemini/agents directory'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all available agents
|
|
||||||
const agents = await this.getAllAgentIds(installDir);
|
|
||||||
let concatenatedContent = '';
|
|
||||||
|
|
||||||
|
// Process Agents
|
||||||
|
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
||||||
for (const agentId of agents) {
|
for (const agentId of agents) {
|
||||||
// Find the source agent file
|
|
||||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||||
|
if (!agentPath) {
|
||||||
if (agentPath) {
|
console.log(chalk.yellow(`✗ Agent file not found for ${agentId}, skipping.`));
|
||||||
const agentContent = await fileManager.readFile(agentPath);
|
continue;
|
||||||
|
|
||||||
// Create properly formatted agent rule content (similar to trae)
|
|
||||||
let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
||||||
agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
|
|
||||||
agentId,
|
|
||||||
installDir,
|
|
||||||
)} agent persona.\n\n`;
|
|
||||||
agentRuleContent += '## Agent Activation\n\n';
|
|
||||||
agentRuleContent +=
|
|
||||||
'CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n';
|
|
||||||
agentRuleContent += '```yaml\n';
|
|
||||||
// Extract just the YAML content from the agent file
|
|
||||||
const yamlContent = extractYamlFromAgent(agentContent);
|
|
||||||
if (yamlContent) {
|
|
||||||
agentRuleContent += yamlContent;
|
|
||||||
} else {
|
|
||||||
// If no YAML found, include the whole content minus the header
|
|
||||||
agentRuleContent += agentContent.replace(/^#.*$/m, '').trim();
|
|
||||||
}
|
|
||||||
agentRuleContent += '\n```\n\n';
|
|
||||||
agentRuleContent += '## File Reference\n\n';
|
|
||||||
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
|
|
||||||
agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
|
|
||||||
agentRuleContent += '## Usage\n\n';
|
|
||||||
agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
|
|
||||||
agentId,
|
|
||||||
installDir,
|
|
||||||
)} persona and follow all instructions defined in the YAML configuration above.\n`;
|
|
||||||
|
|
||||||
// Add to concatenated content with separator
|
|
||||||
concatenatedContent += agentRuleContent + '\n\n---\n\n';
|
|
||||||
console.log(chalk.green(`✓ Added context for @${agentId}`));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the concatenated content to GEMINI.md
|
const agentTitle = await this.getAgentTitle(agentId, installDir);
|
||||||
const geminiMdPath = path.join(bmadMethodDir, 'GEMINI.md');
|
const commandPath = path.join(agentCommandsDir, `${agentId}.toml`);
|
||||||
await fileManager.writeFile(geminiMdPath, concatenatedContent);
|
|
||||||
console.log(chalk.green(`\n✓ Created GEMINI.md in ${bmadMethodDir}`));
|
// Get relative path from installDir to agent file for @{file} reference
|
||||||
|
const relativeAgentPath = path.relative(installDir, agentPath).replaceAll('\\', '/');
|
||||||
|
|
||||||
|
const tomlContent = `description = "Activates the ${agentTitle} agent from the BMad Method."
|
||||||
|
prompt = """
|
||||||
|
CRITICAL: You are now the BMad '${agentTitle}' agent. Adopt its persona, follow its instructions, and use its capabilities. The full agent definition is below.
|
||||||
|
|
||||||
|
@{${relativeAgentPath}}
|
||||||
|
"""`;
|
||||||
|
|
||||||
|
await fileManager.writeFile(commandPath, tomlContent);
|
||||||
|
console.log(chalk.green(`✓ Created agent command: /bmad:agents:${agentId}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Tasks
|
||||||
|
const tasks = await this.getAllTaskIds(installDir);
|
||||||
|
for (const taskId of tasks) {
|
||||||
|
const taskPath = await this.findTaskPath(taskId, installDir);
|
||||||
|
if (!taskPath) {
|
||||||
|
console.log(chalk.yellow(`✗ Task file not found for ${taskId}, skipping.`));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskTitle = taskId
|
||||||
|
.split('-')
|
||||||
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||||
|
.join(' ');
|
||||||
|
const commandPath = path.join(taskCommandsDir, `${taskId}.toml`);
|
||||||
|
|
||||||
|
// Get relative path from installDir to task file for @{file} reference
|
||||||
|
const relativeTaskPath = path.relative(installDir, taskPath).replaceAll('\\', '/');
|
||||||
|
|
||||||
|
const tomlContent = `description = "Executes the BMad Task: ${taskTitle}"
|
||||||
|
prompt = """
|
||||||
|
CRITICAL: You are to execute the BMad Task defined below.
|
||||||
|
|
||||||
|
@{${relativeTaskPath}}
|
||||||
|
"""`;
|
||||||
|
|
||||||
|
await fileManager.writeFile(commandPath, tomlContent);
|
||||||
|
console.log(chalk.green(`✓ Created task command: /bmad:tasks:${taskId}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
chalk.green(`
|
||||||
|
✓ Created Gemini CLI extension in ${bmadCommandsDir}`),
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
chalk.dim('You can now use commands like /bmad:agents:dev or /bmad:tasks:create-doc.'),
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1611,6 +1594,96 @@ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems
|
||||||
console.log(chalk.dim(''));
|
console.log(chalk.dim(''));
|
||||||
console.log(chalk.dim('You can modify these settings anytime in .vscode/settings.json'));
|
console.log(chalk.dim('You can modify these settings anytime in .vscode/settings.json'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setupAuggieCLI(installDir, selectedAgent, spinner = null, preConfiguredSettings = null) {
|
||||||
|
const os = require('node:os');
|
||||||
|
const inquirer = require('inquirer');
|
||||||
|
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
||||||
|
|
||||||
|
// Get the IDE configuration to access location options
|
||||||
|
const ideConfig = await configLoader.getIdeConfiguration('auggie-cli');
|
||||||
|
const locations = ideConfig.locations;
|
||||||
|
|
||||||
|
// Use pre-configured settings if provided, otherwise prompt
|
||||||
|
let selectedLocations;
|
||||||
|
if (preConfiguredSettings && preConfiguredSettings.selectedLocations) {
|
||||||
|
selectedLocations = preConfiguredSettings.selectedLocations;
|
||||||
|
console.log(
|
||||||
|
chalk.dim(
|
||||||
|
`Using pre-configured Auggie CLI (Augment Code) locations: ${selectedLocations.join(', ')}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Pause spinner during location selection to avoid UI conflicts
|
||||||
|
let spinnerWasActive = false;
|
||||||
|
if (spinner && spinner.isSpinning) {
|
||||||
|
spinner.stop();
|
||||||
|
spinnerWasActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear any previous output and add spacing to avoid conflicts with loaders
|
||||||
|
console.log('\n'.repeat(2));
|
||||||
|
console.log(chalk.blue('📍 Auggie CLI Location Configuration'));
|
||||||
|
console.log(chalk.dim('Choose where to install BMad agents for Auggie CLI access.'));
|
||||||
|
console.log(''); // Add extra spacing
|
||||||
|
|
||||||
|
const response = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'selectedLocations',
|
||||||
|
message: 'Select Auggie CLI command locations:',
|
||||||
|
choices: Object.entries(locations).map(([key, location]) => ({
|
||||||
|
name: `${location.name}: ${location.description}`,
|
||||||
|
value: key,
|
||||||
|
})),
|
||||||
|
validate: (selected) => {
|
||||||
|
if (selected.length === 0) {
|
||||||
|
return 'Please select at least one location';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
selectedLocations = response.selectedLocations;
|
||||||
|
|
||||||
|
// Restart spinner if it was active before prompts
|
||||||
|
if (spinner && spinnerWasActive) {
|
||||||
|
spinner.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install to each selected location
|
||||||
|
for (const locationKey of selectedLocations) {
|
||||||
|
const location = locations[locationKey];
|
||||||
|
let commandsDir = location['rule-dir'];
|
||||||
|
|
||||||
|
// Handle tilde expansion for user directory
|
||||||
|
if (commandsDir.startsWith('~/')) {
|
||||||
|
commandsDir = path.join(os.homedir(), commandsDir.slice(2));
|
||||||
|
} else if (commandsDir.startsWith('./')) {
|
||||||
|
commandsDir = path.join(installDir, commandsDir.slice(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
await fileManager.ensureDirectory(commandsDir);
|
||||||
|
|
||||||
|
for (const agentId of agents) {
|
||||||
|
// Find the agent file
|
||||||
|
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||||
|
|
||||||
|
if (agentPath) {
|
||||||
|
const agentContent = await fileManager.readFile(agentPath);
|
||||||
|
const mdPath = path.join(commandsDir, `${agentId}.md`);
|
||||||
|
await fileManager.writeFile(mdPath, agentContent);
|
||||||
|
console.log(chalk.green(`✓ Created command: ${agentId}.md in ${location.name}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.green(`\n✓ Created Auggie CLI commands in ${commandsDir}`));
|
||||||
|
console.log(chalk.dim(` Location: ${location.name} - ${location.description}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new IdeSetup();
|
module.exports = new IdeSetup();
|
||||||
|
|
|
||||||
|
|
@ -408,7 +408,12 @@ class Installer {
|
||||||
if (ides.length > 0) {
|
if (ides.length > 0) {
|
||||||
for (const ide of ides) {
|
for (const ide of ides) {
|
||||||
spinner.text = `Setting up ${ide} integration...`;
|
spinner.text = `Setting up ${ide} integration...`;
|
||||||
const preConfiguredSettings = ide === 'github-copilot' ? config.githubCopilotConfig : null;
|
let preConfiguredSettings = null;
|
||||||
|
if (ide === 'github-copilot') {
|
||||||
|
preConfiguredSettings = config.githubCopilotConfig;
|
||||||
|
} else if (ide === 'auggie-cli') {
|
||||||
|
preConfiguredSettings = config.augmentCodeConfig;
|
||||||
|
}
|
||||||
await ideSetup.setup(ide, installDir, config.agent, spinner, preConfiguredSettings);
|
await ideSetup.setup(ide, installDir, config.agent, spinner, preConfiguredSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue