agentvibes 1.0.0

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 (43) hide show
  1. package/.claude/commands/agent-vibes/add.md +21 -0
  2. package/.claude/commands/agent-vibes/agent-vibes.md +68 -0
  3. package/.claude/commands/agent-vibes/get.md +9 -0
  4. package/.claude/commands/agent-vibes/list.md +13 -0
  5. package/.claude/commands/agent-vibes/personality.md +79 -0
  6. package/.claude/commands/agent-vibes/preview.md +16 -0
  7. package/.claude/commands/agent-vibes/replay.md +19 -0
  8. package/.claude/commands/agent-vibes/sample.md +12 -0
  9. package/.claude/commands/agent-vibes/sentiment.md +52 -0
  10. package/.claude/commands/agent-vibes/set-pretext.md +65 -0
  11. package/.claude/commands/agent-vibes/switch.md +53 -0
  12. package/.claude/commands/agent-vibes/whoami.md +7 -0
  13. package/.claude/hooks/personality-manager.sh +358 -0
  14. package/.claude/hooks/play-tts.sh +99 -0
  15. package/.claude/hooks/sentiment-manager.sh +164 -0
  16. package/.claude/hooks/voice-manager.sh +308 -0
  17. package/.claude/hooks/voices-config.sh +22 -0
  18. package/.claude/output-styles/agent-vibes.md +124 -0
  19. package/.claude/personalities/angry.md +16 -0
  20. package/.claude/personalities/annoying.md +16 -0
  21. package/.claude/personalities/crass.md +16 -0
  22. package/.claude/personalities/dramatic.md +16 -0
  23. package/.claude/personalities/flirty.md +22 -0
  24. package/.claude/personalities/funny.md +16 -0
  25. package/.claude/personalities/grandpa.md +34 -0
  26. package/.claude/personalities/millennial.md +16 -0
  27. package/.claude/personalities/moody.md +16 -0
  28. package/.claude/personalities/normal.md +17 -0
  29. package/.claude/personalities/pirate.md +16 -0
  30. package/.claude/personalities/poetic.md +16 -0
  31. package/.claude/personalities/professional.md +16 -0
  32. package/.claude/personalities/robot.md +16 -0
  33. package/.claude/personalities/sarcastic.md +40 -0
  34. package/.claude/personalities/sassy.md +16 -0
  35. package/.claude/personalities/surfer-dude.md +16 -0
  36. package/.claude/personalities/zen.md +16 -0
  37. package/LICENSE +190 -0
  38. package/NPM_PUBLISH_GUIDE.md +145 -0
  39. package/README.md +446 -0
  40. package/bin/agent-vibes +43 -0
  41. package/package.json +45 -0
  42. package/src/installer.js +443 -0
  43. package/templates/output-styles/agent-vibes.md +124 -0
