agentvibes 2.0.9 → 2.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/.claude/commands/agent-vibes/bmad.md +203 -0
  2. package/.claude/github-star-reminder.txt +1 -0
  3. package/.claude/hooks/bmad-tts-injector.sh +333 -0
  4. package/.claude/hooks/bmad-voice-manager.sh +34 -0
  5. package/.claude/hooks/check-output-style.sh +2 -2
  6. package/.claude/hooks/github-star-reminder.sh +94 -0
  7. package/.claude/hooks/personality-manager.sh +2 -2
  8. package/.claude/hooks/piper-installer.sh +194 -0
  9. package/.claude/hooks/play-tts-elevenlabs.sh +30 -3
  10. package/.claude/hooks/play-tts-local-wrapper.sh +44 -0
  11. package/.claude/hooks/play-tts-piper.sh +10 -2
  12. package/.claude/hooks/play-tts-remote.sh +81 -0
  13. package/.claude/hooks/play-tts.sh +34 -0
  14. package/.claude/hooks/provider-commands.sh +30 -1
  15. package/.claude/hooks/voice-manager.sh +2 -2
  16. package/.claude/output-styles/agent-vibes.md +52 -36
  17. package/README.md +2 -2
  18. package/RELEASE_NOTES.md +412 -0
  19. package/agentvibes.org/.claude/commands/agent-vibes/add.md +21 -0
  20. package/agentvibes.org/.claude/commands/agent-vibes/agent-vibes.md +68 -0
  21. package/agentvibes.org/.claude/commands/agent-vibes/commands.json +53 -0
  22. package/agentvibes.org/.claude/commands/agent-vibes/get.md +9 -0
  23. package/agentvibes.org/.claude/commands/agent-vibes/list.md +13 -0
  24. package/agentvibes.org/.claude/commands/agent-vibes/personality.md +79 -0
  25. package/agentvibes.org/.claude/commands/agent-vibes/preview.md +16 -0
  26. package/agentvibes.org/.claude/commands/agent-vibes/provider.md +54 -0
  27. package/agentvibes.org/.claude/commands/agent-vibes/replay.md +19 -0
  28. package/agentvibes.org/.claude/commands/agent-vibes/sample.md +12 -0
  29. package/agentvibes.org/.claude/commands/agent-vibes/sentiment.md +52 -0
  30. package/agentvibes.org/.claude/commands/agent-vibes/set-language.md +47 -0
  31. package/agentvibes.org/.claude/commands/agent-vibes/set-pretext.md +65 -0
  32. package/agentvibes.org/.claude/commands/agent-vibes/switch.md +53 -0
  33. package/agentvibes.org/.claude/commands/agent-vibes/update.md +20 -0
  34. package/agentvibes.org/.claude/commands/agent-vibes/version.md +10 -0
  35. package/agentvibes.org/.claude/commands/agent-vibes/whoami.md +7 -0
  36. package/agentvibes.org/.claude/hooks/bmad-voice-manager.sh +278 -0
  37. package/agentvibes.org/.claude/hooks/language-manager.sh +190 -0
  38. package/agentvibes.org/.claude/hooks/personality-manager.sh +279 -0
  39. package/agentvibes.org/.claude/hooks/piper-download-voices.sh +133 -0
  40. package/agentvibes.org/.claude/hooks/piper-voice-manager.sh +227 -0
  41. package/agentvibes.org/.claude/hooks/play-tts-elevenlabs.sh +201 -0
  42. package/agentvibes.org/.claude/hooks/play-tts-piper.sh +175 -0
  43. package/agentvibes.org/.claude/hooks/play-tts.sh +138 -0
  44. package/agentvibes.org/.claude/hooks/provider-commands.sh +374 -0
  45. package/agentvibes.org/.claude/hooks/provider-manager.sh +196 -0
  46. package/agentvibes.org/.claude/hooks/sentiment-manager.sh +163 -0
  47. package/agentvibes.org/.claude/hooks/voice-manager.sh +349 -0
  48. package/agentvibes.org/.claude/hooks/voices-config.sh +33 -0
  49. package/agentvibes.org/.claude/journal/2025-10-07.html +373 -0
  50. package/agentvibes.org/.claude/journal/index.html +91 -0
  51. package/agentvibes.org/.claude/output-styles/agent-vibes.md +203 -0
  52. package/agentvibes.org/.claude/personalities/angry.md +16 -0
  53. package/agentvibes.org/.claude/personalities/annoying.md +16 -0
  54. package/agentvibes.org/.claude/personalities/crass.md +16 -0
  55. package/agentvibes.org/.claude/personalities/dramatic.md +16 -0
  56. package/agentvibes.org/.claude/personalities/dry-humor.md +52 -0
  57. package/agentvibes.org/.claude/personalities/flirty.md +22 -0
  58. package/agentvibes.org/.claude/personalities/funny.md +16 -0
  59. package/agentvibes.org/.claude/personalities/grandpa.md +34 -0
  60. package/agentvibes.org/.claude/personalities/millennial.md +16 -0
  61. package/agentvibes.org/.claude/personalities/moody.md +16 -0
  62. package/agentvibes.org/.claude/personalities/normal.md +18 -0
  63. package/agentvibes.org/.claude/personalities/pirate.md +16 -0
  64. package/agentvibes.org/.claude/personalities/poetic.md +16 -0
  65. package/agentvibes.org/.claude/personalities/professional.md +16 -0
  66. package/agentvibes.org/.claude/personalities/robot.md +16 -0
  67. package/agentvibes.org/.claude/personalities/sarcastic.md +40 -0
  68. package/agentvibes.org/.claude/personalities/sassy.md +16 -0
  69. package/agentvibes.org/.claude/personalities/surfer-dude.md +16 -0
  70. package/agentvibes.org/.claude/personalities/zen.md +16 -0
  71. package/agentvibes.org/.mcp-minimal.json +60 -0
  72. package/agentvibes.org/CHANGELOG.md +56 -0
  73. package/agentvibes.org/README.md +93 -0
  74. package/agentvibes.org/app/(auth)/layout.tsx +15 -0
  75. package/agentvibes.org/app/(auth)/reset-password/page.tsx +45 -0
  76. package/agentvibes.org/app/(auth)/signin/page.tsx +82 -0
  77. package/agentvibes.org/app/(auth)/signup/page.tsx +104 -0
  78. package/agentvibes.org/app/(default)/layout.tsx +31 -0
  79. package/agentvibes.org/app/(default)/page.tsx +20 -0
  80. package/agentvibes.org/app/api/hello/route.ts +3 -0
  81. package/agentvibes.org/app/css/additional-styles/theme.css +82 -0
  82. package/agentvibes.org/app/css/additional-styles/utility-patterns.css +55 -0
  83. package/agentvibes.org/app/css/style.css +100 -0
  84. package/agentvibes.org/app/layout.tsx +63 -0
  85. package/agentvibes.org/components/cta.tsx +58 -0
  86. package/agentvibes.org/components/features.tsx +256 -0
  87. package/agentvibes.org/components/hero-home.tsx +133 -0
  88. package/agentvibes.org/components/modal-video.tsx +137 -0
  89. package/agentvibes.org/components/page-illustration.tsx +55 -0
  90. package/agentvibes.org/components/spotlight.tsx +77 -0
  91. package/agentvibes.org/components/testimonials.tsx +282 -0
  92. package/agentvibes.org/components/ui/footer.tsx +82 -0
  93. package/agentvibes.org/components/ui/header.tsx +53 -0
  94. package/agentvibes.org/components/ui/logo.tsx +10 -0
  95. package/agentvibes.org/components/workflows.tsx +176 -0
  96. package/agentvibes.org/next.config.js +4 -0
  97. package/agentvibes.org/package-lock.json +1974 -0
  98. package/agentvibes.org/package.json +30 -0
  99. package/agentvibes.org/pnpm-lock.yaml +1141 -0
  100. package/agentvibes.org/postcss.config.js +5 -0
  101. package/agentvibes.org/public/audio/02-sarcastic.mp3 +0 -0
  102. package/agentvibes.org/public/audio/03-angry.mp3 +0 -0
  103. package/agentvibes.org/public/audio/04-grandpa.mp3 +0 -0
  104. package/agentvibes.org/public/audio/05-sarcastic-example2.mp3 +0 -0
  105. package/agentvibes.org/public/audio/french-rachel.mp3 +0 -0
  106. package/agentvibes.org/public/audio/spanish-antoni.mp3 +0 -0
  107. package/agentvibes.org/public/favicon.ico +0 -0
  108. package/agentvibes.org/public/fonts/nacelle-italic.woff2 +0 -0
  109. package/agentvibes.org/public/fonts/nacelle-regular.woff2 +0 -0
  110. package/agentvibes.org/public/fonts/nacelle-semibold.woff2 +0 -0
  111. package/agentvibes.org/public/fonts/nacelle-semibolditalic.woff2 +0 -0
  112. package/agentvibes.org/public/images/blurred-shape-gray.svg +1 -0
  113. package/agentvibes.org/public/images/blurred-shape.svg +1 -0
  114. package/agentvibes.org/public/images/client-logo-01.svg +1 -0
  115. package/agentvibes.org/public/images/client-logo-02.svg +1 -0
  116. package/agentvibes.org/public/images/client-logo-03.svg +1 -0
  117. package/agentvibes.org/public/images/client-logo-04.svg +1 -0
  118. package/agentvibes.org/public/images/client-logo-05.svg +1 -0
  119. package/agentvibes.org/public/images/client-logo-06.svg +1 -0
  120. package/agentvibes.org/public/images/client-logo-07.svg +1 -0
  121. package/agentvibes.org/public/images/client-logo-08.svg +1 -0
  122. package/agentvibes.org/public/images/client-logo-09.svg +1 -0
  123. package/agentvibes.org/public/images/features.png +0 -0
  124. package/agentvibes.org/public/images/footer-illustration.svg +1 -0
  125. package/agentvibes.org/public/images/hero-image-01.jpg +0 -0
  126. package/agentvibes.org/public/images/logo.svg +1 -0
  127. package/agentvibes.org/public/images/page-illustration.svg +1 -0
  128. package/agentvibes.org/public/images/secondary-illustration.svg +1 -0
  129. package/agentvibes.org/public/images/testimonial-01.jpg +0 -0
  130. package/agentvibes.org/public/images/testimonial-02.jpg +0 -0
  131. package/agentvibes.org/public/images/testimonial-03.jpg +0 -0
  132. package/agentvibes.org/public/images/testimonial-04.jpg +0 -0
  133. package/agentvibes.org/public/images/testimonial-05.jpg +0 -0
  134. package/agentvibes.org/public/images/testimonial-06.jpg +0 -0
  135. package/agentvibes.org/public/images/testimonial-07.jpg +0 -0
  136. package/agentvibes.org/public/images/testimonial-08.jpg +0 -0
  137. package/agentvibes.org/public/images/testimonial-09.jpg +0 -0
  138. package/agentvibes.org/public/images/workflow-01.png +0 -0
  139. package/agentvibes.org/public/images/workflow-02.png +0 -0
  140. package/agentvibes.org/public/images/workflow-03.png +0 -0
  141. package/agentvibes.org/public/videos/video.mp4 +0 -0
  142. package/agentvibes.org/tsconfig.json +28 -0
  143. package/agentvibes.org/utils/useMasonry.tsx +67 -0
  144. package/agentvibes.org/utils/useMousePosition.tsx +27 -0
  145. package/docs/REMOTE_TTS_SETUP.md +190 -0
  146. package/package.json +2 -2
  147. package/src/installer.js +193 -9
  148. package/test/helpers/test-helper.bash +4 -2
  149. package/test/unit/personality-manager.bats +16 -4
  150. package/test/unit/personality-voice-mapping.bats +15 -6
  151. package/test/unit/play-tts.bats +0 -9
  152. package/.claude/commands/agent-vibes-bmad.md +0 -132
