From d9b10490b4486679ae51f8569167d2694b98e327 Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Thu, 27 Nov 2025 09:46:16 -0700 Subject: [PATCH 1/7] fix: Clear all npm config env vars before calling AgentVibes installer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When BMAD is invoked with --prefix flag, npm sets many npm_config_* and npm_package_* environment variables. These caused npx agentvibes to look for files in the wrong directory (/prefix/lib instead of cwd). Changes: - tools/cli/commands/install.js: Filter out ALL npm_config_* and npm_package_* env vars before calling npx agentvibes - tools/cli/installers/lib/core/installer.js: Add AgentVibes prompt to Quick Update flow so existing installations can enable TTS - tools/cli/installers/lib/core/manifest-generator.js: Track agentVibes configuration in manifest.yaml This ensures AgentVibes runs in a clean environment regardless of how BMAD was invoked (with or without --prefix flag). šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- tools/cli/commands/install.js | 8 +++++ tools/cli/installers/lib/core/installer.js | 33 +++++++++++++++++++ .../installers/lib/core/manifest-generator.js | 4 +++ 3 files changed, 45 insertions(+) diff --git a/tools/cli/commands/install.js b/tools/cli/commands/install.js index d5742cf7..4ada1489 100644 --- a/tools/cli/commands/install.js +++ b/tools/cli/commands/install.js @@ -90,10 +90,18 @@ module.exports = { // Run AgentVibes installer const { execSync } = require('node:child_process'); try { + // Clear ALL npm config env vars to prevent inheritance issues + // when BMAD is invoked with --prefix flag + // npm sets many npm_config_* and npm_package_* vars that can interfere + const cleanEnv = Object.fromEntries( + Object.entries(process.env).filter(([key]) => !key.startsWith('npm_config_') && !key.startsWith('npm_package_')), + ); + execSync('npx agentvibes@latest install', { cwd: result.projectDir, stdio: 'inherit', shell: true, + env: cleanEnv, }); console.log(chalk.green('\nāœ“ AgentVibes installation complete')); } catch { diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index f113c141..4abe6eb5 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -824,6 +824,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: const manifestStats = await manifestGen.generateManifests(bmadDir, config.modules || [], this.installedFiles, { ides: config.ides || [], preservedModules: config._preserveModules || [], // Scan these from installed bmad/ dir + agentVibes: { enabled: this.enableAgentVibes || false }, // Track AgentVibes TTS configuration }); spinner.succeed( @@ -1966,6 +1967,37 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: } } + // Check for AgentVibes TTS - prompt if not previously configured + // Read existing manifest to check if AgentVibes was previously set + const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + let agentVibesEnabled = false; + let agentVibesPreviouslyConfigured = false; + + try { + const manifestContent = await fs.readFile(manifestPath, 'utf8'); + const yaml = require('js-yaml'); + const manifest = yaml.load(manifestContent); + // Check if AgentVibes was previously configured (exists in manifest) + if (manifest.agentVibes !== undefined) { + agentVibesPreviouslyConfigured = true; + agentVibesEnabled = manifest.agentVibes?.enabled || false; + } + } catch { + // Manifest doesn't exist or can't be read - treat as not configured + } + + // If AgentVibes wasn't previously configured, prompt the user + if (!agentVibesPreviouslyConfigured) { + const { UI } = require('../../../lib/ui'); + const ui = new UI(); + const agentVibesConfig = await ui.promptAgentVibes(projectDir); + + if (agentVibesConfig.enableTts) { + agentVibesEnabled = true; + promptedForNewFields = true; + } + } + if (!promptedForNewFields) { console.log(chalk.green('āœ“ All configuration is up to date, no new options to configure')); } @@ -2003,6 +2035,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: _quickUpdate: true, // Flag to skip certain prompts _preserveModules: skippedModules, // Preserve these in manifest even though we didn't update them _savedIdeConfigs: savedIdeConfigs, // Pass saved IDE configs to installer + enableAgentVibes: agentVibesEnabled, // AgentVibes TTS configuration }; // Call the standard install method diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index f10d0deb..8612a0b4 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -54,6 +54,9 @@ class ManifestGenerator { // Filter out any undefined/null values from IDE list this.selectedIdes = resolvedIdes.filter((ide) => ide && typeof ide === 'string'); + // Store AgentVibes configuration for manifest + this.agentVibes = options.agentVibes || null; + // Collect workflow data await this.collectWorkflows(selectedModules); @@ -446,6 +449,7 @@ class ManifestGenerator { }, modules: this.modules, ides: this.selectedIdes, + agentVibes: this.agentVibes, // Track AgentVibes TTS configuration }; const yamlStr = yaml.dump(manifest, { From 08aaf5e2f3c8e863e1a049e45ffba9810e385c94 Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Thu, 27 Nov 2025 09:54:17 -0700 Subject: [PATCH 2/7] feat: Swap bmad-master and pm voice assignments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bmad-master: en_US-ryan-high → en_US-lessac-medium - pm (john): en_US-lessac-medium → en_US-ryan-high šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .bmad/_cfg/agent-voice-map.csv | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .bmad/_cfg/agent-voice-map.csv diff --git a/.bmad/_cfg/agent-voice-map.csv b/.bmad/_cfg/agent-voice-map.csv new file mode 100644 index 00000000..18a20fe4 --- /dev/null +++ b/.bmad/_cfg/agent-voice-map.csv @@ -0,0 +1,11 @@ +agent,voice +bmad-master,en_US-lessac-medium +analyst,en_US-kristin-medium +architect,en_GB-alan-medium +dev,en_US-joe-medium +pm,en_US-ryan-high +sm,en_US-amy-medium +tea,en_US-kusal-medium +tech-writer,jenny +ux-designer,kristin +frame-expert,en_GB-alan-medium From fe79f7776803f4fb4f3ded45135933f693bf4f61 Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Thu, 27 Nov 2025 10:04:00 -0700 Subject: [PATCH 3/7] feat: Move AgentVibes prompt after tool selection with smart defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move AgentVibes TTS prompt to after IDE/tool selection - Default to Y if Claude Code is selected (since AgentVibes only works with Claude Code) - Default to N if Claude Code is not selected - Remove mid-install warning about AgentVibes not being installed (handled at end) - Pass configured IDEs to quick update flow for consistent behavior šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- tools/cli/installers/lib/core/installer.js | 3 ++- tools/cli/lib/ui.js | 24 ++++++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 4abe6eb5..562b0731 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -1987,10 +1987,11 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: } // If AgentVibes wasn't previously configured, prompt the user + // Use configuredIdes from line 1904 for smart default (Y if Claude Code is selected) if (!agentVibesPreviouslyConfigured) { const { UI } = require('../../../lib/ui'); const ui = new UI(); - const agentVibesConfig = await ui.promptAgentVibes(projectDir); + const agentVibesConfig = await ui.promptAgentVibes(projectDir, configuredIdes); if (agentVibesConfig.enableTts) { agentVibesEnabled = true; diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index 4c5b3379..f5db8520 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -119,13 +119,14 @@ 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); + // Prompt for AgentVibes TTS integration AFTER tool selection + // Default to Y if Claude Code is selected (since AgentVibes only works with Claude Code) + const agentVibesConfig = await this.promptAgentVibes(confirmedDirectory, toolSelection.ides); + // No more screen clearing - keep output flowing return { @@ -753,7 +754,7 @@ class UI { * - Markers: src/core/workflows/party-mode/instructions.md:101, src/modules/bmm/agents/*.md * - GitHub Issue: paulpreibisch/AgentVibes#36 */ - async promptAgentVibes(projectDir) { + async promptAgentVibes(projectDir, selectedIdes = []) { CLIUtils.displaySection('šŸŽ¤ Voice Features', 'Enable TTS for multi-agent conversations'); // Check if AgentVibes is already installed @@ -765,20 +766,21 @@ class UI { console.log(chalk.dim(' AgentVibes not detected')); } + // Default to Y if Claude Code is selected (AgentVibes only works with Claude Code) + const claudeCodeSelected = selectedIdes.includes('claude-code'); + const defaultValue = claudeCodeSelected; + const answers = await inquirer.prompt([ { type: 'confirm', name: 'enableTts', - message: 'Enable Agents to Speak Out loud (powered by Agent Vibes? Claude Code only currently)', - default: false, // Default to yes - recommended for best experience + message: 'Enable Agents to Speak Out loud (powered by AgentVibes, Claude Code only)', + default: defaultValue, }, ]); - 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')); - } + // Note: AgentVibes installer runs at end of BMAD install if enabled and not already installed + // No need to show warning here - the installer will handle it return { enabled: answers.enableTts, From 6e0b36f0e02012197268e0a938b6699dc608f85e Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Thu, 27 Nov 2025 11:00:01 -0700 Subject: [PATCH 4/7] feat: Add voice map generation with agent intros for party mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Generate _cfg/agent-voice-map.csv during BMAD install with voice and intro columns - Update party mode instructions to have 3-4 agents introduce themselves on activation - Each agent speaks their personalized intro message via TTS šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/core/workflows/party-mode/workflow.md | 20 ++++- .../installers/lib/core/manifest-generator.js | 75 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/core/workflows/party-mode/workflow.md b/src/core/workflows/party-mode/workflow.md index 38f2ce82..1c580dfa 100644 --- a/src/core/workflows/party-mode/workflow.md +++ b/src/core/workflows/party-mode/workflow.md @@ -38,6 +38,7 @@ Load config from `{project-root}/{bmad_folder}/bmm/config.yaml` and resolve: - `installed_path` = `{project-root}/{bmad_folder}/core/workflows/party-mode` - `agent_manifest_path` = `{project-root}/{bmad_folder}/_cfg/agent-manifest.csv` +- `agent_voice_map_path` = `{project-root}/{bmad_folder}/_cfg/agent-voice-map.csv` - `standalone_mode` = `true` (party mode is an interactive workflow) --- @@ -63,6 +64,16 @@ Parse CSV manifest to extract agent entries with complete information: Build complete agent roster with merged personalities for conversation orchestration. +### Voice Map Loading (Optional) + +If `agent_voice_map_path` exists, load agent voice configuration: + +- **agent** (agent identifier matching manifest name) +- **voice** (TTS voice name for the agent) +- **intro** (introduction message the agent uses when joining party mode) + +Merge voice map data with agent roster for TTS integration and personalized introductions. + --- ## EXECUTION @@ -81,7 +92,14 @@ Welcome {{user_name}}! All BMAD agents are here and ready for a dynamic group di **Let me introduce our collaborating agents:** -[Load agent roster and display 2-3 most diverse agents as examples] +[Load agent roster and display all agents with their icons and titles] + +**Agent Introductions (if voice map with intros is available):** + +For each agent in the roster, if they have an intro message from the voice map: +- Have the agent speak their intro message in-character +- Use TTS to voice the introduction with their assigned voice +- Format: `Bash: .claude/hooks/bmad-speak.sh "[Agent Name]" "[Their intro message]"` **What would you like to discuss with the team today?**" diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index 8612a0b4..141fb45a 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -74,6 +74,7 @@ class ManifestGenerator { await this.writeMainManifest(cfgDir), await this.writeWorkflowManifest(cfgDir), await this.writeAgentManifest(cfgDir), + await this.writeVoiceMap(cfgDir), await this.writeTaskManifest(cfgDir), await this.writeToolManifest(cfgDir), await this.writeFilesManifest(cfgDir), @@ -585,6 +586,80 @@ class ManifestGenerator { return csvPath; } + /** + * Write agent voice map CSV for AgentVibes TTS integration + * Maps agent IDs to default Piper TTS voices and intro messages + * AgentVibes will use this if present, otherwise falls back to its own defaults + * @returns {string} Path to the voice map file + */ + async writeVoiceMap(cfgDir) { + const csvPath = path.join(cfgDir, 'agent-voice-map.csv'); + + // Default voice assignments and intros for BMAD agents + // These can be customized by editing the generated CSV + const agentDefaults = { + 'bmad-master': { + voice: 'en_US-lessac-medium', + intro: 'Greetings! The BMad Master is here to orchestrate and guide you through any workflow.', + }, + analyst: { + voice: 'en_US-kristin-medium', + intro: "Hi there! I'm Mary, your Business Analyst. I'll help uncover the real requirements.", + }, + architect: { + voice: 'en_GB-alan-medium', + intro: "Hello! Winston here, your Architect. I'll ensure we build something scalable and pragmatic.", + }, + dev: { + voice: 'en_US-joe-medium', + intro: 'Hey! Amelia here, your Developer. Ready to turn specs into working code.', + }, + pm: { + voice: 'en_US-ryan-high', + intro: "Hey team! John here, your Product Manager. Let's make sure we're building the right thing.", + }, + sm: { + voice: 'en_US-amy-medium', + intro: "Hi everyone! Bob here, your Scrum Master. I'll keep us focused and moving forward.", + }, + tea: { + voice: 'en_US-kusal-medium', + intro: 'Hello! Murat here, your Test Architect. Quality is my obsession.', + }, + 'tech-writer': { + voice: 'jenny', + intro: "Hi! I'm Paige, your Technical Writer. I'll make sure everything is documented clearly.", + }, + 'ux-designer': { + voice: 'kristin', + intro: 'Hey! Sally here, your UX Designer. The user experience is my top priority.', + }, + 'frame-expert': { + voice: 'en_GB-alan-medium', + intro: "Hello! Saif here, your Visual Design Expert. I'll help visualize your ideas.", + }, + }; + + // Fallback values for agents not in the default map + const fallbackVoice = 'en_US-lessac-medium'; + const fallbackIntro = 'Hello! Ready to help with the discussion.'; + + let csv = 'agent,voice,intro\n'; + + // Add voice mapping and intro for each discovered agent + for (const agent of this.agents) { + const defaults = agentDefaults[agent.name] || {}; + const voice = defaults.voice || fallbackVoice; + const intro = defaults.intro || fallbackIntro; + // Escape quotes in intro for CSV + const escapedIntro = intro.replaceAll('"', '""'); + csv += `${agent.name},${voice},"${escapedIntro}"\n`; + } + + await fs.writeFile(csvPath, csv); + return csvPath; + } + /** * Write task manifest CSV * @returns {string} Path to the manifest file From ba2d6c5cad6f6728ae55945f84e3a5b31def1ed3 Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Thu, 27 Nov 2025 14:28:32 -0700 Subject: [PATCH 5/7] fix: Always run AgentVibes installer when enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, BMAD would skip the AgentVibes installer if it detected existing hook files (.claude/hooks/bmad-speak.sh and play-tts.sh). This prevented users from getting AgentVibes updates. Now when user says "Yes" to AgentVibes, it always runs the installer, ensuring users get the latest version with new features and fixes. šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- tools/cli/installers/lib/core/installer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 562b0731..1e67cf43 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -1059,7 +1059,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: path: bmadDir, modules: config.modules, ides: config.ides, - needsAgentVibes: this.enableAgentVibes && !config.agentVibesInstalled, + needsAgentVibes: this.enableAgentVibes, // Always run installer if enabled - handles updates too projectDir: projectDir, }; } catch (error) { From bb2942ef0b1097ebe140bce0f4f3016732714d8b Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Sat, 6 Dec 2025 12:51:50 -0700 Subject: [PATCH 6/7] fix: Apply Prettier formatting to workflow.md --- src/core/workflows/party-mode/workflow.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/workflows/party-mode/workflow.md b/src/core/workflows/party-mode/workflow.md index 1c580dfa..1e54125b 100644 --- a/src/core/workflows/party-mode/workflow.md +++ b/src/core/workflows/party-mode/workflow.md @@ -97,6 +97,7 @@ Welcome {{user_name}}! All BMAD agents are here and ready for a dynamic group di **Agent Introductions (if voice map with intros is available):** For each agent in the roster, if they have an intro message from the voice map: + - Have the agent speak their intro message in-character - Use TTS to voice the introduction with their assigned voice - Format: `Bash: .claude/hooks/bmad-speak.sh "[Agent Name]" "[Their intro message]"` From 961c50f752be4c8e5f82337df05fcb6e46be0739 Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Sat, 6 Dec 2025 13:04:14 -0700 Subject: [PATCH 7/7] fix: Remove agent-voice-map.csv from tracking (user-specific file) --- .bmad/_cfg/agent-voice-map.csv | 11 ----------- .gitignore | 3 +++ 2 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 .bmad/_cfg/agent-voice-map.csv diff --git a/.bmad/_cfg/agent-voice-map.csv b/.bmad/_cfg/agent-voice-map.csv deleted file mode 100644 index 18a20fe4..00000000 --- a/.bmad/_cfg/agent-voice-map.csv +++ /dev/null @@ -1,11 +0,0 @@ -agent,voice -bmad-master,en_US-lessac-medium -analyst,en_US-kristin-medium -architect,en_GB-alan-medium -dev,en_US-joe-medium -pm,en_US-ryan-high -sm,en_US-amy-medium -tea,en_US-kusal-medium -tech-writer,jenny -ux-designer,kristin -frame-expert,en_GB-alan-medium diff --git a/.gitignore b/.gitignore index 47a82e6e..bdd6c859 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,6 @@ z*/ .agentvibes/ .kiro/ .roo + +# Generated voice map (user-specific) +.bmad/_cfg/agent-voice-map.csv