agentvibes 5.9.0 → 5.10.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 (145) hide show
  1. package/.agentvibes/config.json +3 -12
  2. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  3. package/.claude/commands/agent-vibes-rdp.md +24 -24
  4. package/.claude/config/audio-effects.cfg +4 -5
  5. package/.claude/config/audio-effects.cfg.sample +52 -52
  6. package/.claude/config/background-music-enabled.txt +1 -1
  7. package/.claude/docs/TERMUX_SETUP.md +408 -408
  8. package/.claude/github-star-reminder.txt +1 -1
  9. package/.claude/hooks/audio-cache-utils.sh +0 -0
  10. package/.claude/hooks/audio-processor.sh +0 -0
  11. package/.claude/hooks/background-music-manager.sh +0 -0
  12. package/.claude/hooks/bmad-party-speak.sh +0 -0
  13. package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
  14. package/.claude/hooks/bmad-speak.sh +0 -0
  15. package/.claude/hooks/bmad-tts-injector.sh +0 -0
  16. package/.claude/hooks/bmad-voice-manager.sh +0 -0
  17. package/.claude/hooks/clawdbot-receiver-SECURE.sh +0 -0
  18. package/.claude/hooks/clawdbot-receiver.sh +0 -0
  19. package/.claude/hooks/clean-audio-cache.sh +0 -0
  20. package/.claude/hooks/cleanup-cache.sh +0 -0
  21. package/.claude/hooks/configure-rdp-mode.sh +0 -0
  22. package/.claude/hooks/download-extra-voices.sh +0 -0
  23. package/.claude/hooks/effects-manager.sh +0 -0
  24. package/.claude/hooks/github-star-reminder.sh +0 -0
  25. package/.claude/hooks/language-manager.sh +0 -0
  26. package/.claude/hooks/learn-manager.sh +0 -0
  27. package/.claude/hooks/macos-voice-manager.sh +0 -0
  28. package/.claude/hooks/migrate-background-music.sh +0 -0
  29. package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
  30. package/.claude/hooks/optimize-background-music.sh +0 -0
  31. package/.claude/hooks/path-resolver.sh +0 -0
  32. package/.claude/hooks/personality-manager.sh +0 -0
  33. package/.claude/hooks/piper-download-voices.sh +0 -0
  34. package/.claude/hooks/piper-installer.sh +0 -0
  35. package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
  36. package/.claude/hooks/piper-voice-manager.sh +0 -0
  37. package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +0 -0
  38. package/.claude/hooks/play-tts-enhanced.sh +0 -0
  39. package/.claude/hooks/play-tts-macos.sh +0 -0
  40. package/.claude/hooks/play-tts-piper.sh +20 -13
  41. package/.claude/hooks/play-tts-soprano.sh +0 -0
  42. package/.claude/hooks/play-tts-ssh-remote.sh +0 -0
  43. package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
  44. package/.claude/hooks/play-tts-windows-receiver.sh +0 -0
  45. package/.claude/hooks/play-tts.sh +0 -0
  46. package/.claude/hooks/prepare-release.sh +0 -0
  47. package/.claude/hooks/provider-commands.sh +0 -0
  48. package/.claude/hooks/provider-manager.sh +0 -0
  49. package/.claude/hooks/replay-target-audio.sh +0 -0
  50. package/.claude/hooks/requirements.txt +6 -6
  51. package/.claude/hooks/sentiment-manager.sh +0 -0
  52. package/.claude/hooks/session-start-tts.sh +0 -0
  53. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  54. package/.claude/hooks/speed-manager.sh +0 -0
  55. package/.claude/hooks/stop-tts.sh +0 -0
  56. package/.claude/hooks/termux-installer.sh +0 -0
  57. package/.claude/hooks/translate-manager.sh +0 -0
  58. package/.claude/hooks/translator.py +237 -237
  59. package/.claude/hooks/tts-queue-worker.sh +0 -0
  60. package/.claude/hooks/tts-queue.sh +0 -0
  61. package/.claude/hooks/verbosity-manager.sh +0 -0
  62. package/.claude/hooks/voice-manager.sh +6 -0
  63. package/.claude/hooks-windows/play-tts-windows-piper.ps1 +22 -16
  64. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  65. package/.claude/verbosity.txt +1 -1
  66. package/.clawdbot/README.md +105 -105
  67. package/.mcp.json +19 -6
  68. package/README.md +1 -1
  69. package/WINDOWS-SETUP.md +208 -208
  70. package/bin/agent-vibes +39 -39
  71. package/bin/agentvibes-voice-browser.js +0 -0
  72. package/bin/agentvibes.js +0 -0
  73. package/bin/mcp-server.js +121 -121
  74. package/bin/mcp-server.sh +0 -0
  75. package/bin/test-bmad-pr +78 -78
  76. package/mcp-server/QUICK_START.md +203 -203
  77. package/mcp-server/README.md +345 -345
  78. package/mcp-server/WINDOWS_SETUP.md +0 -0
  79. package/mcp-server/examples/claude_desktop_config.json +11 -11
  80. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  81. package/mcp-server/examples/custom_instructions.md +169 -169
  82. package/mcp-server/install-deps.js +0 -0
  83. package/mcp-server/server.py +1807 -1797
  84. package/mcp-server/test_server.py +0 -0
  85. package/package.json +2 -2
  86. package/src/cli/list-personalities.js +110 -110
  87. package/src/cli/list-voices.js +114 -114
  88. package/src/commands/bmad-voices.js +394 -394
  89. package/src/commands/install-mcp.js +730 -476
  90. package/src/console/app.js +3 -3
  91. package/src/console/brand-colors.js +13 -13
  92. package/src/console/constants/personalities.js +44 -44
  93. package/src/console/tabs/agents-tab.js +6 -6
  94. package/src/console/tabs/help-tab.js +314 -314
  95. package/src/console/tabs/music-tab.js +1 -1
  96. package/src/console/tabs/readme-tab.js +272 -272
  97. package/src/console/tabs/receiver-tab.js +13 -13
  98. package/src/console/tabs/settings-tab.js +2 -2
  99. package/src/console/tabs/setup-tab.js +10 -10
  100. package/src/console/tabs/voices-tab.js +4 -4
  101. package/src/console/widgets/destroy-list.js +25 -25
  102. package/src/console/widgets/notice.js +55 -55
  103. package/src/console/widgets/personality-picker.js +2 -2
  104. package/src/console/widgets/reverb-picker.js +1 -1
  105. package/src/i18n/de.js +202 -202
  106. package/src/i18n/es.js +202 -202
  107. package/src/i18n/fr.js +202 -202
  108. package/src/i18n/hi.js +202 -202
  109. package/src/i18n/ja.js +202 -202
  110. package/src/i18n/ko.js +202 -202
  111. package/src/i18n/pt.js +202 -202
  112. package/src/i18n/strings.js +54 -54
  113. package/src/i18n/zh-CN.js +202 -202
  114. package/src/installer/language-screen.js +31 -31
  115. package/src/installer/music-file-input.js +304 -304
  116. package/src/installer.js +32 -27
  117. package/src/services/config-service.js +264 -264
  118. package/src/services/language-service.js +47 -47
  119. package/src/services/provider-service.js +143 -143
  120. package/src/services/tts-engine-service.js +2 -2
  121. package/src/utils/audio-duration-validator.js +298 -298
  122. package/src/utils/audio-format-validator.js +277 -277
  123. package/src/utils/dependency-checker.js +469 -469
  124. package/src/utils/file-ownership-verifier.js +358 -358
  125. package/src/utils/list-formatter.js +200 -194
  126. package/src/utils/music-file-validator.js +285 -285
  127. package/src/utils/platform-resolver.js +369 -0
  128. package/src/utils/preview-list-prompt.js +136 -136
  129. package/src/utils/provider-validator.js +9 -9
  130. package/src/utils/secure-music-storage.js +412 -412
  131. package/templates/agentvibes-receiver.sh +231 -231
  132. package/templates/audio/welcome-music.mp3 +0 -0
  133. package/.agentvibes/install-manifest.json +0 -330
  134. package/.claude/config/background-music-position.txt +0 -27
  135. package/.claude/config/background-music-volume.txt +0 -1
  136. package/.claude/config/background-music.cfg +0 -1
  137. package/.claude/config/background-music.txt +0 -1
  138. package/.claude/config/language.txt +0 -1
  139. package/.claude/config/reverb-level.txt +0 -1
  140. package/.claude/config/tts-speech-rate.txt +0 -1
  141. package/.claude/config/tts-verbosity.txt +0 -1
  142. package/.claude/hooks/play-tts-agentvibes-receiver.sh +0 -1
  143. package/.claude/hooks-windows/audio-cache-utils.ps1.user.bak +0 -119
  144. package/.claude/hooks-windows/soprano-gradio-synth.py.user.bak +0 -153
  145. package/.claude/piper-voices-dir.txt +0 -1
