agentvibes 5.2.0 → 5.2.1

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 (49) hide show
  1. package/.claude/config/audio-effects.cfg +1 -1
  2. package/.claude/hooks/audio-cache-utils.sh +246 -246
  3. package/.claude/hooks/background-music-manager.sh +404 -404
  4. package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
  5. package/.claude/hooks/bmad-speak.sh +290 -290
  6. package/.claude/hooks/bmad-tts-injector.sh +568 -568
  7. package/.claude/hooks/bmad-voice-manager.sh +928 -928
  8. package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
  9. package/.claude/hooks/clawdbot-receiver.sh +107 -107
  10. package/.claude/hooks/clean-audio-cache.sh +22 -22
  11. package/.claude/hooks/cleanup-cache.sh +106 -106
  12. package/.claude/hooks/configure-rdp-mode.sh +137 -137
  13. package/.claude/hooks/download-extra-voices.sh +244 -244
  14. package/.claude/hooks/effects-manager.sh +268 -268
  15. package/.claude/hooks/github-star-reminder.sh +154 -154
  16. package/.claude/hooks/language-manager.sh +362 -362
  17. package/.claude/hooks/learn-manager.sh +492 -492
  18. package/.claude/hooks/macos-voice-manager.sh +205 -205
  19. package/.claude/hooks/migrate-background-music.sh +125 -125
  20. package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
  21. package/.claude/hooks/optimize-background-music.sh +87 -87
  22. package/.claude/hooks/path-resolver.sh +60 -60
  23. package/.claude/hooks/personality-manager.sh +448 -448
  24. package/.claude/hooks/piper-installer.sh +292 -292
  25. package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
  26. package/.claude/hooks/play-tts-enhanced.sh +105 -105
  27. package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
  28. package/.claude/hooks/play-tts.sh +14 -5
  29. package/.claude/hooks/prepare-release.sh +54 -54
  30. package/.claude/hooks/provider-commands.sh +617 -617
  31. package/.claude/hooks/provider-manager.sh +399 -399
  32. package/.claude/hooks/replay-target-audio.sh +95 -95
  33. package/.claude/hooks/sentiment-manager.sh +201 -201
  34. package/.claude/hooks/speed-manager.sh +291 -291
  35. package/.claude/hooks/stop-tts.sh +84 -84
  36. package/.claude/hooks/termux-installer.sh +261 -261
  37. package/.claude/hooks/translate-manager.sh +341 -341
  38. package/.claude/hooks/tts-queue-worker.sh +145 -145
  39. package/.claude/hooks/tts-queue.sh +165 -165
  40. package/.claude/hooks/voice-manager.sh +552 -548
  41. package/.claude/hooks-windows/play-tts.ps1 +2 -2
  42. package/README.md +11 -2
  43. package/RELEASE_NOTES.md +38 -0
  44. package/bin/mcp-server.sh +206 -206
  45. package/mcp-server/server.py +35 -6
  46. package/package.json +1 -1
  47. package/src/console/tabs/setup-tab.js +59 -23
  48. package/src/installer.js +79 -213
  49. package/src/services/llm-provider-service.js +126 -75
@@ -605,12 +605,19 @@ export function createSetupTab(screen, services) {
605
605
  }
606
606
  });
607
607
  btn.key(['down'], () => {
608
+ // Column-preserving down nav. If pressing down from Install/Remove
609
+ // would land on the Default row (which has no Install/Remove — all
610
+ // three slots are configBtn duplicates), don't move. Configure
611
+ // column navigates normally into Default row's Configure.
612
+ const col = providerFocusIndex % 3;
608
613
  const nextIdx = providerFocusIndex + 3;
609
- if (nextIdx < providerFocusableItems.length) {
610
- providerFocusIndex = nextIdx;
611
- providerFocusableItems[providerFocusIndex].focus();
612
- screen.render();
613
- }
614
+ if (nextIdx >= providerFocusableItems.length) return;
615
+ const nextRowIdx = Math.floor(nextIdx / 3);
616
+ const nextRow = PROVIDERS[nextRowIdx];
617
+ if (col < 2 && nextRow && nextRow.isDefault) return; // skip Default from Install/Remove
618
+ providerFocusIndex = nextIdx;
619
+ providerFocusableItems[providerFocusIndex].focus();
620
+ screen.render();
614
621
  });
