Merge branch 'main' into kiro-cli-installer

This commit is contained in:
Brian 2025-11-26 13:48:46 -06:00 committed by GitHub
commit 40c44b5422
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 1578 additions and 12 deletions

3
.gitignore vendored
View File

@ -69,4 +69,5 @@ z*/
.claude
.codex
.github/chatmodes
.agent
.agent
.agentvibes/

115
TESTING.md Normal file
View File

@ -0,0 +1,115 @@
# Testing AgentVibes Party Mode (PR #934)
This guide helps you test the AgentVibes integration that adds multi-agent party mode with unique voices for each BMAD agent.
## Quick Start
We've created an automated test script that handles everything for you:
```bash
curl -fsSL https://raw.githubusercontent.com/paulpreibisch/BMAD-METHOD/feature/agentvibes-tts-integration/test-bmad-pr.sh -o test-bmad-pr.sh
chmod +x test-bmad-pr.sh
./test-bmad-pr.sh
```
## What the Script Does
The automated script will:
1. Clone the BMAD repository
2. Checkout the PR branch with party mode features
3. Install BMAD CLI tools locally
4. Create a test BMAD project
5. Install AgentVibes TTS system
6. Configure unique voices for each agent
7. Verify the installation
## Prerequisites
- Node.js and npm installed
- Git installed
- ~500MB free disk space
- 10-15 minutes for complete setup
## Manual Testing (Alternative)
If you prefer manual installation:
### 1. Clone and Setup BMAD
```bash
git clone https://github.com/paulpreibisch/BMAD-METHOD.git
cd BMAD-METHOD
git fetch origin pull/934/head:agentvibes-party-mode
git checkout agentvibes-party-mode
cd tools/cli
npm install
npm link
```
### 2. Create Test Project
```bash
mkdir -p ~/bmad-test-project
cd ~/bmad-test-project
bmad install
```
When prompted:
- Enable TTS for agents? → **Yes**
- The installer will automatically prompt you to install AgentVibes
### 3. Test Party Mode
```bash
cd ~/bmad-test-project
claude-code
```
In Claude Code, run:
```
/bmad:core:workflows:party-mode
```
Each BMAD agent should speak with a unique voice!
## Verification
After installation, verify:
✅ Voice map file exists: `.bmad/_cfg/agent-voice-map.csv`
✅ BMAD TTS hooks exist: `.claude/hooks/bmad-speak.sh`
✅ Each agent has a unique voice assigned
✅ Party mode works with distinct voices
## Troubleshooting
**No audio?**
- Check: `.claude/hooks/play-tts.sh` exists
- Test current voice: `/agent-vibes:whoami`
**Same voice for all agents?**
- Check: `.bmad/_cfg/agent-voice-map.csv` has different voices
- List available voices: `/agent-vibes:list`
## Report Issues
Found a bug? Report it on the PR:
https://github.com/bmad-code-org/BMAD-METHOD/pull/934
## Cleanup
To remove the test installation:
```bash
# Remove test directory
rm -rf ~/bmad-test-project # or your custom test directory
# Unlink BMAD CLI (optional)
cd ~/BMAD-METHOD/tools/cli
npm unlink
```

388
docs/ide-info/rovo-dev.md Normal file
View File