package/src/installer.js CHANGED
@@ -47,7 +47,7 @@ function showWelcome() {
47
47
 
48
48
  console.log(
49
49
  boxen(
50
- chalk.white.bold('🎤 Beautiful ElevenLabs TTS Voice Commands for Claude Code\n\n') +
50
+ chalk.white.bold('🎤 Now your AI Agents can finally talk back! TTS Voice for Claude Code\n\n') +
51
51
  chalk.gray('Add professional text-to-speech narration to your AI coding sessions\n\n') +
52
52
  chalk.cyan('📦 https://github.com/paulpreibisch/AgentVibes'),
53
53
  {
@@ -136,8 +136,93 @@ async function install(options = {}) {
136
136
 
137
137
  selectedProvider = provider;
138
138
 
139
- // If Piper selected, ask for voice storage location
139
+ // If Piper selected, check if Piper is installed
140
140
  if (selectedProvider === 'piper') {
141
+ // Check if Piper is installed
142
+ let piperInstalled = false;
143
+ try {
144
+ const { execSync } = await import('node:child_process');
145
+ // First check if piper is in PATH
146
+ execSync('which piper', { stdio: 'ignore' });
147
+ piperInstalled = true;
148
+ } catch {
149
+ // If not in PATH, check if it exists in pipx installation directory
150
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
151
+ const pipxPiperPath = path.join(homeDir, '.local', 'bin', 'piper');
152
+ try {
153
+ await fs.access(pipxPiperPath, fs.constants.X_OK);
154
+ piperInstalled = true;
155
+ console.log(chalk.yellow('\n⚠️ Piper is installed but not in PATH'));
156
+ console.log(chalk.gray(` Location: ${pipxPiperPath}`));
157
+ console.log(chalk.gray(' Run this to add to PATH:'));
158
+ console.log(chalk.cyan(' export PATH="$HOME/.local/bin:$PATH"\n'));
159
+ } catch {
160
+ // Piper not found anywhere
161
+ }
162
+ }
163
+
164
+ if (!piperInstalled) {
165
+ console.log(chalk.yellow('\n⚠️ Piper TTS is not installed'));
166
+ console.log(chalk.gray(' Piper is a free, offline neural TTS system'));
167
+ console.log(chalk.gray(' It needs to be installed separately via pipx\n'));
168
+
169
+ const { installPiper } = await inquirer.prompt([
170
+ {
171
+ type: 'confirm',
172
+ name: 'installPiper',
173
+ message: 'Would you like to install Piper TTS now?',
174
+ default: true,
175
+ },
176
+ ]);
177
+
178
+ if (installPiper) {
179
+ console.log(chalk.cyan('\n🚀 Installing Piper TTS...\n'));
180
+
181
+ // Check if piper-installer.sh exists in the source directory
182
+ const piperInstallerPath = path.join(__dirname, '..', '.claude', 'hooks', 'piper-installer.sh');
183
+
184
+ try {
185
+ await fs.access(piperInstallerPath);
186
+
187
+ // Run the Piper installer
188
+ const { execSync } = await import('node:child_process');
189
+ try {
190
+ execSync(`bash "${piperInstallerPath}"`, {
191
+ stdio: 'inherit',
192
+ cwd: path.dirname(piperInstallerPath)
193
+ });
194
+
195
+ // Verify installation succeeded
196
+ try {
197
+ execSync('which piper', { stdio: 'ignore' });
198
+ console.log(chalk.green('\n✓ Piper TTS installed successfully!\n'));
199
+ piperInstalled = true;
200
+ } catch {
201
+ console.log(chalk.yellow('\n⚠️ Piper installed but not found in PATH'));
202
+ console.log(chalk.gray(' You may need to restart your terminal\n'));
203
+ }
204
+ } catch (error) {
205
+ console.log(chalk.red('\n✗ Piper installation failed'));
206
+ console.log(chalk.gray(' You can try installing manually later with:'));
207
+ console.log(chalk.cyan(' .claude/hooks/piper-installer.sh\n'));
208
+ }
209
+ } catch {
210
+ console.log(chalk.yellow('\n⚠️ Piper installer script not found'));
211
+ console.log(chalk.gray(' The installer will be copied during installation'));
212
+ console.log(chalk.gray(' You can install Piper later with:'));
213
+ console.log(chalk.cyan(' .claude/hooks/piper-installer.sh\n'));
214
+ }
215
+ } else {
216
+ console.log(chalk.yellow('\n⚠️ Skipping Piper installation'));
217
+ console.log(chalk.gray(' You can install it later with:'));
218
+ console.log(chalk.cyan(' .claude/hooks/piper-installer.sh'));
219
+ console.log(chalk.gray(' Or switch to ElevenLabs with:'));
220
+ console.log(chalk.cyan(' /agent-vibes:provider switch elevenlabs\n'));
221
+ }
222
+ } else {
223
+ console.log(chalk.green('\n✓ Piper TTS is already installed\n'));
224
+ }
225
+
141
226
  const homeDir = process.env.HOME || process.env.USERPROFILE;
142
227
  const defaultPiperPath = path.join(homeDir, '.claude', 'piper-voices');
143
228
 
@@ -294,6 +379,32 @@ async function install(options = {}) {
294
379
  } else {
295
380
  selectedProvider = 'piper';
296
381
  console.log(chalk.green('✓ Using Piper TTS (free option)\n'));
382
+
383
+ // Check if Piper is installed in auto mode
384
+ let piperInstalled = false;
385
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
386
+ const pipxPiperPath = path.join(homeDir, '.local', 'bin', 'piper');
387
+
388
+ try {
389
+ const { execSync } = await import('node:child_process');
390
+ execSync('which piper', { stdio: 'ignore' });
391
+ piperInstalled = true;
392
+ console.log(chalk.green('✓ Piper TTS is already installed\n'));
393
+ } catch {
394
+ // Check if it exists in pipx installation directory
395
+ try {
396
+ await fs.access(pipxPiperPath, fs.constants.X_OK);
397
+ piperInstalled = true;
398
+ console.log(chalk.yellow('⚠️ Piper is installed but not in PATH'));
399
+ console.log(chalk.gray(` Location: ${pipxPiperPath}`));
400
+ console.log(chalk.gray(' Add to PATH with:'));
401
+ console.log(chalk.cyan(' export PATH="$HOME/.local/bin:$PATH"\n'));
402
+ } catch {
403
+ console.log(chalk.yellow('⚠️ Piper TTS is not installed'));
404
+ console.log(chalk.gray(' Install it after setup with:'));
405
+ console.log(chalk.cyan(' .claude/hooks/piper-installer.sh\n'));
406
+ }
407
+ }
297
408
  }
298
409
  }
299
410
 
@@ -485,6 +596,36 @@ async function install(options = {}) {
485
596
  }
486
597
  spinner.succeed(chalk.green('Installed output styles!\n'));
487
598
 
599
+ // Copy plugins folder (BMAD voice mappings)
600
+ spinner.start('Installing BMAD plugin files...');
601
+ const srcPluginsDir = path.join(__dirname, '..', '.claude', 'plugins');
602
+ const destPluginsDir = path.join(claudeDir, 'plugins');
603
+
604
+ // Create plugins directory
605
+ await fs.mkdir(destPluginsDir, { recursive: true });
606
+
607
+ // Copy only .md files from plugins directory
608
+ let pluginFiles = [];
609
+ try {
610
+ const allPluginFiles = await fs.readdir(srcPluginsDir);
611
+ for (const file of allPluginFiles) {
612
+ const srcPath = path.join(srcPluginsDir, file);
613
+ const stat = await fs.stat(srcPath);
614
+
615
+ // Only copy .md files, skip .flag files (those are runtime generated)
616
+ if (stat.isFile() && file.endsWith('.md')) {
617
+ pluginFiles.push(file);
618
+ const destPath = path.join(destPluginsDir, file);
619
+ await fs.copyFile(srcPath, destPath);
620
+ console.log(chalk.gray(` ✓ ${file}`));
621
+ }
622
+ }
623
+ spinner.succeed(chalk.green('Installed BMAD plugin files!\n'));
624
+ } catch (error) {
625
+ // Plugins directory might not exist in source - that's okay
626
+ spinner.info(chalk.yellow('No plugin files found (optional)\n'));
627
+ }
628
+
488
629
  // Save provider selection
489
630
  spinner.start('Saving provider configuration...');
490
631
  const providerConfigPath = path.join(claudeDir, 'tts-provider.txt');
@@ -502,8 +643,11 @@ async function install(options = {}) {
502
643
  console.log(chalk.cyan('📦 Installation Summary:'));
503
644
  console.log(chalk.white(` • ${commandFiles.length} slash commands installed`));
504
645
  console.log(chalk.white(` • ${hookFiles.length} TTS scripts installed`));
505
- console.log(chalk.white(` • ${personalityFiles.length} personality templates installed`));
646
+ console.log(chalk.white(` • ${personalityMdFiles.length} personality templates installed`));
506
647
  console.log(chalk.white(` • ${outputStyleFiles.length} output styles installed`));
648
+ if (pluginFiles.length > 0) {
649
+ console.log(chalk.white(` • ${pluginFiles.length} BMAD plugin files installed`));
650
+ }
507
651
  console.log(chalk.white(` • Voice manager ready`));
508
652
 
509
653
  if (selectedProvider === 'elevenlabs') {
@@ -585,7 +729,9 @@ async function install(options = {}) {
585
729
  chalk.green.bold('✨ Installation Complete! ✨\n\n') +
586
730
  chalk.yellow.bold('⚠️ IMPORTANT SETUP STEP:\n') +
587
731
  chalk.white('In Claude Code, run this command:\n') +
588
- chalk.cyan.bold('/output-style agent-vibes') + '\n\n' +
732
+ chalk.cyan.bold('/output-style Agent Vibes') + '\n\n' +
733
+ chalk.magenta('💡 Optional: Enable BMAD plugin integration:\n') +
734
+ chalk.magenta('/agent-vibes:bmad enable') + '\n\n' +
589
735
  chalk.white('🎤 Available Commands:\n\n') +
590
736
  chalk.cyan(' /agent-vibes') + chalk.gray(' .................... Show all commands\n') +
591
737
  chalk.cyan(' /agent-vibes:list') + chalk.gray(' ............... List available voices\n') +
@@ -611,8 +757,12 @@ async function install(options = {}) {
611
757
  );
612
758
 
613
759
  console.log(chalk.yellow.bold('\n⚠️ REQUIRED SETUP:'));
614
- console.log(chalk.white(' 1. In Claude Code, run: ') + chalk.cyan.bold('/output-style agent-vibes'));
615
- console.log(chalk.gray(' This enables TTS narration for your sessions\n'));
760
+ console.log(chalk.white(' 1. In Claude Code, run: ') + chalk.cyan.bold('/output-style Agent Vibes'));
761
+ console.log(chalk.gray(' This enables TTS narration for your sessions'));
762
+ console.log(chalk.magenta('\n 💡 Optional: Enable BMAD plugin integration:'));
763
+ console.log(chalk.white(' 2. In Claude Code, run: ') + chalk.magenta.bold('/agent-vibes:bmad enable'));
764
+ console.log(chalk.gray(' This assigns unique voices to each BMAD agent'));
765
+ console.log(chalk.gray(' Get BMAD: ') + chalk.cyan('https://github.com/bmad-code-org/BMAD-METHOD\n'));
616
766
  console.log(chalk.gray('💡 Then try these commands:'));
617
767
  console.log(chalk.gray(' • /agent-vibes:list - See all available voices'));
618
768
  console.log(chalk.gray(' • /agent-vibes:switch <name> - Change your voice'));
@@ -671,7 +821,7 @@ async function install(options = {}) {
671
821
  // CLI setup
672
822
  program
673
823
  .version(VERSION)
674
- .description('AgentVibes - Beautiful ElevenLabs TTS Voice Commands for Claude Code');
824
+ .description('AgentVibes - Now your AI Agents can finally talk back! TTS Voice for Claude Code');
675
825
 
676
826
  program
677
827
  .command('install')
@@ -727,7 +877,7 @@ program
727
877
  // Welcome box
728
878
  console.log(
729
879
  boxen(
730
- chalk.white('🎤 Beautiful ElevenLabs TTS Voice Commands for Claude Code\n\n') +
880
+ chalk.white('🎤 Now your AI Agents can finally talk back! TTS Voice for Claude Code\n\n') +
731
881
  chalk.gray('Add professional text-to-speech narration to your AI coding sessions\n\n') +
732
882
  chalk.cyan('📦 https://github.com/paulpreibisch/AgentVibes'),
733
883
  {
@@ -908,13 +1058,47 @@ program
908
1058
  }
909
1059
  console.log(chalk.green(`✓ Updated ${outputStyleFiles.length} output styles`));
910
1060
 
1061
+ // Update plugins folder (BMAD voice mappings)
1062
+ spinner.text = 'Updating BMAD plugin files...';
1063
+ const srcPluginsDir = path.join(__dirname, '..', '.claude', 'plugins');
1064
+ const destPluginsDir = path.join(claudeDir, 'plugins');
1065
+
1066
+ // Create plugins directory if it doesn't exist
1067
+ await fs.mkdir(destPluginsDir, { recursive: true });
1068
+
1069
+ // Copy only .md files from plugins directory
1070
+ let pluginFiles = [];
1071
+ try {
1072
+ const allPluginFiles = await fs.readdir(srcPluginsDir);
1073
+ for (const file of allPluginFiles) {
1074
+ const srcPath = path.join(srcPluginsDir, file);
1075
+ const stat = await fs.stat(srcPath);
1076
+
1077
+ // Only copy .md files, skip .flag files (those are runtime generated)
1078
+ if (stat.isFile() && file.endsWith('.md')) {
1079
+ pluginFiles.push(file);
1080
+ const destPath = path.join(destPluginsDir, file);
1081
+ await fs.copyFile(srcPath, destPath);
1082
+ }
1083
+ }
1084
+ if (pluginFiles.length > 0) {
1085
+ console.log(chalk.green(`✓ Updated ${pluginFiles.length} BMAD plugin files`));
1086
+ }
1087
+ } catch (error) {
1088
+ // Plugins directory might not exist in source - that's okay
1089
+ }
1090
+
911
1091
  spinner.succeed(chalk.green.bold('\n✨ Update complete!\n'));
912
1092
 
913
1093
  console.log(chalk.cyan('📦 Update Summary:'));
914
1094
  console.log(chalk.white(` • ${commandFiles.length} commands updated`));
915
1095
  console.log(chalk.white(` • ${hookFiles.length} TTS scripts updated`));
916
1096
  console.log(chalk.white(` • ${newPersonalities + updatedPersonalities} personality templates (${newPersonalities} new, ${updatedPersonalities} updated)`));
917
- console.log(chalk.white(` • ${outputStyleFiles.length} output styles updated\n`));
1097
+ console.log(chalk.white(` • ${outputStyleFiles.length} output styles updated`));
1098
+ if (pluginFiles.length > 0) {
1099
+ console.log(chalk.white(` • ${pluginFiles.length} BMAD plugin files updated`));
1100
+ }
1101
+ console.log('');
918
1102
 
919
1103
  // Show latest release notes from RELEASE_NOTES_V2.md (v2.0+) or RELEASE_NOTES.md (legacy)
920
1104
  try {
@@ -118,13 +118,15 @@ setup_agentvibes_scripts() {
118
118
  # Create a test personality file
119
119
  create_test_personality() {
120
120
  local name="$1"
121
- local voice="${2:-}"
121
+ local elevenlabs_voice="${2:-}"
122
+ local piper_voice="${3:-en_US-lessac-medium}"
122
123
 
123
124
  cat > "$TEST_PERSONALITIES_DIR/${name}.md" << EOF
124
125
  ---
125
126
  name: ${name}
126
127
  description: Test personality
127
- voice: ${voice}
128
+ elevenlabs_voice: ${elevenlabs_voice}
129
+ piper_voice: ${piper_voice}
128
130
  ---
129
131
 
130
132
  # ${name} Personality
@@ -11,9 +11,9 @@ setup() {
11
11
 
12
12
  PERSONALITY_MANAGER="$TEST_CLAUDE_DIR/hooks/personality-manager.sh"
13
13
 
14
- # Create test personalities
15
- create_test_personality "sarcastic" "Jessica Anne Bogart"
16
- create_test_personality "normal"
14
+ # Create test personalities with both ElevenLabs and Piper voices
15
+ create_test_personality "sarcastic" "Jessica Anne Bogart" "en_US-amy-medium"
16
+ create_test_personality "normal" "Aria" "en_US-lessac-medium"
17
17
  }
18
18
 
19
19
  teardown() {
@@ -50,7 +50,8 @@ teardown() {
50
50
  }
51
51
 
52
52
  @test "personality-manager set with assigned voice switches voice silently" {
53
- # sarcastic personality has assigned voice "Jessica Anne Bogart"
53
+ # Set default provider (no provider file defaults to elevenlabs)
54
+ # sarcastic personality has assigned voice "Jessica Anne Bogart" (ElevenLabs)
54
55
  run "$PERSONALITY_MANAGER" set "sarcastic"
55
56
 
56
57
  [ "$status" -eq 0 ]
@@ -60,6 +61,17 @@ teardown() {
60
61
  # (that would indicate double audio bug)
61
62
  }
62
63
 
64
+ @test "personality-manager set with piper provider uses piper voice" {
65
+ # Set Piper as active provider
66
+ echo "piper" > "$HOME/.claude/tts-provider.txt"
67
+
68
+ # sarcastic personality should use en_US-amy-medium (Piper voice)
69
+ run "$PERSONALITY_MANAGER" set "sarcastic"
70
+
71
+ [ "$status" -eq 0 ]
72
+ assert_output_contains "Switching to assigned voice: en_US-amy-medium"
73
+ }
74
+
63
75
  @test "personality-manager reset changes to normal" {
64
76
  echo "sarcastic" > "$HOME/.claude/tts-personality.txt"
65
77
 
@@ -83,9 +83,13 @@ declare -A EXPECTED_VOICES=(
83
83
  for personality_file in "$REPO_ROOT/.claude/personalities"/*.md; do
84
84
  personality_name=$(basename "$personality_file" .md)
85
85
 
86
- # Check if file has voice field
87
- if ! grep -q "^voice:" "$personality_file"; then
88
- errors="${errors}Personality '${personality_name}' missing voice field\n"
86
+ # Check if file has both elevenlabs_voice and piper_voice fields
87
+ if ! grep -q "^elevenlabs_voice:" "$personality_file"; then
88
+ errors="${errors}Personality '${personality_name}' missing elevenlabs_voice field\n"
89
+ failed=1
90
+ fi
91
+ if ! grep -q "^piper_voice:" "$personality_file"; then
92
+ errors="${errors}Personality '${personality_name}' missing piper_voice field\n"
89
93
  failed=1
90
94
  fi
91
95
  done
@@ -103,11 +107,16 @@ declare -A EXPECTED_VOICES=(
103
107
 
104
108
  for personality_file in "$REPO_ROOT/.claude/personalities"/*.md; do
105
109
  personality_name=$(basename "$personality_file" .md)
106
- assigned_voice=$(grep "^voice:" "$personality_file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
110
+ assigned_voice=$(grep "^elevenlabs_voice:" "$personality_file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
111
+
112
+ # Skip if no elevenlabs_voice assigned
113
+ if [[ -z "$assigned_voice" ]]; then
114
+ continue
115
+ fi
107
116
 
108
- # Check if voice exists in config
117
+ # Check if ElevenLabs voice exists in config
109
118
  if [[ -z "${VOICES[$assigned_voice]}" ]]; then
110
- errors="${errors}Personality '${personality_name}' uses undefined voice: ${assigned_voice}\n"
119
+ errors="${errors}Personality '${personality_name}' uses undefined ElevenLabs voice: ${assigned_voice}\n"
111
120
  failed=1
112
121
  fi
113
122
  done
@@ -66,15 +66,6 @@ teardown() {
66
66
  assert_output_contains "Text truncated to 500 characters"
67
67
  }
68
68
 
69
- @test "play-tts fails without API key" {
70
- unset ELEVENLABS_API_KEY
71
-
72
- run "$PLAY_TTS" "Test message"
73
-
74
- [ "$status" -eq 1 ]
75
- assert_output_contains "ELEVENLABS_API_KEY not set"
76
- }
77
-
78
69
  @test "play-tts fails without text argument" {
79
70
  run "$PLAY_TTS"
80
71
 
@@ -1,132 +0,0 @@
1
- # /agent-vibes:bmad Command
2
-
3
- Manage BMAD voice plugin integration for automatic voice assignment to BMAD agents.
4
-
5
- ## Usage
6
-
7
- ```
8
- /agent-vibes:bmad <subcommand> [arguments]
9
- ```
10
-
11
- ## Subcommands
12
-
13
- ### `enable`
14
- Enables automatic voice assignment for BMAD agents.
15
-
16
- **Example:**
17
- ```
18
- /agent-vibes:bmad enable
19
- ```
20
-
21
- **Output:**
22
- - Creates `.claude/plugins/bmad-voices-enabled.flag`
23
- - Shows current agent voice mappings
24
- - Confirms activation
25
-
26
- ### `disable`
27
- Disables BMAD voice plugin (reverts to default AgentVibes behavior).
28
-
29
- **Example:**
30
- ```
31
- /agent-vibes:bmad disable
32
- ```
33
-
34
- **Output:**
35
- - Removes activation flag
36
- - AgentVibes uses default voice settings
37
-
38
- ### `status`
39
- Shows plugin status and current voice mappings.
40
-
41
- **Example:**
42
- ```
43
- /agent-vibes:bmad status
44
- ```
45
-
46
- **Output:**
47
- ```
48
- ✅ BMAD voice plugin: ENABLED
49
-
50
- 📊 BMAD Agent Voice Mappings:
51
- pm → Matthew Schmitz [professional]
52
- dev → Jessica Anne Bogart [normal]
53
- qa → Ralf Eisend [professional]
54
- ...
55
- ```
56
-
57
- ### `list`
58
- Lists all BMAD agents and their assigned voices.
59
-
60
- **Example:**
61
- ```
62
- /agent-vibes:bmad list
63
- ```
64
-
65
- ### `set <agent-id> <voice> [personality]`
66
- Quickly change voice for specific agent.
67
-
68
- **Examples:**
69
- ```
70
- /agent-vibes:bmad set pm "Aria"
71
- /agent-vibes:bmad set dev "Cowboy Bob" sarcastic
72
- /agent-vibes:bmad set qa "Northern Terry" professional
73
- ```
74
-
75
- **Arguments:**
76
- - `agent-id`: BMAD agent identifier (pm, dev, qa, architect, po, analyst, sm, ux-expert, bmad-master, bmad-orchestrator)
77
- - `voice`: Valid AgentVibes voice name
78
- - `personality` (optional): Personality to apply (default: normal)
79
-
80
- ### `edit`
81
- Opens `.claude/plugins/bmad-voices.md` for manual editing.
82
-
83
- **Example:**
84
- ```
85
- /agent-vibes:bmad edit
86
- ```
87
-
88
- **Usage:**
89
- Edit the markdown table directly to change voice mappings.
90
-
91
- ## How It Works
92
-
93
- 1. **Plugin File**: `.claude/plugins/bmad-voices.md` contains voice mappings
94
- 2. **Activation Flag**: `.claude/plugins/bmad-voices-enabled.flag` enables/disables plugin
95
- 3. **Auto-Detection**: When a BMAD agent activates (e.g., `/BMad:agents:pm`), AgentVibes automatically:
96
- - Detects the agent ID from the command
97
- - Looks up voice mapping in plugin file
98
- - Uses assigned voice for TTS acknowledgments/completions
99
-
100
- ## Available BMAD Agents
101
-
102
- | Agent ID | Role | Default Voice |
103
- |----------|------|---------------|
104
- | pm | Product Manager | Matthew Schmitz |
105
- | dev | Developer | Jessica Anne Bogart |
106
- | qa | QA Engineer | Ralf Eisend |
107
- | architect | Architect | Michael |
108
- | po | Product Owner | Amy |
109
- | analyst | Analyst | Lutz Laugh |
110
- | sm | Scrum Master | Ms. Walker |
111
- | ux-expert | UX Expert | Aria |
112
- | bmad-master | BMAD Master | Aria |
113
- | bmad-orchestrator | Orchestrator | Ms. Walker |
114
-
115
- ## Implementation Details
116
-
117
- **For AgentVibes Developers:**
118
-
119
- The plugin integrates with the Agent Vibes output style through bash hooks:
120
-
121
- ```bash
122
- # Check if BMAD agent is active
123
- BMAD_AGENT_ID=$(echo "$COMMAND" | grep -oP '/BMad:agents:\K[a-z-]+')
124
-
125
- # Get voice from plugin if enabled
126
- if [[ -n "$BMAD_AGENT_ID" ]]; then
127
- MAPPED_VOICE=$(.claude/hooks/bmad-voice-manager.sh get-voice "$BMAD_AGENT_ID")
128
- if [[ -n "$MAPPED_VOICE" ]]; then
129
- .claude/hooks/play-tts.sh "message" "$MAPPED_VOICE"
130
- fi
131
- fi
132
- ```