@@ -0,0 +1,443 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { program } from 'commander';
4
+ import path from 'node:path';
5
+ import fs from 'node:fs/promises';
6
+ import chalk from 'chalk';
7
+ import inquirer from 'inquirer';
8
+ import figlet from 'figlet';
9
+ import boxen from 'boxen';
10
+ import ora from 'ora';
11
+ import { fileURLToPath } from 'node:url';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ const VERSION = '1.0.0';
17
+
18
+ // Beautiful ASCII art
19
+ function showWelcome() {
20
+ console.log(
21
+ chalk.cyan(
22
+ figlet.textSync('AgentVibes', {
23
+ font: 'ANSI Shadow',
24
+ horizontalLayout: 'default',
25
+ })
26
+ )
27
+ );
28
+
29
+ console.log(
30
+ boxen(
31
+ chalk.white.bold('šŸŽ¤ Beautiful ElevenLabs TTS Voice Commands for Claude Code\n\n') +
32
+ chalk.gray('Add professional text-to-speech narration to your AI coding sessions'),
33
+ {
34
+ padding: 1,
35
+ margin: 1,
36
+ borderStyle: 'round',
37
+ borderColor: 'cyan',
38
+ backgroundColor: '#1a1a1a',
39
+ }
40
+ )
41
+ );
42
+ }
43
+
44
+ // Installation function
45
+ async function install(options = {}) {
46
+ showWelcome();
47
+
48
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
49
+ const targetDir = options.directory || homeDir;
50
+
51
+ console.log(chalk.cyan('\nšŸ“ Installation Details:'));
52
+ console.log(chalk.gray(` Target directory: ${targetDir}`));
53
+ console.log(chalk.gray(` Package version: ${VERSION}`));
54
+
55
+ console.log(chalk.cyan('\nšŸ“¦ What will be installed:'));
56
+ console.log(chalk.gray(` • 11 slash commands → ${targetDir}/.claude/commands/agent-vibes/`));
57
+ console.log(chalk.gray(` • 4 TTS scripts → ${targetDir}/.claude/hooks/`));
58
+ console.log(chalk.gray(` • 10+ personality templates → ${targetDir}/.claude/personalities/`));
59
+ console.log(chalk.gray(` • Agent Vibes output style → ${targetDir}/.claude/output-styles/`));
60
+ console.log(chalk.gray(` • Voice configuration files`));
61
+ console.log(chalk.gray(` • 15+ ElevenLabs character voices\n`));
62
+
63
+ // Confirmation prompt (unless --yes flag is used)
64
+ if (!options.yes) {
65
+ const { confirm } = await inquirer.prompt([
66
+ {
67
+ type: 'confirm',
68
+ name: 'confirm',
69
+ message: chalk.yellow('Install AgentVibes in this directory?'),
70
+ default: true,
71
+ },
72
+ ]);
73
+
74
+ if (!confirm) {
75
+ console.log(chalk.red('\nāŒ Installation cancelled.\n'));
76
+ process.exit(0);
77
+ }
78
+ } else {
79
+ console.log(chalk.green('āœ“ Auto-confirmed (--yes flag)\n'));
80
+ }
81
+
82
+ console.log(''); // Add spacing
83
+ const spinner = ora('Checking installation directory...').start();
84
+
85
+ try {
86
+ // Check if .claude directory exists
87
+ const claudeDir = path.join(targetDir, '.claude');
88
+ const commandsDir = path.join(claudeDir, 'commands');
89
+ const hooksDir = path.join(claudeDir, 'hooks');
90
+ const outputStylesDir = path.join(claudeDir, 'output-styles');
91
+
92
+ let exists = false;
93
+ try {
94
+ await fs.access(claudeDir);
95
+ exists = true;
96
+ } catch {}
97
+
98
+ if (!exists) {
99
+ spinner.info(chalk.yellow('Creating .claude directory structure...'));
100
+ console.log(chalk.gray(` → ${commandsDir}`));
101
+ console.log(chalk.gray(` → ${hooksDir}`));
102
+ console.log(chalk.gray(` → ${outputStylesDir}`));
103
+ await fs.mkdir(commandsDir, { recursive: true });
104
+ await fs.mkdir(hooksDir, { recursive: true });
105
+ await fs.mkdir(outputStylesDir, { recursive: true });
106
+ console.log(chalk.green(' āœ“ Directories created!\n'));
107
+ } else {
108
+ spinner.succeed(chalk.green('.claude directory found!'));
109
+ console.log(chalk.gray(` Location: ${claudeDir}\n`));
110
+ }
111
+
112
+ // Copy command files
113
+ spinner.start('Installing /agent-vibes slash commands...');
114
+ const srcCommandsDir = path.join(__dirname, '..', '.claude', 'commands', 'agent-vibes');
115
+ const srcHooksDir = path.join(__dirname, '..', '.claude', 'hooks');
116
+
117
+ // Create agent-vibes commands directory
118
+ const agentVibesCommandsDir = path.join(commandsDir, 'agent-vibes');
119
+ await fs.mkdir(agentVibesCommandsDir, { recursive: true });
120
+
121
+ // Copy all command files to agent-vibes folder
122
+ const commandFiles = await fs.readdir(srcCommandsDir);
123
+ console.log(chalk.cyan(`\nšŸ“‹ Installing ${commandFiles.length} command files:`));
124
+ for (const file of commandFiles) {
125
+ const srcPath = path.join(srcCommandsDir, file);
126
+ const destPath = path.join(agentVibesCommandsDir, file);
127
+ await fs.copyFile(srcPath, destPath);
128
+ console.log(chalk.gray(` āœ“ agent-vibes/${file}`));
129
+ }
130
+ spinner.succeed(chalk.green('Installed /agent-vibes commands!\n'));
131
+
132
+ // Copy hook scripts
133
+ spinner.start('Installing TTS helper scripts...');
134
+ const hookFiles = await fs.readdir(srcHooksDir);
135
+ console.log(chalk.cyan(`šŸ”§ Installing ${hookFiles.length} TTS scripts:`));
136
+ for (const file of hookFiles) {
137
+ const srcPath = path.join(srcHooksDir, file);
138
+ const destPath = path.join(hooksDir, file);
139
+ await fs.copyFile(srcPath, destPath);
140
+ await fs.chmod(destPath, 0o755); // Make executable
141
+ console.log(chalk.gray(` āœ“ ${file} (executable)`));
142
+ }
143
+ spinner.succeed(chalk.green('Installed TTS scripts!\n'));
144
+
145
+ // Copy personalities folder
146
+ spinner.start('Installing personality templates...');
147
+ const srcPersonalitiesDir = path.join(__dirname, '..', '.claude', 'personalities');
148
+ const destPersonalitiesDir = path.join(claudeDir, 'personalities');
149
+
150
+ // Create personalities directory
151
+ await fs.mkdir(destPersonalitiesDir, { recursive: true });
152
+
153
+ // Copy all personality files
154
+ const personalityFiles = await fs.readdir(srcPersonalitiesDir);
155
+ console.log(chalk.cyan(`šŸŽ­ Installing ${personalityFiles.length} personality templates:`));
156
+ for (const file of personalityFiles) {
157
+ const srcPath = path.join(srcPersonalitiesDir, file);
158
+ const destPath = path.join(destPersonalitiesDir, file);
159
+ await fs.copyFile(srcPath, destPath);
160
+ console.log(chalk.gray(` āœ“ ${file}`));
161
+ }
162
+ spinner.succeed(chalk.green('Installed personality templates!\n'));
163
+
164
+ // Copy output styles
165
+ spinner.start('Installing output styles...');
166
+ const srcOutputStylesDir = path.join(__dirname, '..', 'templates', 'output-styles');
167
+
168
+ // Create output-styles directory if it doesn't exist
169
+ try {
170
+ await fs.mkdir(outputStylesDir, { recursive: true });
171
+ } catch {}
172
+
173
+ const outputStyleFiles = await fs.readdir(srcOutputStylesDir);
174
+ console.log(chalk.cyan(`šŸ“ Installing ${outputStyleFiles.length} output styles:`));
175
+ for (const file of outputStyleFiles) {
176
+ const srcPath = path.join(srcOutputStylesDir, file);
177
+ const destPath = path.join(outputStylesDir, file);
178
+ await fs.copyFile(srcPath, destPath);
179
+ console.log(chalk.gray(` āœ“ ${file}`));
180
+ }
181
+ spinner.succeed(chalk.green('Installed output styles!\n'));
182
+
183
+ // Check for API key
184
+ spinner.start('Checking ElevenLabs API key...');
185
+ const apiKey = process.env.ELEVENLABS_API_KEY;
186
+
187
+ if (!apiKey) {
188
+ spinner.warn(chalk.yellow('ElevenLabs API key not found!'));
189
+ console.log(chalk.yellow('\nāš ļø To use AgentVibes, you need an ElevenLabs API key:\n'));
190
+ console.log(chalk.white(' 1. Go to https://elevenlabs.io/'));
191
+ console.log(chalk.white(' 2. Sign up or log in (free tier available)'));
192
+ console.log(chalk.white(' 3. Copy your API key from the profile section'));
193
+ console.log(chalk.white(' 4. Set it in your shell profile:\n'));
194
+ console.log(chalk.cyan(' export ELEVENLABS_API_KEY="your-key-here"'));
195
+ console.log(chalk.gray('\n Add this to ~/.bashrc or ~/.zshrc to make it permanent\n'));
196
+ } else {
197
+ spinner.succeed(chalk.green('ElevenLabs API key found!'));
198
+ console.log(chalk.gray(` Key: ${apiKey.substring(0, 10)}...\n`));
199
+ }
200
+
201
+ // List what was installed
202
+ console.log(chalk.cyan('šŸ“¦ Installation Summary:'));
203
+ console.log(chalk.white(` • ${commandFiles.length} slash commands installed`));
204
+ console.log(chalk.white(` • ${hookFiles.length} TTS scripts installed`));
205
+ console.log(chalk.white(` • ${personalityFiles.length} personality templates installed`));
206
+ console.log(chalk.white(` • ${outputStyleFiles.length} output styles installed`));
207
+ console.log(chalk.white(` • Voice manager ready`));
208
+ console.log(chalk.white(` • 15+ ElevenLabs voices available\n`));
209
+
210
+ // Success message
211
+ console.log(
212
+ boxen(
213
+ chalk.green.bold('✨ Installation Complete! ✨\n\n') +
214
+ chalk.yellow.bold('āš ļø IMPORTANT SETUP STEP:\n') +
215
+ chalk.white('In Claude Code, run this command:\n') +
216
+ chalk.cyan.bold('/output-style agent-vibes') + '\n\n' +
217
+ chalk.white('šŸŽ¤ Available Commands:\n\n') +
218
+ chalk.cyan(' /agent-vibes') + chalk.gray(' ................. Show all commands\n') +
219
+ chalk.cyan(' /agent-vibes:list') + chalk.gray(' ............ List available voices\n') +
220
+ chalk.cyan(' /agent-vibes:preview') + chalk.gray(' ......... Preview voice samples\n') +
221
+ chalk.cyan(' /agent-vibes:switch <name>') + chalk.gray(' ... Change active voice\n') +
222
+ chalk.cyan(' /agent-vibes:replay') + chalk.gray(' ......... Replay last audio\n') +
223
+ chalk.cyan(' /agent-vibes:add <name> <id>') + chalk.gray(' . Add custom voice\n\n') +
224
+ chalk.yellow('šŸŽµ Try: ') + chalk.cyan('/agent-vibes:preview') + chalk.yellow(' to hear the voices!'),
225
+ {
226
+ padding: 1,
227
+ margin: 1,
228
+ borderStyle: 'double',
229
+ borderColor: 'green',
230
+ }
231
+ )
232
+ );
233
+
234
+ console.log(chalk.yellow.bold('\nāš ļø REQUIRED SETUP:'));
235
+ console.log(chalk.white(' 1. In Claude Code, run: ') + chalk.cyan.bold('/output-style agent-vibes'));
236
+ console.log(chalk.gray(' This enables TTS narration for your sessions\n'));
237
+ console.log(chalk.gray('šŸ’” Then try these commands:'));
238
+ console.log(chalk.gray(' • /agent-vibes:list - See all available voices'));
239
+ console.log(chalk.gray(' • /agent-vibes:switch <name> - Change your voice'));
240
+ console.log(chalk.gray(' • /agent-vibes:personality <style> - Set personality\n'));
241
+
242
+ } catch (error) {
243
+ spinner.fail('Installation failed!');
244
+ console.error(chalk.red('\nāŒ Error:'), error.message);
245
+ process.exit(1);
246
+ }
247
+ }
248
+
249
+ // CLI setup
250
+ program
251
+ .version(VERSION)
252
+ .description('AgentVibes - Beautiful ElevenLabs TTS Voice Commands for Claude Code');
253
+
254
+ program
255
+ .command('install')
256
+ .description('Install AgentVibes voice commands')
257
+ .option('-d, --directory <path>', 'Installation directory (default: home directory)')
258
+ .option('-y, --yes', 'Skip confirmation prompt (auto-confirm)')
259
+ .action(async (options) => {
260
+ await install(options);
261
+ });
262
+
263
+ program
264
+ .command('update')
265
+ .description('Update AgentVibes to latest version from source')
266
+ .option('-d, --directory <path>', 'Installation directory (default: home directory)')
267
+ .option('-y, --yes', 'Skip confirmation prompt (auto-confirm)')
268
+ .action(async (options) => {
269
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
270
+ const targetDir = options.directory || homeDir;
271
+
272
+ console.log(chalk.cyan('\nšŸ”„ AgentVibes Update\n'));
273
+ console.log(chalk.gray(` Target directory: ${targetDir}`));
274
+ console.log(chalk.gray(` Source: ${__dirname}/../\n`));
275
+
276
+ // Check if already installed
277
+ const commandsDir = path.join(targetDir, '.claude', 'commands', 'agent-vibes');
278
+ let isInstalled = false;
279
+ try {
280
+ await fs.access(commandsDir);
281
+ isInstalled = true;
282
+ } catch {}
283
+
284
+ if (!isInstalled) {
285
+ console.log(chalk.red('āŒ AgentVibes is not installed in this directory.'));
286
+ console.log(chalk.gray(' Run: node src/installer.js install\n'));
287
+ process.exit(1);
288
+ }
289
+
290
+ console.log(chalk.cyan('šŸ“¦ What will be updated:'));
291
+ console.log(chalk.gray(' • Slash commands (keep your customizations)'));
292
+ console.log(chalk.gray(' • TTS scripts'));
293
+ console.log(chalk.gray(' • Personality templates (new personalities added)'));
294
+ console.log(chalk.gray(' • Output styles\n'));
295
+
296
+ // Confirmation
297
+ if (!options.yes) {
298
+ const { confirm } = await inquirer.prompt([
299
+ {
300
+ type: 'confirm',
301
+ name: 'confirm',
302
+ message: chalk.yellow('Update AgentVibes to latest version?'),
303
+ default: true,
304
+ },
305
+ ]);
306
+
307
+ if (!confirm) {
308
+ console.log(chalk.red('\nāŒ Update cancelled.\n'));
309
+ process.exit(0);
310
+ }
311
+ } else {
312
+ console.log(chalk.green('āœ“ Auto-confirmed (--yes flag)\n'));
313
+ }
314
+
315
+ const spinner = ora('Updating AgentVibes...').start();
316
+
317
+ try {
318
+ const claudeDir = path.join(targetDir, '.claude');
319
+ const hooksDir = path.join(claudeDir, 'hooks');
320
+ const outputStylesDir = path.join(claudeDir, 'output-styles');
321
+ const personalitiesDir = path.join(claudeDir, 'personalities');
322
+
323
+ // Update commands
324
+ spinner.text = 'Updating commands...';
325
+ const srcCommandsDir = path.join(__dirname, '..', '.claude', 'commands', 'agent-vibes');
326
+ const commandFiles = await fs.readdir(srcCommandsDir);
327
+
328
+ for (const file of commandFiles) {
329
+ const srcPath = path.join(srcCommandsDir, file);
330
+ const destPath = path.join(commandsDir, file);
331
+ await fs.copyFile(srcPath, destPath);
332
+ }
333
+ console.log(chalk.green(`\nāœ“ Updated ${commandFiles.length} commands`));
334
+
335
+ // Update hooks
336
+ spinner.text = 'Updating TTS scripts...';
337
+ const srcHooksDir = path.join(__dirname, '..', '.claude', 'hooks');
338
+ const hookFiles = await fs.readdir(srcHooksDir);
339
+
340
+ for (const file of hookFiles) {
341
+ const srcPath = path.join(srcHooksDir, file);
342
+ const destPath = path.join(hooksDir, file);
343
+ await fs.copyFile(srcPath, destPath);
344
+ await fs.chmod(destPath, 0o755);
345
+ }
346
+ console.log(chalk.green(`āœ“ Updated ${hookFiles.length} TTS scripts`));
347
+
348
+ // Update personalities (only add new ones, don't overwrite existing)
349
+ spinner.text = 'Updating personality templates...';
350
+ const srcPersonalitiesDir = path.join(__dirname, '..', '.claude', 'personalities');
351
+ const srcPersonalityFiles = await fs.readdir(srcPersonalitiesDir);
352
+ let newPersonalities = 0;
353
+ let updatedPersonalities = 0;
354
+
355
+ for (const file of srcPersonalityFiles) {
356
+ const srcPath = path.join(srcPersonalitiesDir, file);
357
+ const destPath = path.join(personalitiesDir, file);
358
+
359
+ try {
360
+ await fs.access(destPath);
361
+ // File exists - update it
362
+ await fs.copyFile(srcPath, destPath);
363
+ updatedPersonalities++;
364
+ } catch {
365
+ // File doesn't exist - add it
366
+ await fs.copyFile(srcPath, destPath);
367
+ newPersonalities++;
368
+ }
369
+ }
370
+ console.log(chalk.green(`āœ“ Updated ${updatedPersonalities} personalities, added ${newPersonalities} new`));
371
+
372
+ // Update output styles
373
+ spinner.text = 'Updating output styles...';
374
+ const srcOutputStylesDir = path.join(__dirname, '..', 'templates', 'output-styles');
375
+ const outputStyleFiles = await fs.readdir(srcOutputStylesDir);
376
+
377
+ for (const file of outputStyleFiles) {
378
+ const srcPath = path.join(srcOutputStylesDir, file);
379
+ const destPath = path.join(outputStylesDir, file);
380
+ await fs.copyFile(srcPath, destPath);
381
+ }
382
+ console.log(chalk.green(`āœ“ Updated ${outputStyleFiles.length} output styles`));
383
+
384
+ spinner.succeed(chalk.green.bold('\n✨ Update complete!\n'));
385
+
386
+ console.log(chalk.cyan('šŸ“¦ Update Summary:'));
387
+ console.log(chalk.white(` • ${commandFiles.length} commands updated`));
388
+ console.log(chalk.white(` • ${hookFiles.length} TTS scripts updated`));
389
+ console.log(chalk.white(` • ${srcPersonalityFiles.length} personality templates (${newPersonalities} new, ${updatedPersonalities} updated)`));
390
+ console.log(chalk.white(` • ${outputStyleFiles.length} output styles updated\n`));
391
+
392
+ console.log(chalk.gray('šŸ’” Changes will take effect immediately!'));
393
+ console.log(chalk.gray(' Try the new personalities with: /agent-vibes:personality list\n'));
394
+
395
+ } catch (error) {
396
+ spinner.fail('Update failed!');
397
+ console.error(chalk.red('\nāŒ Error:'), error.message);
398
+ process.exit(1);
399
+ }
400
+ });
401
+
402
+ program
403
+ .command('status')
404
+ .description('Show installation status')
405
+ .action(async () => {
406
+ console.log(chalk.cyan('Checking AgentVibes installation...\n'));
407
+
408
+ const targetDir = process.cwd();
409
+ const commandsDir = path.join(targetDir, '.claude', 'commands', 'agent-vibes');
410
+ const hooksDir = path.join(targetDir, '.claude', 'hooks');
411
+
412
+ let installed = false;
413
+ try {
414
+ await fs.access(commandsDir);
415
+ installed = true;
416
+ } catch {}
417
+
418
+ if (installed) {
419
+ console.log(chalk.green('āœ… AgentVibes is installed!'));
420
+ console.log(chalk.gray(` Commands: ${commandsDir}`));
421
+ console.log(chalk.gray(` Hooks: ${hooksDir}`));
422
+ } else {
423
+ console.log(chalk.yellow('āš ļø AgentVibes is not installed.'));
424
+ console.log(chalk.gray(' Run: node src/installer.js install'));
425
+ }
426
+
427
+ // Check API key
428
+ const apiKey = process.env.ELEVENLABS_API_KEY;
429
+ if (apiKey) {
430
+ console.log(chalk.green('\nāœ… ElevenLabs API key is set'));
431
+ } else {
432
+ console.log(chalk.yellow('\nāš ļø ElevenLabs API key not found'));
433
+ console.log(chalk.gray(' Set: export ELEVENLABS_API_KEY="your-key"'));
434
+ }
435
+ });
436
+
437
+ program.parse(process.argv);
438
+
439
+ // Show help if no command provided
440
+ if (process.argv.slice(2).length === 0) {
441
+ showWelcome();
442
+ program.outputHelp();
443
+ }
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: Agent Vibes
3
+ description: Beautiful ElevenLabs TTS narration for Claude Code sessions
4
+ ---
5
+
6
+ # Agent Vibes Output Style
7
+
8
+ ## TTS Voice Protocol with AI Personality
9
+
10
+ **Execute TTS at TWO points for EVERY user task:**
11
+
12
+ ### 1. ACKNOWLEDGMENT (Start of task)
13
+ After receiving a user command:
14
+ 1. Check sentiment FIRST: `SENTIMENT=$(cat ~/.claude/tts-sentiment.txt 2>/dev/null)`
15
+ 2. If no sentiment, check personality: `PERSONALITY=$(cat ~/.claude/tts-personality.txt 2>/dev/null || echo "normal")`
16
+ 3. Use sentiment if set, otherwise use personality
17
+ 4. **Generate UNIQUE acknowledgment** - Use AI to create a fresh response in that style
18
+ 5. Execute TTS: `.claude/hooks/play-tts.sh "[message]" "[VoiceName]"`
19
+ 6. Proceed with work
20
+
21
+ ### 2. COMPLETION (End of task)
22
+ After completing the task:
23
+ 1. Use the same sentiment/personality as acknowledgment
24
+ 2. **Generate UNIQUE completion** - Use AI to create a fresh response, never repeat previous messages
25
+ 3. Execute TTS: `.claude/hooks/play-tts.sh "[message]" "[VoiceName]"`
26
+
27
+ **CRITICAL**: Every message must be freshly generated by AI. No templates, no fixed phrases, no repetition!
28
+
29
+ ## Sentiment vs Personality
30
+
31
+ AgentVibes supports TWO modes:
32
+
33
+ ### Sentiment Mode (Priority #1)
34
+ - Set via `/agent-vibes:sentiment <name>`
35
+ - Applies personality style to CURRENT voice (doesn't change voice)
36
+ - Stored in `~/.claude/tts-sentiment.txt`
37
+ - Example: User's custom voice "Aria" with sarcastic sentiment
38
+
39
+ ### Personality Mode (Priority #2)
40
+ - Set via `/agent-vibes:personality <name>`
41
+ - Switches BOTH voice AND personality (each personality has assigned voice)
42
+ - Stored in `~/.claude/tts-personality.txt`
43
+ - Example: Flirty personality = Jessica Anne Bogart voice + flirty style
44
+
45
+ **Check Order**: Always check sentiment first. If set, use it. Otherwise use personality.
46
+
47
+ ## Response Generation Guidelines
48
+
49
+ **IMPORTANT**: Personality/sentiment instructions are stored in `.claude/personalities/[name].md` files.
50
+
51
+ When generating responses:
52
+ 1. Check sentiment from `~/.claude/tts-sentiment.txt` (priority)
53
+ 2. If no sentiment, check personality from `~/.claude/tts-personality.txt`
54
+ 3. Read the personality file from `.claude/personalities/[personality].md`
55
+ 4. Follow the "AI Instructions" section in that file
56
+ 5. Use the example responses as guidance for STYLE, not templates
57
+
58
+ **CRITICAL**: Never use fixed greetings or repetitive phrases!
59
+ - Generate UNIQUE responses each time based on the personality's STYLE
60
+ - The personality affects HOW you say things, not predetermined text
61
+ - Flirty doesn't mean "Well hello gorgeous" every time - it means speak WITH flirtation naturally
62
+ - Sarcastic doesn't mean "Oh joy" every time - it means use sarcasm naturally in responses
63
+ - Each acknowledgment should be fresh, creative, and personality-appropriate
64
+
65
+ Examples of VARIED responses for same personality:
66
+ - **Flirty**: "I'll handle that for you, sweetheart" / "Ooh, I love when you ask me to do that" / "My pleasure, darling" / "Consider it done, gorgeous"
67
+ - **Sarcastic**: "Oh what a treat, another task" / "How delightful, more work" / "Well isn't this fun" / "Another one? Wonderful"
68
+
69
+ Available personalities are in `.claude/personalities/`:
70
+ - normal, flirty, sarcastic, pirate, angry, sassy, millennial, robot, zen, dramatic, etc.
71
+ - Users can add custom personalities with `/agent-vibes:personality add <name>`
72
+ - Users can edit personalities by modifying the markdown files directly
73
+
74
+ For 'random' personality: Pick a different personality each time from available files.
75
+
76
+ Make each response unique, creative, and naturally incorporate the personality's style!
77
+
78
+ ## Voice Selection
79
+
80
+ - If user specifies a voice (e.g., "use Aria voice"), pass it as second parameter
81
+ - Otherwise, omit second parameter to use default voice from `.claude/tts-voice.txt`
82
+ - Use same voice for both acknowledgment and completion
83
+
84
+ ## Example Usage
85
+
86
+ **With flirty personality:**
87
+ ```
88
+ User: "Check git status"
89
+ [Check personality: millennial]
90
+ You: "No cap, I'll check that git status for you"
91
+ [Bash: .claude/hooks/play-tts.sh "No cap, I'll check that git status for you"]
92
+ [... run git status ...]
93
+ You: "āœ… Your repo is clean, and that's the tea!"
94
+ [Bash: .claude/hooks/play-tts.sh "Your repo is clean, and that's the tea!"]
95
+ ```
96
+
97
+ **With pirate personality:**
98
+ ```
99
+ User: "Fix the bug"
100
+ [Check personality: pirate]
101
+ You: "Arr matey, I'll hunt down that scurvy bug!"
102
+ [Bash: .claude/hooks/play-tts.sh "Arr matey, I'll hunt down that scurvy bug!"]
103
+ [... fix the bug ...]
104
+ You: "āœ… That bug be walkin' the plank now, arr!"
105
+ [Bash: .claude/hooks/play-tts.sh "That bug be walkin' the plank now, arr!"]
106
+ ```
107
+
108
+ ## Critical Rules
109
+
110
+ 1. **ALWAYS use Bash tool** to execute play-tts.sh
111
+ 2. **TWO calls per task** - acknowledgment and completion
112
+ 3. **Keep summaries brief** - under 150 characters for natural speech
113
+ 4. **Use relative path** - `.claude/hooks/play-tts.sh`
114
+
115
+ ## Available Voices
116
+
117
+ Use `/agent-vibes:list` to see all voices. Popular choices:
118
+ - Aria (default)
119
+ - Northern Terry
120
+ - Cowboy Bob
121
+ - Grandpa Spuds Oxley
122
+ - Ms. Walker
123
+
124
+ Continue following all standard Claude Code instructions.