615
622
  }
616
623
 
@@ -1522,7 +1529,6 @@ export function createSetupTab(screen, services) {
1522
1529
  hideAllProviderRows();
1523
1530
  contentBox.hide();
1524
1531
 
1525
- const mcpPath = path.join(targetDir, '.mcp.json');
1526
1532
  const hooksDir = path.join(targetDir, '.claude', process.platform === 'win32' ? 'hooks-windows' : 'hooks');
1527
1533
  const installed = installedState['claude-code'];
1528
1534
  const verb = wasInstalled ? 'reinstalled' : 'installed';
@@ -1532,9 +1538,14 @@ export function createSetupTab(screen, services) {
1532
1538
  lines.push('');
1533
1539
 
1534
1540
  if (result) {
1535
- lines.push(result.success
1536
- ? `{green-fg}AgentVibes for Claude Code ${verb}!{/green-fg}`
1537
- : `{red-fg}Installation failed{/red-fg}`);
1541
+ if (result.success) {
1542
+ lines.push(`{green-fg}AgentVibes for Claude Code ${verb}!{/green-fg}`);
1543
+ if (result.mcpError) {
1544
+ lines.push(`{yellow-fg}Warning:{/yellow-fg} ${result.mcpError}`);
1545
+ }
1546
+ } else {
1547
+ lines.push(`{red-fg}Installation failed:{/red-fg} ${result.error || 'Unknown error'}`);
1548
+ }
1538
1549
  } else {
1539
1550
  lines.push(installed
1540
1551
  ? '{green-fg}Installed{/green-fg}'
@@ -1543,10 +1554,7 @@ export function createSetupTab(screen, services) {
1543
1554
 
1544
1555
  lines.push('');
1545
1556
  lines.push(`{bold}{cyan-fg}What ${result ? `got ${verb}` : 'gets installed'}:{/cyan-fg}{/bold}`);
1546
- lines.push('');
1547
- lines.push(' {yellow-fg}1.{/yellow-fg} {bold}.mcp.json{/bold} (project root)');
1548
- lines.push(` Location: ${mcpPath}`);
1549
- lines.push(' Registers the AgentVibes MCP server for Claude Code.');
1557
+ lines.push(' {yellow-fg}1.{/yellow-fg} {bold}.mcp.json{/bold} (MCP server — natural language voice control)');
1550
1558
  lines.push('');
1551
1559
  lines.push(' {yellow-fg}2.{/yellow-fg} {bold}.claude/hooks/{/bold} (session-start + pre-tool hooks)');
1552
1560
  lines.push(` Location: ${hooksDir}`);
@@ -1575,9 +1583,14 @@ export function createSetupTab(screen, services) {
1575
1583
  const lines = [];
1576
1584
  lines.push('{bold}{cyan-fg}GitHub Copilot -- AgentVibes Integration{/cyan-fg}{/bold}');
1577
1585
  lines.push('');
1578
- lines.push(result.success
1579
- ? `{green-fg}AgentVibes for Copilot ${verb}!{/green-fg}`
1580
- : `{red-fg}Installation failed:{/red-fg} ${result.error || 'Unknown error'}`);
1586
+ if (result.success) {
1587
+ lines.push(`{green-fg}AgentVibes for Copilot ${verb}!{/green-fg}`);
1588
+ if (result.mcpError) {
1589
+ lines.push(`{yellow-fg}MCP config failed:{/yellow-fg} ${result.mcpError}`);
1590
+ }
1591
+ } else {
1592
+ lines.push(`{red-fg}Installation failed:{/red-fg} ${result.error || 'Unknown error'}`);
1593
+ }
1581
1594
  lines.push('');
1582
1595
  lines.push(`{bold}{cyan-fg}What got ${verb}:{/cyan-fg}{/bold}`);
1583
1596
  lines.push('');
@@ -1604,9 +1617,14 @@ export function createSetupTab(screen, services) {
1604
1617
  const lines = [];
1605
1618
  lines.push('{bold}{cyan-fg}OpenAI Codex -- AgentVibes Integration{/cyan-fg}{/bold}');
1606
1619
  lines.push('');
1607
- lines.push(result.success
1608
- ? `{green-fg}AgentVibes for Codex ${verb}!{/green-fg}`
1609
- : `{red-fg}Installation failed:{/red-fg} ${result.error || 'Unknown error'}`);
1620
+ if (result.success) {
1621
+ lines.push(`{green-fg}AgentVibes for Codex ${verb}!{/green-fg}`);
1622
+ if (result.mcpError) {
1623
+ lines.push(`{yellow-fg}MCP config failed:{/yellow-fg} ${result.mcpError}`);
1624
+ }
1625
+ } else {
1626
+ lines.push(`{red-fg}Installation failed:{/red-fg} ${result.error || 'Unknown error'}`);
1627
+ }
1610
1628
  lines.push('');
1611
1629
  lines.push(`{bold}{cyan-fg}What got ${verb}:{/cyan-fg}{/bold}`);
1612
1630
  lines.push('');
@@ -1679,11 +1697,29 @@ export function createSetupTab(screen, services) {
1679
1697
 
1680
1698
  infoBox.key(['escape', 'enter'], () => {
1681
1699
  // After dismissing the install/remove info page, advance focus to the
1682
- // NEXT provider row but keep the same column (Install stays on Install,
1683
- // Remove stays on Remove, Configure stays on Configure). Each row has
1684
- // 3 focusable slots so +3 moves one full row down with wraparound.
1700
+ // NEXT provider row but keep the same column (Install/Remove/Configure).
1701
+ // Each row has 3 focusable slots, so +3 moves one full row down.
1702
+ //
1703
+ // Special case: when leaving the LAST installable provider (Codex) from
1704
+ // Install or Remove column, skip the Default row (it has no Install or
1705
+ // Remove) and wrap to the FIRST Configure button (Claude Code Configure).
1706
+ // This lets the user cleanly walk all three installs, then all three
1707
+ // Configures, ending on Default Configure.
1685
1708
  const max = providerFocusableItems.length;
1686
- const nextIdx = max > 0 ? (_preInfoFocusIndex + 3) % max : 0;
1709
+ if (max === 0) { showProviderListView(0); return; }
1710
+ const col = _preInfoFocusIndex % 3; // 0=Install, 1=Remove, 2=Configure
1711
+ const row = Math.floor(_preInfoFocusIndex / 3);
1712
+ const nextRow = PROVIDERS[row + 1];
1713
+ const nextRowIsDefault = nextRow && nextRow.isDefault;
1714
+ let nextIdx;
1715
+ if (col < 2 && nextRowIsDefault) {
1716
+ // Last Install/Remove → jump to the FIRST non-default provider's
1717
+ // Configure column (dynamic: don't hardcode PROVIDERS[0]).
1718
+ const firstInstallableIdx = PROVIDERS.findIndex(p => !p.isDefault);
1719
+ nextIdx = firstInstallableIdx >= 0 ? firstInstallableIdx * 3 + 2 : (_preInfoFocusIndex + 3) % max;
1720
+ } else {
1721
+ nextIdx = (_preInfoFocusIndex + 3) % max;
1722
+ }
1687
1723
  showProviderListView(nextIdx);
1688
1724
  });
1689
1725
 
package/src/installer.js CHANGED
@@ -3771,18 +3771,31 @@ async function copyConfigFiles(targetDir, spinner) {
3771
3771
  const stat = await fs.stat(srcPath);
3772
3772
 
3773
3773
  if (stat.isFile()) {
3774
- // Don't overwrite existing config files (except audio-effects.cfg which is required)
3775
- try {
3776
- await fs.access(destPath);
3777
- if (file !== 'audio-effects.cfg') {
3778
- continue; // Skip if file exists and it's not audio-effects.cfg
3774
+ // For .sample files: copy as the real config name if it doesn't exist yet
3775
+ // e.g. audio-effects.cfg.sample → audio-effects.cfg (only if absent)
3776
+ let finalDest = destPath;
3777
+ let finalName = file;
3778
+ if (file.endsWith('.sample')) {
3779
+ finalName = file.replace(/\.sample$/, '');
3780
+ finalDest = path.join(destConfigDir, finalName);
3781
+ try {
3782
+ await fs.access(finalDest);
3783
+ continue; // Real config already exists, don't overwrite
3784
+ } catch {
3785
+ // Real config doesn't exist, install from sample
3786
+ }
3787
+ } else {
3788
+ // Non-sample files: skip if already exists
3789
+ try {
3790
+ await fs.access(destPath);
3791
+ continue;
3792
+ } catch {
3793
+ // File doesn't exist, proceed with copy
3779
3794
  }
3780
- } catch {
3781
- // File doesn't exist, proceed with copy
3782
3795
  }
3783
3796
 
3784
- await fs.copyFile(srcPath, destPath);
3785
- copiedFiles.push(file);
3797
+ await fs.copyFile(srcPath, finalDest);
3798
+ copiedFiles.push(finalName);
3786
3799
  }
3787
3800
  }
3788
3801
 
@@ -4297,239 +4310,92 @@ function isPathSafe(targetPath, basePath) {
4297
4310
  async function handleMcpConfiguration(targetDir, options) {
4298
4311
  const mcpConfigPath = path.join(targetDir, '.mcp.json');
4299
4312
 
4300
- // MCP server configuration for AgentVibes.
4313
+ // .mcp.json registers the AgentVibes MCP server for Claude Code, enabling
4314
+ // natural language control (text_to_speech, get_config, set_voice, etc.).
4301
4315
  //
4302
- // No `env.AGENTVIBES_LLM` block: GitHub Copilot CLI also reads project
4303
- // `.mcp.json` with precedence over its own `~/.copilot/mcp-config.json`,
4304
- // so setting `claude-code` here would mis-route Copilot CLI too.
4305
- // Instead, the MCP server auto-detects Claude Code via the `CLAUDECODE=1`
4306
- // env var that Claude Code sets on every subprocess it spawns.
4316
+ // AGENTVIBES_MCP_FALLBACK=copilot is the identity for non-Claude-Code tools
4317
+ // that read .mcp.json (primarily VS Code Copilot, which reads .mcp.json
4318
+ // with precedence over its own .vscode/mcp.json). Claude Code is
4319
+ // auto-detected via CLAUDECODE=1 which takes priority over the fallback.
4307
4320
  const mcpConfig = {
4308
4321
  mcpServers: {
4309
4322
  agentvibes: {
4310
4323
  command: 'npx',
4311
- args: ['-y', '--package=agentvibes', 'agentvibes-mcp-server']
4324
+ args: ['-y', '--package=agentvibes', 'agentvibes-mcp-server'],
4325
+ env: { AGENTVIBES_MCP_FALLBACK: 'copilot' }
4312
4326
  }
4313
4327
  }
4314
4328
  };
4315
4329
 
4316
- // Check if .mcp.json already exists
4317
4330
  let mcpExists = false;
4318
4331
  try {
4319
4332
  await fs.access(mcpConfigPath);
4320
4333
  mcpExists = true;
4321
- } catch {
4322
- // File doesn't exist
4323
- }
4334
+ } catch { /* doesn't exist */ }
4324
4335
 
4325
4336
  if (mcpExists) {
4326
- // Existing config: upgrade it in-place. Two jobs:
4327
- // 1. Ensure the agentvibes server entry exists.
4328
- // 2. STRIP any stale `env.AGENTVIBES_LLM` from earlier versions
4329
- // (v5.1.2..v5.1.4) — setting it in `.mcp.json` broke Copilot CLI
4330
- // routing because Copilot CLI also reads `.mcp.json` and would
4331
- // adopt claude-code's env. Claude Code is now auto-detected
4332
- // downstream via the CLAUDECODE=1 env var.
4333
- let migrated = false;
4334
- let migrationError = null;
4337
+ // Upgrade: ensure agentvibes entry exists with fallback env
4338
+ let parseFailed = false;
4335
4339
  try {
4336
- const existingRaw = await fs.readFile(mcpConfigPath, 'utf8');
4337
- const existingCfg = JSON.parse(existingRaw);
4338
- if (existingCfg && typeof existingCfg === 'object') {
4339
- if (!existingCfg.mcpServers || typeof existingCfg.mcpServers !== 'object') {
4340
- existingCfg.mcpServers = {};
4341
- }
4342
- const current = existingCfg.mcpServers.agentvibes;
4343
- const hasStaleEnv = current?.env?.AGENTVIBES_LLM !== undefined;
4344
- const needsWrite = !current || hasStaleEnv;
4345
- if (needsWrite) {
4346
- // Preserve any OTHER env keys the user added manually (rare) but
4347
- // drop AGENTVIBES_LLM so Copilot CLI doesn't mis-route.
4348
- const cleanEnv = { ...(current?.env ?? {}) };
4349
- delete cleanEnv.AGENTVIBES_LLM;
4350
- const newEntry = {
4351
- command: 'npx',
4352
- args: ['-y', '--package=agentvibes', 'agentvibes-mcp-server'],
4353
- };
4354
- if (Object.keys(cleanEnv).length > 0) {
4355
- newEntry.env = cleanEnv;
4356
- }
4357
- existingCfg.mcpServers.agentvibes = newEntry;
4358
- await fs.writeFile(mcpConfigPath, JSON.stringify(existingCfg, null, 2) + '\n');
4359
- migrated = true;
4360
- }
4340
+ const existing = JSON.parse(await fs.readFile(mcpConfigPath, 'utf8'));
4341
+ // Guard: non-object root (arrays/primitives are valid JSON but wrong shape)
4342
+ if (!existing || typeof existing !== 'object' || Array.isArray(existing)) {
4343
+ console.log(chalk.yellow(
4344
+ `āš ļø ${mcpConfigPath} has a non-object root — skipping MCP registration. Fix the file manually and re-run.`
4345
+ ));
4346
+ return;
4347
+ }
4348
+ // Guard: mcpServers must be a plain object
4349
+ if (!existing.mcpServers || typeof existing.mcpServers !== 'object' || Array.isArray(existing.mcpServers)) {
4350
+ existing.mcpServers = {};
4361
4351
  }
4352
+ const current = existing.mcpServers.agentvibes;
4353
+ // Strip AGENTVIBES_LLM if present (causes identity collisions)
4354
+ if (current?.env?.AGENTVIBES_LLM) {
4355
+ delete current.env.AGENTVIBES_LLM;
4356
+ }
4357
+ // Ensure fallback is set
4358
+ const mergedEnv = { ...(current?.env ?? {}), AGENTVIBES_MCP_FALLBACK: 'copilot' };
4359
+ existing.mcpServers.agentvibes = {
4360
+ command: 'npx',
4361
+ args: ['-y', '--package=agentvibes', 'agentvibes-mcp-server'],
4362
+ env: mergedEnv,
4363
+ };
4364
+ await fs.writeFile(mcpConfigPath, JSON.stringify(existing, null, 2) + '\n');
4362
4365
  } catch (err) {
4363
- migrationError = err;
4364
- }
4365
-
4366
- if (migrated) {
4367
- console.log(
4368
- boxen(
4369
- chalk.green.bold('āœ… MCP Configuration Updated\n\n') +
4370
- chalk.white('Your existing ') + chalk.cyan('.mcp.json') + chalk.white(' has been updated.\n') +
4371
- chalk.white('Claude Code is auto-detected via ') + chalk.cyan('CLAUDECODE=1') + chalk.white(' at runtime.'),
4372
- {
4373
- padding: 1,
4374
- margin: { top: 1, bottom: 1, left: 0, right: 0 },
4375
- borderStyle: 'double',
4376
- borderColor: 'green',
4377
- }
4378
- )
4379
- );
4380
- return;
4366
+ parseFailed = true;
4367
+ console.log(chalk.yellow(
4368
+ `āš ļø Could not update ${mcpConfigPath}: ${err.message}\n` +
4369
+ ` AgentVibes MCP server was NOT registered. Fix the file manually and re-run.`
4370
+ ));
4381
4371
  }
4382
-
4383
- // Migration was not needed (already correct) or failed — fall through
4384
- // to the manual-instructions box.
4385
- console.log(
4386
- boxen(
4387
- chalk.yellow.bold('ā„¹ļø MCP Configuration Already Exists\n\n') +
4388
- chalk.white('An ') + chalk.cyan('.mcp.json') + chalk.white(' file already exists in this project.\n\n') +
4389
- (migrationError
4390
- ? chalk.red('Could not auto-update it: ' + migrationError.message + '\n\n')
4391
- : chalk.gray('It already has the correct AgentVibes entry.\n\n')) +
4392
- chalk.white('To add or fix the AgentVibes MCP server manually, use:'),
4393
- {
4394
- padding: 1,
4395
- margin: { top: 1, bottom: 1, left: 0, right: 0 },
4396
- borderStyle: 'round',
4397
- borderColor: migrationError ? 'red' : 'yellow',
4398
- }
4399
- )
4400
- );
4401
-
4402
- // Display the snippet to add
4403
- console.log(
4404
- '\n"agentvibes": {\n' +
4405
- ' "command": "npx",\n' +
4406
- ' "args": ["-y", "--package=agentvibes", "agentvibes-mcp-server"]\n' +
4407
- '}\n'
4408
- );
4409
-
4410
- console.log(
4411
- boxen(
4412
- chalk.cyan('To use with Claude Code:\n') +
4413
- chalk.white(' claude --mcp-config .mcp.json\n\n') +
4414
- chalk.cyan('šŸ“– Full Guide:\n') +
4415
- chalk.cyan.bold('https://github.com/paulpreibisch/AgentVibes#mcp-server'),
4416
- {
4417
- padding: 1,
4418
- margin: { top: 1, bottom: 1, left: 0, right: 0 },
4419
- borderStyle: 'round',
4420
- borderColor: 'cyan',
4421
- }
4422
- )
4423
- );
4372
+ if (!parseFailed) return;
4424
4373
  return;
4425
4374
  }
4426
4375
 
4427
- // Scenario 1 & 2: Config doesn't exist - offer to create
4428
- console.log(
4429
- boxen(
4430
- chalk.cyan.bold('šŸŽ™ļø MCP Server Configuration\n\n') +
4431
- chalk.white.bold('AgentVibes MCP Server - Control TTS with Natural Language!\n\n') +
4432
- chalk.gray('Use natural language instead of slash commands:\n') +
4433
- chalk.gray(' "Switch to Aria voice" instead of /agent-vibes:switch "Aria"\n') +
4434
- chalk.gray(' "Set personality to sarcastic" instead of /agent-vibes:personality sarcastic\n\n') +
4435
- chalk.white('No ') + chalk.cyan('.mcp.json') + chalk.white(' found in this project.'),
4436
- {
4437
- padding: 1,
4438
- margin: { top: 1, bottom: 1, left: 0, right: 0 },
4439
- borderStyle: 'round',
4440
- borderColor: 'cyan',
4441
- }
4442
- )
4443
- );
4444
-
4445
- let createConfig = options.yes; // Auto-create if --yes flag
4446
-
4376
+ // New install — create .mcp.json
4447
4377
  if (!options.yes) {
4448
- const { confirmCreate } = await inquirer.prompt([
4449
- {
4450
- type: 'confirm',
4451
- name: 'confirmCreate',
4452
- message: chalk.cyan('Would you like to create .mcp.json for this project?'),
4453
- default: true,
4454
- },
4455
- ]);
4456
- createConfig = confirmCreate;
4457
- }
4458
-
4459
- if (createConfig) {
4460
- // Scenario 1: User says YES - create the config
4461
- try {
4462
- await fs.writeFile(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + '\n');
4463
-
4464
- console.log(
4465
- boxen(
4466
- chalk.green.bold('āœ… MCP Configuration Created!\n\n') +
4467
- chalk.white('Your ') + chalk.cyan('.mcp.json') + chalk.white(' has been created in this project.\n\n') +
4468
- chalk.white('To use AgentVibes MCP server with Claude, run:\n') +
4469
- chalk.cyan.bold(' claude --mcp-config .mcp.json\n\n') +
4470
- chalk.green('The MCP server is now installed and ready to use!'),
4471
- {
4472
- padding: 1,
4473
- margin: { top: 1, bottom: 1, left: 0, right: 0 },
4474
- borderStyle: 'double',
4475
- borderColor: 'green',
4476
- }
4477
- )
4478
- );
4479
-
4480
- // Show the installed JSON so users can see exactly what was written
4481
- console.log(chalk.gray(JSON.stringify(mcpConfig, null, 2)) + '\n');
4482
- } catch (error) {
4483
- console.log(chalk.red(`\nāœ— Failed to create .mcp.json: ${error.message}`));
4484
- console.log(chalk.gray(' You can create it manually with the config shown below.\n'));
4485
- // Fall through to show manual instructions
4486
- createConfig = false;
4487
- }
4378
+ const { confirmCreate } = await inquirer.prompt([{
4379
+ type: 'confirm',
4380
+ name: 'confirmCreate',
4381
+ message: chalk.cyan('Create .mcp.json for AgentVibes MCP server? (enables natural language voice control)'),
4382
+ default: true,
4383
+ }]);
4384
+ if (!confirmCreate) return;
4488
4385
  }
4489
4386
 
4490
- if (!createConfig) {
4491
- // Scenario 2: User says NO - show manual instructions
4492
- console.log(
4493
- boxen(
4494
- chalk.cyan.bold('šŸ“‹ Manual MCP Configuration\n\n') +
4495
- chalk.white('Create a ') + chalk.cyan('.mcp.json') + chalk.white(' file in your project with:'),
4496
- {
4497
- padding: 1,
4498
- margin: { top: 1, bottom: 1, left: 0, right: 0 },
4499
- borderStyle: 'round',
4500
- borderColor: 'cyan',
4501
- }
4502
- )
4503
- );
4504
-
4505
- // Display JSON config
4506
- console.log(
4507
- '\n{\n' +
4508
- ' "mcpServers": {\n' +
4509
- ' "agentvibes": {\n' +
4510
- ' "command": "npx",\n' +
4511
- ' "args": ["-y", "--package=agentvibes", "agentvibes-mcp-server"]\n' +
4512
- ' }\n' +
4513
- ' }\n' +
4514
- '}\n'
4515
- );
4516
-
4387
+ try {
4388
+ await fs.writeFile(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + '\n');
4517
4389
  console.log(
4518
4390
  boxen(
4519
- chalk.cyan('To use with Claude Code:\n') +
4520
- chalk.white(' claude --mcp-config .mcp.json\n\n') +
4521
- chalk.cyan('šŸ“± Claude Desktop / Warp Terminal:\n') +
4522
- chalk.white(' npx agentvibes setup-mcp-for-claude-desktop\n\n') +
4523
- chalk.cyan('šŸ“– Full Guide:\n') +
4524
- chalk.cyan.bold('https://github.com/paulpreibisch/AgentVibes#mcp-server'),
4525
- {
4526
- padding: 1,
4527
- margin: { top: 1, bottom: 1, left: 0, right: 0 },
4528
- borderStyle: 'round',
4529
- borderColor: 'cyan',
4530
- }
4391
+ chalk.green.bold('āœ… MCP Configuration Created!\n\n') +
4392
+ chalk.white('AgentVibes MCP server registered in ') + chalk.cyan('.mcp.json') + chalk.white('.\n') +
4393
+ chalk.green('Natural language voice control is ready!'),
4394
+ { padding: 1, margin: { top: 1, bottom: 1 }, borderStyle: 'double', borderColor: 'green' }
4531
4395
  )
4532
4396
  );
4397
+ } catch (err) {
4398
+ console.log(chalk.red(`\nāœ— Failed to create .mcp.json: ${err.message}`));
4533
4399
  }
4534
4400
  }
4535
4401