@@ -123,7 +123,7 @@ async function _ensureSopranoWebUI(onStatus, signal) {
123
123
  if (Date.now() - _sopranoSpawnedAt > 10_000) {
124
124
  _sopranoSpawnedAt = Date.now();
125
125
  try {
126
- const p = spawn('soprano-webui', [], {
126
+ const p = spawn('soprano-webui', [], { // NOSONAR
127
127
  stdio: 'ignore', detached: true, windowsHide: true,
128
128
  shell: process.platform === 'win32',
129
129
  });
@@ -1159,7 +1159,7 @@ export function createSetupTab(screen, services) {
1159
1159
  const raw = fs.readFileSync(sshConfigPath, 'utf8');
1160
1160
  const seen = new Set();
1161
1161
  for (const line of raw.split('\n')) {
1162
- const m = line.match(/^\s*IdentityFile\s+(.+)\s*$/i);
1162
+ const m = line.match(/^\s*IdentityFile\s+(.+)\s*$/i); // NOSONAR
1163
1163
  if (m) {
1164
1164
  const expanded = m[1].trim().replace(/^~/, os.homedir());
1165
1165
  if (!seen.has(expanded)) { seen.add(expanded); keys.push(expanded); }
@@ -1297,7 +1297,7 @@ export function createSetupTab(screen, services) {
1297
1297
  try {
1298
1298
  const lines = fs.readFileSync(path.join(os.homedir(), '.ssh', 'config'), 'utf8').split('\n');
1299
1299
  for (const line of lines) {
1300
- const m = line.match(/^\s*[Hh]ost\s+(.+)$/);
1300
+ const m = line.match(/^\s*[Hh]ost\s+(.+)$/); // NOSONAR
1301
1301
  if (m) {
1302
1302
  for (const name of m[1].trim().split(/\s+/)) {
1303
1303
  if (!name.includes('*') && !name.includes('?') && !seen.has(name)) {
@@ -1608,10 +1608,10 @@ export function createSetupTab(screen, services) {
1608
1608
  const sampleText = 'This is how your audio settings sound right now.';
1609
1609
  const script = path.join(targetDir, '.claude', hooksSubdir, isWin ? 'play-tts.ps1' : 'play-tts.sh');
1610
1610
  const proc = isWin
1611
- ? spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', script, sampleText], {
1611
+ ? spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', script, sampleText], { // NOSONAR
1612
1612
  stdio: 'ignore', windowsHide: true, env: { ...process.env, CLAUDE_PROJECT_DIR: targetDir },
1613
1613
  })
1614
- : spawn('bash', [script, sampleText], {
1614
+ : spawn('bash', [script, sampleText], { // NOSONAR
1615
1615
  stdio: 'ignore', env: { ...process.env, CLAUDE_PROJECT_DIR: targetDir },
1616
1616
  });
1617
1617
  _previewProc = proc;
@@ -2360,13 +2360,13 @@ export function createSetupTab(screen, services) {
2360
2360
  let proc = null;
2361
2361
  try {
2362
2362
  if (engine === 'soprano') {
2363
- proc = spawn('soprano', [phrase], { stdio: 'ignore' });
2363
+ proc = spawn('soprano', [phrase], { stdio: 'ignore' }); // NOSONAR
2364
2364
  } else if (engine === 'sapi') {
2365
2365
  const safePhrase = phrase.replace(/'/g, "''");
2366
2366
  const sapiScript = `Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('${safePhrase}')`;
2367
- proc = spawn('powershell', ['-NoProfile', '-Command', sapiScript], { stdio: 'ignore', windowsHide: true });
2367
+ proc = spawn('powershell', ['-NoProfile', '-Command', sapiScript], { stdio: 'ignore', windowsHide: true }); // NOSONAR
2368
2368
  } else if (engine === 'macos-say') {
2369
- proc = spawn('say', [phrase], { stdio: 'ignore' });
2369
+ proc = spawn('say', [phrase], { stdio: 'ignore' }); // NOSONAR
2370
2370
  }
2371
2371
  } catch {}
2372
2372
  if (!proc) {
@@ -2519,13 +2519,13 @@ export function createSetupTab(screen, services) {
2519
2519
  if (_isWin) {
2520
2520
  const _playTts = path.join(_hooksBase, '.claude', 'hooks-windows', 'play-tts.ps1');
2521
2521
  const _llmArgs = llmKey ? ['-llm', llmKey] : [];
2522
- rProc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', _playTts, phrase, voiceId, ..._llmArgs], {
2522
+ rProc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', _playTts, phrase, voiceId, ..._llmArgs], { // NOSONAR
2523
2523
  stdio: 'ignore', detached: false, windowsHide: true, env: _rEnv,
2524
2524
  });
2525
2525
  } else {
2526
2526
  const _playTts = path.join(_hooksBase, '.claude', 'hooks', 'play-tts.sh');
2527
2527
  const _llmArgs = llmKey ? ['--llm', llmKey] : [];
2528
- rProc = spawn('bash', [_playTts, phrase, voiceId, ..._llmArgs], {
2528
+ rProc = spawn('bash', [_playTts, phrase, voiceId, ..._llmArgs], { // NOSONAR
2529
2529
  stdio: 'ignore', detached: true, env: _rEnv, cwd: targetDir,
2530
2530
  });
2531
2531
  }
@@ -936,12 +936,12 @@ export function createVoicesTab(screen, services) {
936
936
  let proc;
937
937
  if (isWindows) {
938
938
  const playTts = path.join(hooksBase, '.claude', 'hooks-windows', 'play-tts.ps1');
939
- proc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', playTts, phrase, voiceId], {
939
+ proc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', playTts, phrase, voiceId], { // NOSONAR
940
940
  stdio: 'ignore', detached: false, windowsHide: true, env: _spawnEnv,
941
941
  });
942
942
  } else {
943
943
  const playTts = path.join(hooksBase, '.claude', 'hooks', 'play-tts.sh');
944
- proc = spawn('bash', [playTts, phrase, voiceId], {
944
+ proc = spawn('bash', [playTts, phrase, voiceId], { // NOSONAR
945
945
  stdio: ['ignore', 'ignore', 'pipe'], detached: true, env: _spawnEnv,
946
946
  cwd: process.cwd(),
947
947
  });
@@ -1512,13 +1512,13 @@ export function createVoicesTab(screen, services) {
1512
1512
  Invoke-WebRequest -Uri '${configUrl}' -OutFile '${configFile.replace(/'/g, "''")}' -ErrorAction Stop
1513
1513
  Write-Output 'PHASE:done'
1514
1514
  `;
1515
- dlProc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', psScript], {
1515
+ dlProc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', psScript], { // NOSONAR
1516
1516
  stdio: ['ignore', 'pipe', 'pipe'],
1517
1517
  env: _spawnEnv,
1518
1518
  });
1519
1519
  } else {
1520
1520
  const managerScript = path.resolve(packageRoot, '.claude', 'hooks', 'piper-voice-manager.sh');
1521
- dlProc = spawn('bash', ['-c', 'source "$1" && download_voice "$2"', '_', managerScript, modelToDownload], {
1521
+ dlProc = spawn('bash', ['-c', 'source "$1" && download_voice "$2"', '_', managerScript, modelToDownload], { // NOSONAR
1522
1522
  stdio: ['ignore', 'pipe', 'pipe'],
1523
1523
  env: _spawnEnv,
1524
1524
  });
@@ -1,25 +1,25 @@
1
- /**
2
- * AgentVibes TUI — Shared Widget: Modal Destroy Helper
3
- *
4
- * Force-invalidates blessed's olines buffer after destroying a modal widget.
5
- * Without this, blessed skips repainting cells where lines==olines and the
6
- * terminal retains stale modal content as ghost artifacts.
7
- */
8
-
9
- /**
10
- * Destroy a blessed list/box widget and force full screen repaint.
11
- *
12
- * @param {object} widget - blessed widget to destroy
13
- * @param {object} screen - blessed screen instance
14
- * @param {Function} [onClose] - optional callback after destruction
15
- */
16
- export function destroyList(widget, screen, onClose) {
17
- widget.destroy();
18
- try {
19
- for (let r = 0; r < screen.height; r++)
20
- for (let c = 0; c < screen.width; c++)
21
- if (screen.olines[r]?.[c]) screen.olines[r][c][0] = -1;
22
- } catch {}
23
- onClose?.();
24
- screen.render();
25
- }
1
+ /**
2
+ * AgentVibes TUI — Shared Widget: Modal Destroy Helper
3
+ *
4
+ * Force-invalidates blessed's olines buffer after destroying a modal widget.
5
+ * Without this, blessed skips repainting cells where lines==olines and the
6
+ * terminal retains stale modal content as ghost artifacts.
7
+ */
8
+
9
+ /**
10
+ * Destroy a blessed list/box widget and force full screen repaint.
11
+ *
12
+ * @param {object} widget - blessed widget to destroy
13
+ * @param {object} screen - blessed screen instance
14
+ * @param {Function} [onClose] - optional callback after destruction
15
+ */
16
+ export function destroyList(widget, screen, onClose) {
17
+ widget.destroy();
18
+ try {
19
+ for (let r = 0; r < screen.height; r++)
20
+ for (let c = 0; c < screen.width; c++)
21
+ if (screen.olines[r]?.[c]) screen.olines[r][c][0] = -1;
22
+ } catch {}
23
+ onClose?.();
24
+ screen.render();
25
+ }
@@ -1,55 +1,55 @@
1
- /**
2
- * AgentVibes TUI — Shared Widget: Notice Toast
3
- *
4
- * Displays a short auto-dismissing notice modal centred on screen.
5
- * Usable from any tab; no settings-specific state required.
6
- */
7
-
8
- import { destroyList } from './destroy-list.js';
9
-
10
- const IS_TEST = process.env.AGENTVIBES_TEST_MODE === 'true';
11
- let blessed;
12
- if (!IS_TEST) {
13
- const { default: b } = await import('blessed');
14
- blessed = b;
15
- }
16
-
17
- /**
18
- * Show a temporary notice that auto-dismisses after 2.5 seconds.
19
- *
20
- * @param {object} screen - blessed screen instance
21
- * @param {string} message - text to display
22
- * @param {object} [opts]
23
- * @param {string} [opts.bg='#0a0e1a'] - background colour
24
- * @param {string} [opts.fg='#e3f2fd'] - foreground colour
25
- * @param {string} [opts.borderFg='bright-cyan'] - border colour
26
- * @param {number} [opts.durationMs=2500] - auto-dismiss delay in ms
27
- */
28
- export function showNotice(screen, message, opts = {}) {
29
- const bg = opts.bg ?? '#0a0e1a';
30
- const fg = opts.fg ?? '#e3f2fd';
31
- const borderFg = opts.borderFg ?? 'bright-cyan';
32
- const durationMs = opts.durationMs ?? 2500;
33
-
34
- const width = Math.max(28, message.length + 6);
35
- const modal = blessed.box({
36
- parent: screen,
37
- top: 'center',
38
- left: 'center',
39
- width,
40
- height: 3,
41
- border: { type: 'line' },
42
- tags: true,
43
- content: `{center}${message}{/center}`,
44
- style: {
45
- fg,
46
- bg,
47
- border: { fg: borderFg },
48
- },
49
- });
50
- screen.render();
51
-
52
- setTimeout(() => {
53
- destroyList(modal, screen);
54
- }, durationMs);
55
- }
1
+ /**
2
+ * AgentVibes TUI — Shared Widget: Notice Toast
3
+ *
4
+ * Displays a short auto-dismissing notice modal centred on screen.
5
+ * Usable from any tab; no settings-specific state required.
6
+ */
7
+
8
+ import { destroyList } from './destroy-list.js';
9
+
10
+ const IS_TEST = process.env.AGENTVIBES_TEST_MODE === 'true';
11
+ let blessed;
12
+ if (!IS_TEST) {
13
+ const { default: b } = await import('blessed');
14
+ blessed = b;
15
+ }
16
+
17
+ /**
18
+ * Show a temporary notice that auto-dismisses after 2.5 seconds.
19
+ *
20
+ * @param {object} screen - blessed screen instance
21
+ * @param {string} message - text to display
22
+ * @param {object} [opts]
23
+ * @param {string} [opts.bg='#0a0e1a'] - background colour
24
+ * @param {string} [opts.fg='#e3f2fd'] - foreground colour
25
+ * @param {string} [opts.borderFg='bright-cyan'] - border colour
26
+ * @param {number} [opts.durationMs=2500] - auto-dismiss delay in ms
27
+ */
28
+ export function showNotice(screen, message, opts = {}) {
29
+ const bg = opts.bg ?? '#0a0e1a';
30
+ const fg = opts.fg ?? '#e3f2fd';
31
+ const borderFg = opts.borderFg ?? 'bright-cyan';
32
+ const durationMs = opts.durationMs ?? 2500;
33
+
34
+ const width = Math.max(28, message.length + 6);
35
+ const modal = blessed.box({
36
+ parent: screen,
37
+ top: 'center',
38
+ left: 'center',
39
+ width,
40
+ height: 3,
41
+ border: { type: 'line' },
42
+ tags: true,
43
+ content: `{center}${message}{/center}`,
44
+ style: {
45
+ fg,
46
+ bg,
47
+ border: { fg: borderFg },
48
+ },
49
+ });
50
+ screen.render();
51
+
52
+ setTimeout(() => {
53
+ destroyList(modal, screen);
54
+ }, durationMs);
55
+ }
@@ -132,7 +132,7 @@ export function openPersonalityPicker(screen, currentPersonality, onSelect, onCl
132
132
  const _cwdScript = path.join(process.cwd(), '.claude', 'hooks-windows', 'play-tts.ps1');
133
133
  const _homeScript = path.join(os.homedir(), '.claude', 'hooks-windows', 'play-tts.ps1');
134
134
  const ttsScript = fs.existsSync(_cwdScript) ? _cwdScript : _homeScript;
135
- _pickerTtsProc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', ttsScript, phrase], {
135
+ _pickerTtsProc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', ttsScript, phrase], { // NOSONAR
136
136
  stdio: 'ignore',
137
137
  env: _env,
138
138
  });
@@ -141,7 +141,7 @@ export function openPersonalityPicker(screen, currentPersonality, onSelect, onCl
141
141
  const remoteLlm = detectRemoteLlm();
142
142
  const ttsArgs = [ttsScript, phrase];
143
143
  if (remoteLlm) ttsArgs.push('--llm', remoteLlm);
144
- _pickerTtsProc = spawn('bash', ttsArgs, {
144
+ _pickerTtsProc = spawn('bash', ttsArgs, { // NOSONAR
145
145
  stdio: 'ignore',
146
146
  detached: true,
147
147
  env: _env,
@@ -78,7 +78,7 @@ export function openReverbPicker(screen, currentPreset, onSelect, onClose, opts
78
78
  const _isWin = process.platform === 'win32' && !process.env.WSL_DISTRO_NAME;
79
79
  if (!_isWin) {
80
80
  const effectsScript = path.join(process.cwd(), '.claude', 'hooks', 'effects-manager.sh');
81
- spawnSync('bash', [effectsScript, 'set-reverb', selected.value, 'default'], {
81
+ spawnSync('bash', [effectsScript, 'set-reverb', selected.value, 'default'], { // NOSONAR
82
82
  stdio: 'ignore',
83
83
  timeout: 5000,
84
84
  env: { ...process.env },