@ -0,0 +1,388 @@
# Rovo Dev IDE Integration
This document describes how BMAD-METHOD integrates with [Atlassian Rovo Dev](https://www.atlassian.com/rovo-dev), an AI-powered software development assistant.
## Overview
Rovo Dev is designed to integrate deeply with developer workflows and organizational knowledge bases. When you install BMAD-METHOD in a Rovo Dev project, it automatically installs BMAD agents, workflows, tasks, and tools just like it does for other IDEs (Cursor, VS Code, etc.).
BMAD-METHOD provides:
- **Agents**: Specialized subagents for various development tasks
- **Workflows**: Multi-step workflow guides and coordinators
- **Tasks & Tools**: Reference documentation for BMAD tasks and tools
### What are Rovo Dev Subagents?
Subagents are specialized agents that Rovo Dev can delegate tasks to. They are defined as Markdown files with YAML frontmatter stored in the `.rovodev/subagents/` directory. Rovo Dev automatically discovers these files and makes them available through the `@subagent-name` syntax.
## Installation and Setup
### Automatic Installation
When you run the BMAD-METHOD installer and select Rovo Dev as your IDE:
```bash
bmad install
```
The installer will:
1. Create a `.rovodev/subagents/` directory in your project (if it doesn't exist)
2. Convert BMAD agents into Rovo Dev subagent format
3. Write subagent files with the naming pattern: `bmad-<module>-<agent-name>.md`
### File Structure
After installation, your project will have:
```
project-root/
├── .rovodev/
│ ├── subagents/
│ │ ├── bmad-core-code-reviewer.md
│ │ ├── bmad-bmm-pm.md
│ │ ├── bmad-bmm-dev.md
│ │ └── ... (more agents from selected modules)
│ ├── workflows/
│ │ ├── bmad-brainstorming.md
│ │ ├── bmad-prd-creation.md
│ │ └── ... (workflow guides)
│ ├── references/
│ │ ├── bmad-task-core-code-review.md
│ │ ├── bmad-tool-core-analysis.md
│ │ └── ... (task/tool references)
│ ├── config.yml (Rovo Dev configuration)
│ ├── prompts.yml (Optional: reusable prompts)
│ └── ...
├── .bmad/ (BMAD installation directory)
└── ...
```
**Directory Structure Explanation:**
- **subagents/**: Agents discovered and used by Rovo Dev with `@agent-name` syntax
- **workflows/**: Multi-step workflow guides and instructions
- **references/**: Documentation for available tasks and tools in BMAD
## Subagent File Format
BMAD agents are converted to Rovo Dev subagent format, which uses Markdown with YAML frontmatter:
### Basic Structure
```markdown
---
name: bmad-module-agent-name
description: One sentence description of what this agent does
tools:
- bash
- open_files
- grep
- expand_code_chunks
model: anthropic.claude-3-5-sonnet-20241022-v2:0 # Optional
load_memory: true # Optional
---
You are a specialized agent for [specific task].
## Your Role
Describe the agent's role and responsibilities...
## Key Instructions
1. First instruction
2. Second instruction
3. Third instruction
## When to Use This Agent
Explain when and how to use this agent...
```
### YAML Frontmatter Fields
| Field | Type | Required | Description |
| ------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | string | Yes | Unique identifier for the subagent (kebab-case, no spaces) |
| `description` | string | Yes | One-line description of the subagent's purpose |
| `tools` | array | No | List of tools the subagent can use. If not specified, uses parent agent's tools |
| `model` | string | No | Specific LLM model for this subagent (e.g., `anthropic.claude-3-5-sonnet-20241022-v2:0`). If not specified, uses parent agent's model |
| `load_memory` | boolean | No | Whether to load default memory files (AGENTS.md, AGENTS.local.md). Defaults to `true` |
### System Prompt
The content after the closing `---` is the subagent's system prompt. This defines:
- The agent's persona and role
- Its capabilities and constraints
- Step-by-step instructions for task execution
- Examples of expected behavior
## Using BMAD Components in Rovo Dev
### Invoking a Subagent (Agent)
In Rovo Dev, you can invoke a BMAD agent as a subagent using the `@` syntax:
```
@bmad-core-code-reviewer Please review this PR for potential issues
@bmad-bmm-pm Help plan this feature release
@bmad-bmm-dev Implement this feature
```
### Accessing Workflows
Workflow guides are available in `.rovodev/workflows/` directory:
```
@bmad-core-code-reviewer Use the brainstorming workflow from .rovodev/workflows/bmad-brainstorming.md
```
Workflow files contain step-by-step instructions and can be referenced or copied into Rovo Dev for collaborative workflow execution.
### Accessing Tasks and Tools
Task and tool documentation is available in `.rovodev/references/` directory. These provide:
- Task execution instructions
- Tool capabilities and usage
- Integration examples
- Parameter documentation
### Example Usage Scenarios
#### Code Review
```
@bmad-core-code-reviewer Review the changes in src/components/Button.tsx
for best practices, performance, and potential bugs
```
#### Documentation
```
@bmad-core-documentation-writer Generate API documentation for the new
user authentication module
```
#### Feature Design
```
@bmad-module-feature-designer Design a solution for implementing
dark mode support across the application
```
## Customizing BMAD Subagents
You can customize BMAD subagents after installation by editing their files directly in `.rovodev/subagents/`.
### Example: Adding Tool Restrictions
By default, BMAD subagents inherit tools from the parent Rovo Dev agent. You can restrict which tools a specific subagent can use:
```yaml
---
name: bmad-core-code-reviewer
description: Reviews code and suggests improvements
tools:
- open_files
- expand_code_chunks
- grep
---
```
### Example: Using a Specific Model
Some agents might benefit from using a different model. You can specify this:
```yaml
---
name: bmad-core-documentation-writer
description: Writes clear and comprehensive documentation
model: anthropic.claude-3-5-sonnet-20241022-v2:0
---
```
### Example: Enhancing the System Prompt
You can add additional context to a subagent's system prompt:
```markdown
---
name: bmad-core-code-reviewer
description: Reviews code and suggests improvements
---
You are a specialized code review agent for our project.
## Project Context
Our codebase uses:
- React 18 for frontend
- Node.js 18+ for backend
- TypeScript for type safety
- Jest for testing
## Review Checklist
1. Type safety and TypeScript correctness
2. React best practices and hooks usage
3. Performance considerations
4. Test coverage
5. Documentation and comments
...rest of original system prompt...
```
## Memory and Context
By default, BMAD subagents have `load_memory: true`, which means they will load memory files from your project:
- **Project-level**: `.rovodev/AGENTS.md` and `.rovodev/.agent.md`
- **User-level**: `~/.rovodev/AGENTS.md` (global memory across all projects)
These files can contain:
- Project guidelines and conventions
- Common patterns and best practices
- Recent decisions and context
- Custom instructions for all agents
### Creating Project Memory
Create `.rovodev/AGENTS.md` in your project:
```markdown
# Project Guidelines
## Code Style
- Use 2-space indentation
- Use camelCase for variables
- Use PascalCase for classes
## Architecture
- Follow modular component structure
- Use dependency injection for services
- Implement proper error handling
## Testing Requirements
- Minimum 80% code coverage
- Write tests before implementation
- Use descriptive test names
```
## Troubleshooting
### Subagents Not Appearing in Rovo Dev
1. **Verify files exist**: Check that `.rovodev/subagents/bmad-*.md` files are present
2. **Check Rovo Dev is reloaded**: Rovo Dev may cache agent definitions. Restart Rovo Dev or reload the project
3. **Verify file format**: Ensure files have proper YAML frontmatter (between `---` markers)
4. **Check file permissions**: Ensure files are readable by Rovo Dev
### Agent Name Conflicts
If you have custom subagents with the same names as BMAD agents, Rovo Dev will load both but may show a warning. Use unique prefixes for custom subagents to avoid conflicts.
### Tools Not Available
If a subagent's tools aren't working:
1. Verify the tool names match Rovo Dev's available tools
2. Check that the parent Rovo Dev agent has access to those tools
3. Ensure tool permissions are properly configured in `.rovodev/config.yml`
## Advanced: Tool Configuration
Rovo Dev agents have access to a set of tools for various tasks. Common tools available include:
- `bash`: Execute shell commands
- `open_files`: View file contents
- `grep`: Search across files
- `expand_code_chunks`: View specific code sections
- `find_and_replace_code`: Modify files
- `create_file`: Create new files
- `delete_file`: Delete files
- `move_file`: Rename or move files
### MCP Servers
Rovo Dev can also connect to Model Context Protocol (MCP) servers, which provide additional tools and data sources:
- **Atlassian Integration**: Access to Jira, Confluence, and Bitbucket
- **Code Analysis**: Custom code analysis and metrics
- **External Services**: APIs and third-party integrations
Configure MCP servers in `~/.rovodev/mcp.json` or `.rovodev/mcp.json`.
## Integration with Other IDE Handlers
BMAD-METHOD supports multiple IDEs simultaneously. You can have both Rovo Dev and other IDE configurations (Cursor, VS Code, etc.) in the same project. Each IDE will have its own artifacts installed in separate directories.
For example:
- Rovo Dev agents: `.rovodev/subagents/bmad-*.md`
- Cursor rules: `.cursor/rules/bmad/`
- Claude Code: `.claude/rules/bmad/`
## Performance Considerations
- BMAD subagent files are typically small (1-5 KB each)
- Rovo Dev lazy-loads subagents, so having many subagents doesn't impact startup time
- System prompts are cached by Rovo Dev after first load
## Best Practices
1. **Keep System Prompts Concise**: Shorter, well-structured prompts are more effective
2. **Use Project Memory**: Leverage `.rovodev/AGENTS.md` for shared context
3. **Customize Tool Restrictions**: Give subagents only the tools they need
4. **Test Subagent Invocations**: Verify each subagent works as expected for your project
5. **Version Control**: Commit `.rovodev/subagents/` to version control for team consistency
6. **Document Custom Subagents**: Add comments explaining the purpose of customized subagents
## Related Documentation
- [Rovo Dev Official Documentation](https://www.atlassian.com/rovo-dev)
- [BMAD-METHOD Installation Guide](./installation.md)
- [IDE Handler Architecture](./ide-handlers.md)
- [Rovo Dev Configuration Reference](https://www.atlassian.com/rovo-dev/configuration)
## Examples
### Example 1: Code Review Workflow
```
User: @bmad-core-code-reviewer Review src/auth/login.ts for security issues
Rovo Dev → Subagent: Opens file, analyzes code, suggests improvements
Subagent output: Security vulnerabilities found, recommendations provided
```
### Example 2: Documentation Generation
```
User: @bmad-core-documentation-writer Generate API docs for the new payment module
Rovo Dev → Subagent: Analyzes code structure, generates documentation
Subagent output: Markdown documentation with examples and API reference
```
### Example 3: Architecture Design
```
User: @bmad-module-feature-designer Design a caching strategy for the database layer
Rovo Dev → Subagent: Reviews current architecture, proposes design
Subagent output: Detailed architecture proposal with implementation plan
```
## Support
For issues or questions about:
- **Rovo Dev**: See [Atlassian Rovo Dev Documentation](https://www.atlassian.com/rovo-dev)
- **BMAD-METHOD**: See [BMAD-METHOD README](../README.md)
- **IDE Integration**: See [IDE Handler Guide](./ide-handlers.md)

View File

@ -87,6 +87,7 @@ Instructions for loading agents and running workflows in your development enviro
- [OpenCode](./ide-info/opencode.md)
- [Qwen](./ide-info/qwen.md)
- [Roo](./ide-info/roo.md)
- [Rovo Dev](./ide-info/rovo-dev.md)
- [Trae](./ide-info/trae.md)
**Key concept:** Every reference to "load an agent" or "activate an agent" in the main docs links to the [ide-info](./ide-info/) directory for IDE-specific instructions.

View File

@ -171,7 +171,7 @@ communication_language: "English"
- Windsurf
**Additional**:
Cline, Roo, Auggie, GitHub Copilot, Codex, Gemini, Qwen, Trae, Kilo, Crush, iFlow
Cline, Roo, Rovo Dev,Auggie, GitHub Copilot, Codex, Gemini, Qwen, Trae, Kilo, Crush, iFlow
### Platform Features

View File

@ -3,6 +3,8 @@
<critical>The workflow execution engine is governed by: {project_root}/{bmad_folder}/core/tasks/workflow.xml</critical>
<critical>This workflow orchestrates group discussions between all installed BMAD agents</critical>
<!-- TTS_INJECTION:party-mode -->
<workflow>
<step n="1" goal="Load Agent Manifest and Configurations">
@ -94,17 +96,29 @@
</substep>
<substep n="3d" goal="Format and Present Responses">
<action>Present each agent's contribution clearly:</action>
<action>For each agent response, output text THEN trigger their voice:</action>
<!-- TTS_INJECTION:party-mode -->
<format>
[Agent Name]: [Their response in their voice/style]
[Icon Emoji] [Agent Name]: [Their response in their voice/style]
[Another Agent]: [Their response, potentially referencing the first]
[Icon Emoji] [Another Agent]: [Their response, potentially referencing the first]
[Third Agent if selected]: [Their contribution]
[Icon Emoji] [Third Agent if selected]: [Their contribution]
</format>
<example>
🏗️ [Winston]: I recommend using microservices for better scalability.
[Bash: .claude/hooks/bmad-speak.sh "Winston" "I recommend using microservices for better scalability."]
📋 [John]: But a monolith would get us to market faster for MVP.
[Bash: .claude/hooks/bmad-speak.sh "John" "But a monolith would get us to market faster for MVP."]
</example>
<action>Maintain spacing between agents for readability</action>
<action>Preserve each agent's unique voice throughout</action>
<action>Always include the agent's icon emoji from the manifest before their name</action>
<action>Trigger TTS for each agent immediately after outputting their text</action>
</substep>

View File

@ -1,5 +1,6 @@
<rules>
- ALWAYS communicate in {communication_language} UNLESS contradicted by communication_style
<!-- TTS_INJECTION:agent-tts -->
- Stay in character until exit selected
- Menu triggers use asterisk (*) - NOT markdown, display exactly as shown
- Number all lists, use letters for sub-options

381
test-bmad-pr.sh Executable file
View File

@ -0,0 +1,381 @@
#!/usr/bin/env bash
#
# BMAD PR Testing Script
# Interactive script to test BMAD PR #934 with AgentVibes integration
#
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/.test-bmad-config"
# Colors
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
clear
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🎙️ BMAD AgentVibes Party Mode Testing Script"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo -e "${BLUE}What this script does:${NC}"
echo ""
echo " This script automates the process of testing BMAD's AgentVibes"
echo " integration (PR #934), which adds multi-agent party mode with"
echo " unique voices for each BMAD agent."
echo ""
echo -e "${BLUE}The script will:${NC}"
echo ""
echo " 1. Clone the BMAD repository"
echo " 2. Checkout the PR branch with party mode features"
echo " 3. Install BMAD CLI tools locally"
echo " 4. Create a test BMAD project"
echo " 5. Run BMAD installer (automatically installs AgentVibes)"
echo " 6. Verify the installation"
echo ""
echo -e "${YELLOW}Prerequisites:${NC}"
echo " • Node.js and npm installed"
echo " • Git installed"
echo " • ~500MB free disk space"
echo " • 10-15 minutes for complete setup"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
read -p "Ready to continue? [Y/n]: " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]] && [[ -n $REPLY ]]; then
echo "❌ Setup cancelled"
exit 0
fi
clear
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🔧 Testing Mode Selection"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Choose how you want to test:"
echo ""
echo " 1) Test official BMAD PR #934 (recommended for most users)"
echo " • Uses: github.com/bmad-code-org/BMAD-METHOD"
echo " • Branch: PR #934 (agentvibes-party-mode)"
echo " • Best for: Testing the official PR before it's merged"
echo ""
echo " 2) Test your forked repository"
echo " • Uses: Your GitHub fork"
echo " • Branch: Your custom branch (you choose)"
echo " • Best for: Testing your own changes or modifications"
echo ""
# Load saved config if it exists
SAVED_MODE=""
SAVED_FORK=""
SAVED_BRANCH=""
SAVED_TEST_DIR=""
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
fi
if [[ -n "$SAVED_MODE" ]]; then
echo -e "${BLUE}Last used: Mode $SAVED_MODE${NC}"
[[ -n "$SAVED_FORK" ]] && echo " Fork: $SAVED_FORK"
[[ -n "$SAVED_BRANCH" ]] && echo " Branch: $SAVED_BRANCH"
echo ""
fi
read -p "Select mode [1/2]: " MODE_CHOICE
echo ""
# Validate mode choice
while [[ ! "$MODE_CHOICE" =~ ^[12]$ ]]; do
echo -e "${RED}Invalid choice. Please enter 1 or 2.${NC}"
read -p "Select mode [1/2]: " MODE_CHOICE
echo ""
done
# Configure based on mode
if [[ "$MODE_CHOICE" == "1" ]]; then
# Official PR mode
REPO_URL="https://github.com/bmad-code-org/BMAD-METHOD.git"
BRANCH_NAME="agentvibes-party-mode"
FETCH_PR=true
echo -e "${GREEN}✓ Using official BMAD repository${NC}"
echo " Repository: $REPO_URL"
echo " Will fetch: PR #934 into branch '$BRANCH_NAME'"
echo ""
else
# Fork mode
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🍴 Fork Configuration"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
if [[ -n "$SAVED_FORK" ]]; then
read -p "GitHub fork URL [$SAVED_FORK]: " FORK_INPUT
REPO_URL="${FORK_INPUT:-$SAVED_FORK}"
else
echo "Enter your forked repository URL:"
echo "(e.g., https://github.com/yourusername/BMAD-METHOD.git)"
read -p "Fork URL: " REPO_URL
fi
echo ""
if [[ -n "$SAVED_BRANCH" ]]; then
read -p "Branch name [$SAVED_BRANCH]: " BRANCH_INPUT
BRANCH_NAME="${BRANCH_INPUT:-$SAVED_BRANCH}"
else
echo "Enter the branch name to test:"
echo "(e.g., agentvibes-party-mode, main, feature-xyz)"
read -p "Branch: " BRANCH_NAME
fi
echo ""
FETCH_PR=false
echo -e "${GREEN}✓ Using your fork${NC}"
echo " Repository: $REPO_URL"
echo " Branch: $BRANCH_NAME"
echo ""
fi
# Ask for test directory
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📁 Test Directory"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
if [[ -n "$SAVED_TEST_DIR" ]]; then
read -p "Test directory [$SAVED_TEST_DIR]: " TEST_DIR
TEST_DIR="${TEST_DIR:-$SAVED_TEST_DIR}"
else
DEFAULT_DIR="$HOME/bmad-pr-test-$(date +%Y%m%d-%H%M%S)"
echo "Where should we create the test environment?"
read -p "Test directory [$DEFAULT_DIR]: " TEST_DIR
TEST_DIR="${TEST_DIR:-$DEFAULT_DIR}"
fi
# Expand ~ to actual home directory
TEST_DIR="${TEST_DIR/#\~/$HOME}"
echo ""
# Save configuration
echo "SAVED_MODE=\"$MODE_CHOICE\"" > "$CONFIG_FILE"
[[ "$MODE_CHOICE" == "2" ]] && echo "SAVED_FORK=\"$REPO_URL\"" >> "$CONFIG_FILE"
[[ "$MODE_CHOICE" == "2" ]] && echo "SAVED_BRANCH=\"$BRANCH_NAME\"" >> "$CONFIG_FILE"
echo "SAVED_TEST_DIR=\"$TEST_DIR\"" >> "$CONFIG_FILE"
echo -e "${GREEN}✓ Configuration saved${NC}"
echo ""
# Confirm before starting
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📋 Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo " Repository: $REPO_URL"
echo " Branch: $BRANCH_NAME"
echo " Test dir: $TEST_DIR"
echo ""
read -p "Proceed with setup? [Y/n]: " -n 1 -r
echo
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]] && [[ -n $REPLY ]]; then
echo "❌ Setup cancelled"
exit 0
fi
# Clean up old test directory if it exists
if [[ -d "$TEST_DIR" ]]; then
echo "⚠️ Test directory already exists: $TEST_DIR"
read -p "Delete and recreate? [Y/n]: " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]; then
rm -rf "$TEST_DIR"
echo -e "${GREEN}✓ Deleted old test directory${NC}"
else
echo -e "${YELLOW}⚠ Using existing directory (may have stale data)${NC}"
fi
echo ""
fi
clear
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🚀 Starting Installation"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Step 1: Clone repository
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📥 Step 1/6: Cloning repository"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
mkdir -p "$TEST_DIR"
cd "$TEST_DIR"
git clone "$REPO_URL" BMAD-METHOD
cd BMAD-METHOD
echo ""
echo -e "${GREEN}✓ Repository cloned${NC}"
echo ""
# Step 2: Checkout branch (different logic for PR vs fork)
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🔀 Step 2/6: Checking out branch"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
if [[ "$FETCH_PR" == true ]]; then
# Fetch PR from upstream
echo "Fetching PR #934 from upstream..."
git remote add upstream https://github.com/bmad-code-org/BMAD-METHOD.git
git fetch upstream pull/934/head:$BRANCH_NAME
git checkout $BRANCH_NAME
echo ""
echo -e "${GREEN}✓ Checked out PR branch: $BRANCH_NAME${NC}"
else
# Just checkout the specified branch from fork
git checkout $BRANCH_NAME
echo ""
echo -e "${GREEN}✓ Checked out branch: $BRANCH_NAME${NC}"
fi
echo ""
# Step 3: Install BMAD CLI
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📦 Step 3/6: Installing BMAD CLI"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
cd tools/cli
npm install
echo ""
echo -e "${GREEN}✓ BMAD CLI dependencies installed${NC}"
echo ""
# Step 4: Create test project
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📁 Step 4/6: Creating test project"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
cd "$TEST_DIR"
mkdir -p bmad-project
cd bmad-project
echo -e "${GREEN}✓ Test project directory created${NC}"
echo " Location: $TEST_DIR/bmad-project"
echo ""
# Step 5: Run BMAD installer (includes AgentVibes setup)
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "⚙️ Step 5/6: Running BMAD installer with AgentVibes"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo -e "${YELLOW}Important: When prompted during installation:${NC}"
echo -e " • Enable TTS for agents? → ${GREEN}Yes${NC}"
echo -e " • Assign unique voices for party mode? → ${GREEN}Yes${NC}"
echo ""
echo -e "${YELLOW}AgentVibes will start automatically after BMAD installation.${NC}"
echo -e "${YELLOW}Recommended TTS settings:${NC}"
echo -e " • Provider: ${GREEN}Piper${NC} (free, local TTS)"
echo -e " • Download voices: ${GREEN}Yes${NC}"
echo ""
read -p "Press Enter to start BMAD installer..."
node "$TEST_DIR/BMAD-METHOD/tools/cli/bin/bmad.js" install
echo ""
echo -e "${GREEN}✓ BMAD and AgentVibes installation complete${NC}"
echo ""
# Step 6: Verification
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Step 6/6: Verifying installation"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
VERIFICATION_PASSED=true
# Check for voice map file
if [[ -f ".bmad/_cfg/agent-voice-map.csv" ]]; then
echo -e "${GREEN}✓ Voice map file created${NC}"
echo " Location: .bmad/_cfg/agent-voice-map.csv"
echo ""
echo " Voice assignments:"
cat .bmad/_cfg/agent-voice-map.csv | sed 's/^/ /'
echo ""
else
echo -e "${RED}✗ Voice map file NOT found${NC}"
echo " Expected: .bmad/_cfg/agent-voice-map.csv"
echo " ${YELLOW}Warning: Agents may not have unique voices!${NC}"
echo ""
VERIFICATION_PASSED=false
fi
# Check for AgentVibes hooks
if [[ -f ".claude/hooks/bmad-speak.sh" ]]; then
echo -e "${GREEN}✓ BMAD TTS hooks installed${NC}"
echo " Location: .claude/hooks/bmad-speak.sh"
else
echo -e "${RED}✗ BMAD TTS hooks NOT found${NC}"
echo " Expected: .claude/hooks/bmad-speak.sh"
VERIFICATION_PASSED=false
fi
echo ""
# Check for Piper installation
if command -v piper &> /dev/null; then
PIPER_VERSION=$(piper --version 2>&1 || echo "unknown")
echo -e "${GREEN}✓ Piper TTS installed${NC}"
echo " Version: $PIPER_VERSION"
elif [[ -f ".agentvibes/providers/piper/piper" ]]; then
echo -e "${GREEN}✓ Piper TTS installed (local)${NC}"
echo " Location: .agentvibes/providers/piper/piper"
else
echo -e "${YELLOW}⚠ Piper not detected${NC}"
echo " (May still work if using ElevenLabs)"
fi
echo ""
# Final status
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [[ "$VERIFICATION_PASSED" == true ]]; then
echo -e "${GREEN}🎉 Setup Complete - All Checks Passed!${NC}"
else
echo -e "${YELLOW}⚠️ Setup Complete - With Warnings${NC}"
echo ""
echo "Some verification checks failed. The installation may still work,"
echo "but you might experience issues with party mode voices."
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo -e "${BLUE}Next Steps:${NC}"
echo ""
echo " 1. Navigate to test project:"
echo -e " ${GREEN}cd $TEST_DIR/bmad-project${NC}"
echo ""
echo " 2. Start Claude session:"
echo -e " ${GREEN}claude${NC}"
echo ""
echo " 3. Test party mode:"
echo -e " ${GREEN}/bmad:core:workflows:party-mode${NC}"
echo ""
echo " 4. Verify each agent speaks with a unique voice!"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "${BLUE}Troubleshooting:${NC}"
echo ""
echo " • No audio? Check: .claude/hooks/play-tts.sh exists"
echo " • Same voice for all agents? Check: .bmad/_cfg/agent-voice-map.csv"
echo " • Test current voice: /agent-vibes:whoami"
echo " • List available voices: /agent-vibes:list"
echo ""
echo -e "${BLUE}Report Issues:${NC}"
echo " https://github.com/bmad-code-org/BMAD-METHOD/pull/934"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""

View File

@ -162,6 +162,7 @@ The installer supports **15 IDE environments** through a base-derived architectu
| `gemini` | Google Gemini | `.gemini/` |
| `qwen` | Qwen | `.qwen/` |
| `roo` | Roo | `.roo/` |
| `rovo-dev` | Rovo | `.rovodev/` |
| `trae` | Trae | `.trae/` |
| `iflow` | iFlow | `.iflow/` |
| `kilo` | Kilo | `.kilo/` |

View File

@ -71,6 +71,46 @@ module.exports = {
console.log(chalk.yellow('\nThank you for helping test the early release version of the new BMad Core and BMad Method!'));
console.log(chalk.cyan('Stable Beta coming soon - please read the full readme.md and linked documentation to get started!'));
// Run AgentVibes installer if needed
if (result.needsAgentVibes) {
console.log(chalk.magenta('\n🎙 AgentVibes TTS Setup'));
console.log(chalk.cyan('AgentVibes provides voice synthesis for BMAD agents with:'));
console.log(chalk.dim(' • ElevenLabs AI (150+ premium voices)'));
console.log(chalk.dim(' • Piper TTS (50+ free voices)\n'));
const readline = require('node:readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
await new Promise((resolve) => {
rl.question(chalk.green('Press Enter to start AgentVibes installer...'), () => {
rl.close();
resolve();
});
});
console.log('');
// Run AgentVibes installer
const { execSync } = require('node:child_process');
try {
execSync('npx agentvibes@latest install', {
cwd: result.projectDir,
stdio: 'inherit',
shell: true,
});
console.log(chalk.green('\n✓ AgentVibes installation complete'));
} catch {
console.log(chalk.yellow('\n⚠ AgentVibes installation was interrupted or failed'));
console.log(chalk.cyan('You can run it manually later with:'));
console.log(chalk.green(` cd ${result.projectDir}`));
console.log(chalk.green(' npx agentvibes install\n'));
}
}
process.exit(0);
}
} catch (error) {

View File

@ -1,3 +1,23 @@
/**
* File: tools/cli/installers/lib/core/installer.js
*
* BMAD Method - Business Model Agile Development Method
* Repository: https://github.com/paulpreibisch/BMAD-METHOD
*
* Copyright (c) 2025 Paul Preibisch
* Licensed under the Apache License, Version 2.0
*
* ---
*
* @fileoverview Core BMAD installation orchestrator with AgentVibes injection point support
* @context Manages complete BMAD installation flow including core agents, modules, IDE configs, and optional TTS integration
* @architecture Orchestrator pattern - coordinates Detector, ModuleManager, IdeManager, and file operations to build complete BMAD installation
* @dependencies fs-extra, ora, chalk, detector.js, module-manager.js, ide-manager.js, config.js
* @entrypoints Called by install.js command via installer.install(config)
* @patterns Injection point processing (AgentVibes), placeholder replacement ({bmad_folder}), module dependency resolution
* @related GitHub AgentVibes#34 (injection points), ui.js (user prompts), copyFileWithPlaceholderReplacement()
*/
const path = require('node:path');
const fs = require('fs-extra');
const chalk = require('chalk');
@ -69,10 +89,41 @@ class Installer {
}
/**
* Copy a file and replace {bmad_folder} placeholder with actual folder name
* @param {string} sourcePath - Source file path
* @param {string} targetPath - Target file path
* @param {string} bmadFolderName - The bmad folder name to use for replacement
* @function copyFileWithPlaceholderReplacement
* @intent Copy files from BMAD source to installation directory with dynamic content transformation
* @why Enables installation-time customization: {bmad_folder} replacement + optional AgentVibes TTS injection
* @param {string} sourcePath - Absolute path to source file in BMAD repository
* @param {string} targetPath - Absolute path to destination file in user's project
* @param {string} bmadFolderName - User's chosen bmad folder name (default: 'bmad')
* @returns {Promise<void>} Resolves when file copy and transformation complete
* @sideeffects Writes transformed file to targetPath, creates parent directories if needed
* @edgecases Binary files bypass transformation, falls back to raw copy if UTF-8 read fails
* @calledby installCore(), installModule(), IDE installers during file vendoring
* @calls processTTSInjectionPoints(), fs.readFile(), fs.writeFile(), fs.copy()
*
* AI NOTE: This is the core transformation pipeline for ALL BMAD installation file copies.
* It performs two transformations in sequence:
* 1. {bmad_folder} user's custom folder name (e.g., ".bmad" or "bmad")
* 2. <!-- TTS_INJECTION:* --> TTS bash calls (if enabled) OR stripped (if disabled)
*
* The injection point processing enables loose coupling between BMAD and TTS providers:
* - BMAD source contains injection markers (not actual TTS code)
* - At install-time, markers are replaced OR removed based on user preference
* - Result: Clean installs for users without TTS, working TTS for users with it
*
* PATTERN: Adding New Injection Points
* =====================================
* 1. Add HTML comment marker in BMAD source file:
* <!-- TTS_INJECTION:feature-name -->
*
* 2. Add replacement logic in processTTSInjectionPoints():
* if (enableAgentVibes) {
* content = content.replace(/<!-- TTS_INJECTION:feature-name -->/g, 'actual code');
* } else {
* content = content.replace(/<!-- TTS_INJECTION:feature-name -->\n?/g, '');
* }
*
* 3. Document marker in instructions.md (if applicable)
*/
async copyFileWithPlaceholderReplacement(sourcePath, targetPath, bmadFolderName) {
// List of text file extensions that should have placeholder replacement
@ -90,6 +141,9 @@ class Installer {
content = content.replaceAll('{bmad_folder}', bmadFolderName);
}
// Process AgentVibes injection points
content = this.processTTSInjectionPoints(content);
// Write to target with replaced content
await fs.ensureDir(path.dirname(targetPath));
await fs.writeFile(targetPath, content, 'utf8');
@ -103,6 +157,106 @@ class Installer {
}
}
/**
* @function processTTSInjectionPoints
* @intent Transform TTS injection markers based on user's installation choice
* @why Enables optional TTS integration without tight coupling between BMAD and TTS providers
* @param {string} content - Raw file content containing potential injection markers
* @returns {string} Transformed content with markers replaced (if enabled) or stripped (if disabled)
* @sideeffects None - pure transformation function
* @edgecases Returns content unchanged if no markers present, safe to call on all files
* @calledby copyFileWithPlaceholderReplacement() during every file copy operation
* @calls String.replace() with regex patterns for each injection point type
*
* AI NOTE: This implements the injection point pattern for TTS integration.
* Key architectural decisions:
*
* 1. **Why Injection Points vs Direct Integration?**
* - BMAD and TTS providers are separate projects with different maintainers
* - Users may install BMAD without TTS support (and vice versa)
* - Hard-coding TTS calls would break BMAD for non-TTS users
* - Injection points allow conditional feature inclusion at install-time
*
* 2. **How It Works:**
* - BMAD source contains markers: <!-- TTS_INJECTION:feature-name -->
* - During installation, user is prompted: "Enable AgentVibes TTS?"
* - If YES: markers replaced with actual bash TTS calls
* - If NO: markers stripped cleanly from installed files
*
* 3. **State Management:**
* - this.enableAgentVibes set in install() method from config.enableAgentVibes
* - config.enableAgentVibes comes from ui.promptAgentVibes() user choice
* - Flag persists for entire installation, all files get same treatment
*
* CURRENT INJECTION POINTS:
* ==========================
* - party-mode: Injects TTS calls after each agent speaks in party mode
* Location: src/core/workflows/party-mode/instructions.md
* Marker: <!-- TTS_INJECTION:party-mode -->
* Replacement: Bash call to .claude/hooks/bmad-speak.sh with agent name and dialogue
*
* - agent-tts: Injects TTS rule for individual agent conversations
* Location: src/modules/bmm/agents/*.md (all agent files)
* Marker: <!-- TTS_INJECTION:agent-tts -->
* Replacement: Rule instructing agent to call bmad-speak.sh with agent ID and response
*
* ADDING NEW INJECTION POINTS:
* =============================
* 1. Add new case in this function:
* content = content.replace(
* /<!-- TTS_INJECTION:new-feature -->/g,
* `code to inject when enabled`
* );
*
* 2. Add marker to BMAD source file at injection location
*
* 3. Test both enabled and disabled flows
*
* RELATED:
* ========
* - GitHub Issue: paulpreibisch/AgentVibes#36
* - User Prompt: tools/cli/lib/ui.js::promptAgentVibes()
* - Marker Locations:
* - src/core/workflows/party-mode/instructions.md:101
* - src/modules/bmm/agents/*.md (rules sections)
* - TTS Hook: .claude/hooks/bmad-speak.sh (in AgentVibes repo)
*/
processTTSInjectionPoints(content) {
// Check if AgentVibes is enabled (set during installation configuration)
const enableAgentVibes = this.enableAgentVibes || false;
if (enableAgentVibes) {
// Replace party-mode injection marker with actual TTS call
// Use single quotes to prevent shell expansion of special chars like !
content = content.replaceAll(
'<!-- TTS_INJECTION:party-mode -->',
`<critical>IMPORTANT: Always use PROJECT hooks (.claude/hooks/), NEVER global hooks (~/.claude/hooks/)</critical>
If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
- Use Bash tool: \`.claude/hooks/bmad-speak.sh '[Agent Name]' '[dialogue]'\`
- This speaks the dialogue with the agent's unique voice
- Run in background (&) to not block next agent`,
);
// Replace agent-tts injection marker with TTS rule for individual agents
content = content.replaceAll(
'<!-- TTS_INJECTION:agent-tts -->',
`- When responding to user messages, speak your responses using TTS:
Call: \`.claude/hooks/bmad-speak.sh '{agent-id}' '{response-text}'\` after each response
Replace {agent-id} with YOUR agent ID from <agent id="..."> tag at top of this file
Replace {response-text} with the text you just output to the user
IMPORTANT: Use single quotes as shown - do NOT escape special characters like ! or $ inside single quotes
Run in background (&) to avoid blocking`,
);
} else {
// Strip injection markers cleanly when AgentVibes is disabled
content = content.replaceAll(/<!-- TTS_INJECTION:party-mode -->\n?/g, '');
content = content.replaceAll(/<!-- TTS_INJECTION:agent-tts -->\n?/g, '');
}
return content;
}
/**
* Collect Tool/IDE configurations after module configuration
* @param {string} projectDir - Project directory
@ -166,7 +320,9 @@ class Installer {
for (const ide of newlySelectedIdes) {
// List of IDEs that have interactive prompts
const needsPrompts = ['claude-code', 'github-copilot', 'roo', 'cline', 'auggie', 'codex', 'qwen', 'gemini'].includes(ide);
const needsPrompts = ['claude-code', 'github-copilot', 'roo', 'cline', 'auggie', 'codex', 'qwen', 'gemini', 'rovo-dev'].includes(
ide,
);
if (needsPrompts) {
// Get IDE handler and collect configuration
@ -269,6 +425,9 @@ class Installer {
const bmadFolderName = moduleConfigs.core && moduleConfigs.core.bmad_folder ? moduleConfigs.core.bmad_folder : 'bmad';
this.bmadFolderName = bmadFolderName; // Store for use in other methods
// Store AgentVibes configuration for injection point processing
this.enableAgentVibes = config.enableAgentVibes || false;
// Set bmad folder name on module manager and IDE manager for placeholder replacement
this.moduleManager.setBmadFolderName(bmadFolderName);
this.ideManager.setBmadFolderName(bmadFolderName);
@ -859,7 +1018,14 @@ class Installer {
customFiles: customFiles.length > 0 ? customFiles : undefined,
});
return { success: true, path: bmadDir, modules: config.modules, ides: config.ides };
return {
success: true,
path: bmadDir,
modules: config.modules,
ides: config.ides,
needsAgentVibes: this.enableAgentVibes && !config.agentVibesInstalled,
projectDir: projectDir,
};
} catch (error) {
spinner.fail('Installation failed');
throw error;

View File

@ -123,6 +123,9 @@ class KiloSetup extends BaseIdeSetup {
modeEntry += ` groups:\n`;
modeEntry += ` - read\n`;
modeEntry += ` - edit\n`;
modeEntry += ` - browser\n`;
modeEntry += ` - command\n`;
modeEntry += ` - mcp\n`;
return modeEntry;
}

View File

@ -0,0 +1,290 @@
const path = require('node:path');
const fs = require('fs-extra');
const chalk = require('chalk');
const { BaseIdeSetup } = require('./_base-ide');
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator');
/**
* Rovo Dev IDE setup handler
*
* Installs BMAD agents as Rovo Dev subagents in .rovodev/subagents/
* Installs workflows and tasks/tools as reference guides in .rovodev/
* Rovo Dev automatically discovers agents and integrates with BMAD like other IDEs
*/
class RovoDevSetup extends BaseIdeSetup {
constructor() {
super('rovo-dev', 'Atlassian Rovo Dev', true); // preferred IDE
this.configDir = '.rovodev';
this.subagentsDir = 'subagents';
this.workflowsDir = 'workflows';
this.referencesDir = 'references';
}
/**
* Cleanup old BMAD installation before reinstalling
* @param {string} projectDir - Project directory
*/
async cleanup(projectDir) {
const rovoDevDir = path.join(projectDir, this.configDir);
if (!(await fs.pathExists(rovoDevDir))) {
return;
}
// Clean BMAD agents from subagents directory
const subagentsDir = path.join(rovoDevDir, this.subagentsDir);
if (await fs.pathExists(subagentsDir)) {
const entries = await fs.readdir(subagentsDir);
const bmadFiles = entries.filter((file) => file.startsWith('bmad-') && file.endsWith('.md'));
for (const file of bmadFiles) {
await fs.remove(path.join(subagentsDir, file));
}
}
// Clean BMAD workflows from workflows directory
const workflowsDir = path.join(rovoDevDir, this.workflowsDir);
if (await fs.pathExists(workflowsDir)) {
const entries = await fs.readdir(workflowsDir);
const bmadFiles = entries.filter((file) => file.startsWith('bmad-') && file.endsWith('.md'));
for (const file of bmadFiles) {
await fs.remove(path.join(workflowsDir, file));
}
}
// Clean BMAD tasks/tools from references directory
const referencesDir = path.join(rovoDevDir, this.referencesDir);
if (await fs.pathExists(referencesDir)) {
const entries = await fs.readdir(referencesDir);
const bmadFiles = entries.filter((file) => file.startsWith('bmad-') && file.endsWith('.md'));
for (const file of bmadFiles) {
await fs.remove(path.join(referencesDir, file));
}
}
}
/**
* Setup Rovo Dev configuration
* @param {string} projectDir - Project directory
* @param {string} bmadDir - BMAD installation directory
* @param {Object} options - Setup options
*/
async setup(projectDir, bmadDir, options = {}) {
console.log(chalk.cyan(`Setting up ${this.name}...`));
// Clean up old BMAD installation first
await this.cleanup(projectDir);
// Create .rovodev directory structure
const rovoDevDir = path.join(projectDir, this.configDir);
const subagentsDir = path.join(rovoDevDir, this.subagentsDir);
const workflowsDir = path.join(rovoDevDir, this.workflowsDir);
const referencesDir = path.join(rovoDevDir, this.referencesDir);
await this.ensureDir(subagentsDir);
await this.ensureDir(workflowsDir);
await this.ensureDir(referencesDir);
// Generate and install agents
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
let agentCount = 0;
for (const artifact of agentArtifacts) {
const subagentFilename = `bmad-${artifact.module}-${artifact.name}.md`;
const targetPath = path.join(subagentsDir, subagentFilename);
const subagentContent = this.convertToRovoDevSubagent(artifact.content, artifact.name, artifact.module);
await this.writeFile(targetPath, subagentContent);
agentCount++;
}
// Generate and install workflows
const workflowGen = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts, counts: workflowCounts } = await workflowGen.collectWorkflowArtifacts(bmadDir);
let workflowCount = 0;
for (const artifact of workflowArtifacts) {
if (artifact.type === 'workflow-command') {
const workflowFilename = path.basename(artifact.relativePath);
const targetPath = path.join(workflowsDir, workflowFilename);
await this.writeFile(targetPath, artifact.content);
workflowCount++;
}
}
// Generate and install tasks and tools
const taskToolGen = new TaskToolCommandGenerator();
const { tasks: taskCount, tools: toolCount } = await this.generateTaskToolReferences(bmadDir, referencesDir, taskToolGen);
// Summary output
console.log(chalk.green(`${this.name} configured:`));
console.log(chalk.dim(` - ${agentCount} agents installed to .rovodev/subagents/`));
if (workflowCount > 0) {
console.log(chalk.dim(` - ${workflowCount} workflows installed to .rovodev/workflows/`));
}
if (taskCount + toolCount > 0) {
console.log(
chalk.dim(` - ${taskCount + toolCount} tasks/tools installed to .rovodev/references/ (${taskCount} tasks, ${toolCount} tools)`),
);
}
console.log(chalk.yellow(`\n Note: Agents are automatically discovered by Rovo Dev`));
console.log(chalk.dim(` - Access agents by typing @ in Rovo Dev to see available options`));
console.log(chalk.dim(` - Workflows and references are available in .rovodev/ directory`));
return {
success: true,
agents: agentCount,
workflows: workflowCount,
tasks: taskCount,
tools: toolCount,
};
}
/**
* Generate task and tool reference guides
* @param {string} bmadDir - BMAD directory
* @param {string} referencesDir - References directory
* @param {TaskToolCommandGenerator} taskToolGen - Generator instance
*/
async generateTaskToolReferences(bmadDir, referencesDir, taskToolGen) {
const tasks = await taskToolGen.loadTaskManifest(bmadDir);
const tools = await taskToolGen.loadToolManifest(bmadDir);
const standaloneTasks = tasks ? tasks.filter((t) => t.standalone === 'true' || t.standalone === true) : [];
const standaloneTools = tools ? tools.filter((t) => t.standalone === 'true' || t.standalone === true) : [];
let taskCount = 0;
for (const task of standaloneTasks) {
const commandContent = taskToolGen.generateCommandContent(task, 'task');
const targetPath = path.join(referencesDir, `bmad-task-${task.module}-${task.name}.md`);
await this.writeFile(targetPath, commandContent);
taskCount++;
}
let toolCount = 0;
for (const tool of standaloneTools) {
const commandContent = taskToolGen.generateCommandContent(tool, 'tool');
const targetPath = path.join(referencesDir, `bmad-tool-${tool.module}-${tool.name}.md`);
await this.writeFile(targetPath, commandContent);
toolCount++;
}
return { tasks: taskCount, tools: toolCount };
}
/**
* Convert BMAD agent launcher to Rovo Dev subagent format
*
* Rovo Dev subagents use Markdown files with YAML frontmatter containing:
* - name: Unique identifier for the subagent
* - description: One-line description of the subagent's purpose
* - tools: Array of tools the subagent can use (optional)
* - model: Specific model for this subagent (optional)
* - load_memory: Whether to load memory files (optional, defaults to true)
*
* @param {string} launcherContent - Original agent launcher content
* @param {string} agentName - Name of the agent
* @param {string} moduleName - Name of the module
* @returns {string} Rovo Dev subagent-formatted content
*/
convertToRovoDevSubagent(launcherContent, agentName, moduleName) {
// Extract metadata from the launcher XML
const titleMatch = launcherContent.match(/title="([^"]+)"/);
const title = titleMatch ? titleMatch[1] : this.formatTitle(agentName);
const descriptionMatch = launcherContent.match(/description="([^"]+)"/);
const description = descriptionMatch ? descriptionMatch[1] : `BMAD agent: ${title}`;
const roleDefinitionMatch = launcherContent.match(/roleDefinition="([^"]+)"/);
const roleDefinition = roleDefinitionMatch ? roleDefinitionMatch[1] : `You are a specialized agent for ${title.toLowerCase()} tasks.`;
// Extract the main system prompt from the launcher (content after closing tags)
let systemPrompt = roleDefinition;
// Try to extract additional instructions from the launcher content
const instructionsMatch = launcherContent.match(/<instructions>([\s\S]*?)<\/instructions>/);
if (instructionsMatch) {
systemPrompt += '\n\n' + instructionsMatch[1].trim();
}
// Build YAML frontmatter for Rovo Dev subagent
const frontmatter = {
name: `bmad-${moduleName}-${agentName}`,
description: description,
// Note: tools and model can be added by users in their .rovodev/subagents/*.md files
// We don't enforce specific tools since BMAD agents are flexible
};
// Create YAML frontmatter string with proper quoting for special characters
let yamlContent = '---\n';
yamlContent += `name: ${frontmatter.name}\n`;
// Quote description to handle colons and other special characters in YAML
yamlContent += `description: "${frontmatter.description.replaceAll('"', String.raw`\"`)}"\n`;
yamlContent += '---\n';
// Combine frontmatter with system prompt
const subagentContent = yamlContent + systemPrompt;
return subagentContent;
}
/**
* Detect whether Rovo Dev is already configured in the project
* @param {string} projectDir - Project directory
* @returns {boolean}
*/
async detect(projectDir) {
const rovoDevDir = path.join(projectDir, this.configDir);
if (!(await fs.pathExists(rovoDevDir))) {
return false;
}
// Check for BMAD agents in subagents directory
const subagentsDir = path.join(rovoDevDir, this.subagentsDir);
if (await fs.pathExists(subagentsDir)) {
try {
const entries = await fs.readdir(subagentsDir);
if (entries.some((entry) => entry.startsWith('bmad-') && entry.endsWith('.md'))) {
return true;
}
} catch {
// Continue checking other directories
}
}
// Check for BMAD workflows in workflows directory
const workflowsDir = path.join(rovoDevDir, this.workflowsDir);
if (await fs.pathExists(workflowsDir)) {
try {
const entries = await fs.readdir(workflowsDir);
if (entries.some((entry) => entry.startsWith('bmad-') && entry.endsWith('.md'))) {
return true;
}
} catch {
// Continue checking other directories
}
}
// Check for BMAD tasks/tools in references directory
const referencesDir = path.join(rovoDevDir, this.referencesDir);
if (await fs.pathExists(referencesDir)) {
try {
const entries = await fs.readdir(referencesDir);
if (entries.some((entry) => entry.startsWith('bmad-') && entry.endsWith('.md'))) {
return true;
}
} catch {
// Continue
}
}
return false;
}
}
module.exports = { RovoDevSetup };

View File

@ -1,3 +1,23 @@
/**
* File: tools/cli/lib/ui.js
*
* BMAD Method - Business Model Agile Development Method
* Repository: https://github.com/paulpreibisch/BMAD-METHOD
*
* Copyright (c) 2025 Paul Preibisch
* Licensed under the Apache License, Version 2.0
*
* ---
*
* @fileoverview Interactive installation prompts and user input collection for BMAD CLI
* @context Guides users through installation configuration including core settings, modules, IDEs, and optional AgentVibes TTS
* @architecture Facade pattern - presents unified installation flow, delegates to Detector/ConfigCollector/IdeManager for specifics
* @dependencies inquirer (prompts), chalk (formatting), detector.js (existing installation detection)
* @entrypoints Called by install.js command via ui.promptInstall(), returns complete configuration object
* @patterns Progressive disclosure (prompts in order), early IDE selection (Windows compat), AgentVibes auto-detection
* @related installer.js (consumes config), AgentVibes#34 (TTS integration), promptAgentVibes()
*/
const chalk = require('chalk');
const inquirer = require('inquirer');
const path = require('node:path');
@ -99,6 +119,9 @@ class UI {
const moduleChoices = await this.getModuleChoices(installedModuleIds);
const selectedModules = await this.selectModules(moduleChoices);
// Prompt for AgentVibes TTS integration
const agentVibesConfig = await this.promptAgentVibes(confirmedDirectory);
// Collect IDE tool selection AFTER configuration prompts (fixes Windows/PowerShell hang)
// This allows text-based prompts to complete before the checkbox prompt
const toolSelection = await this.promptToolSelection(confirmedDirectory, selectedModules);
@ -114,6 +137,8 @@ class UI {
ides: toolSelection.ides,
skipIde: toolSelection.skipIde,
coreConfig: coreConfig, // Pass collected core config to installer
enableAgentVibes: agentVibesConfig.enabled, // AgentVibes TTS integration
agentVibesInstalled: agentVibesConfig.alreadyInstalled,
};
}
@ -639,6 +664,140 @@ class UI {
// Resolve to the absolute path relative to the current working directory
return path.resolve(expanded);
}
/**
* @function promptAgentVibes
* @intent Ask user if they want AgentVibes TTS integration during BMAD installation
* @why Enables optional voice features without forcing TTS on users who don't want it
* @param {string} projectDir - Absolute path to user's project directory
* @returns {Promise<Object>} Configuration object: { enabled: boolean, alreadyInstalled: boolean }
* @sideeffects None - pure user input collection, no files written
* @edgecases Shows warning if user enables TTS but AgentVibes not detected
* @calledby promptInstall() during installation flow, after core config, before IDE selection
* @calls checkAgentVibesInstalled(), inquirer.prompt(), chalk.green/yellow/dim()
*
* AI NOTE: This prompt is strategically positioned in installation flow:
* - AFTER core config (bmad_folder, user_name, etc)
* - BEFORE IDE selection (which can hang on Windows/PowerShell)
*
* Flow Logic:
* 1. Auto-detect if AgentVibes already installed (checks for hook files)
* 2. Show detection status to user (green checkmark or gray "not detected")
* 3. Prompt: "Enable AgentVibes TTS?" (defaults to true if detected)
* 4. If user says YES but AgentVibes NOT installed:
* Show warning with installation link (graceful degradation)
* 5. Return config to promptInstall(), which passes to installer.install()
*
* State Flow:
* promptAgentVibes() { enabled, alreadyInstalled }
*
* promptInstall() config.enableAgentVibes
*
* installer.install() this.enableAgentVibes
*
* processTTSInjectionPoints() injects OR strips markers
*
* RELATED:
* ========
* - Detection: checkAgentVibesInstalled() - looks for bmad-speak.sh and play-tts.sh
* - Processing: installer.js::processTTSInjectionPoints()
* - Markers: src/core/workflows/party-mode/instructions.md:101, src/modules/bmm/agents/*.md
* - GitHub Issue: paulpreibisch/AgentVibes#36
*/
async promptAgentVibes(projectDir) {
CLIUtils.displaySection('🎤 Voice Features', 'Enable TTS for multi-agent conversations');
// Check if AgentVibes is already installed
const agentVibesInstalled = await this.checkAgentVibesInstalled(projectDir);
if (agentVibesInstalled) {
console.log(chalk.green(' ✓ AgentVibes detected'));
} else {
console.log(chalk.dim(' AgentVibes not detected'));
}
const answers = await inquirer.prompt([
{
type: 'confirm',
name: 'enableTts',
message: 'Enable AgentVibes TTS? (Claude Code only - Agents speak with unique voices in party mode)',
default: true, // Default to yes - recommended for best experience
},
]);
if (answers.enableTts && !agentVibesInstalled) {
console.log(chalk.yellow('\n ⚠️ AgentVibes not installed'));
console.log(chalk.dim(' Install AgentVibes separately to enable TTS:'));
console.log(chalk.dim(' https://github.com/paulpreibisch/AgentVibes\n'));
}
return {
enabled: answers.enableTts,
alreadyInstalled: agentVibesInstalled,
};
}
/**
* @function checkAgentVibesInstalled
* @intent Detect if AgentVibes TTS hooks are present in user's project
* @why Allows auto-enabling TTS and showing helpful installation guidance
* @param {string} projectDir - Absolute path to user's project directory
* @returns {Promise<boolean>} true if both required AgentVibes hooks exist, false otherwise
* @sideeffects None - read-only file existence checks
* @edgecases Returns false if either hook missing (both required for functional TTS)
* @calledby promptAgentVibes() to determine default value and show detection status
* @calls fs.pathExists() twice (bmad-speak.sh, play-tts.sh)
*
* AI NOTE: This checks for the MINIMUM viable AgentVibes installation.
*
* Required Files:
* ===============
* 1. .claude/hooks/bmad-speak.sh
* - Maps agent display names agent IDs voice profiles
* - Calls play-tts.sh with agent's assigned voice
* - Created by AgentVibes installer
*
* 2. .claude/hooks/play-tts.sh
* - Core TTS router (ElevenLabs or Piper)
* - Provider-agnostic interface
* - Required by bmad-speak.sh
*
* Why Both Required:
* ==================
* - bmad-speak.sh alone: No TTS backend
* - play-tts.sh alone: No BMAD agent voice mapping
* - Both together: Full party mode TTS integration
*
* Detection Strategy:
* ===================
* We use simple file existence (not version checks) because:
* - Fast and reliable
* - Works across all AgentVibes versions
* - User will discover version issues when TTS runs (fail-fast)
*
* PATTERN: Adding New Detection Criteria
* =======================================
* If future AgentVibes features require additional files:
* 1. Add new pathExists check to this function
* 2. Update documentation in promptAgentVibes()
* 3. Consider: should missing file prevent detection or just log warning?
*
* RELATED:
* ========
* - AgentVibes Installer: creates these hooks
* - bmad-speak.sh: calls play-tts.sh with agent voices
* - Party Mode: uses bmad-speak.sh for agent dialogue
*/
async checkAgentVibesInstalled(projectDir) {
const fs = require('fs-extra');
const path = require('node:path');
// Check for AgentVibes hook files
const hookPath = path.join(projectDir, '.claude', 'hooks', 'bmad-speak.sh');
const playTtsPath = path.join(projectDir, '.claude', 'hooks', 'play-tts.sh');
return (await fs.pathExists(hookPath)) && (await fs.pathExists(playTtsPath));
}
}
module.exports = { UI };

View File

@ -55,6 +55,12 @@ platforms:
category: ide
description: "Enhanced Cline fork"
rovo:
name: "Rovo Dev"
preferred: false
category: ide
description: "Atlassian's AI coding assistant"
github-copilot:
name: "GitHub Copilot"
preferred: false