Skip to content

Conversation

@dotCipher
Copy link

@dotCipher dotCipher commented Oct 27, 2025

This PR implements a major UX improvement to the VoiceMode CLI by introducing a consistent, verb-first command structure.

🔍 Problem

The current CLI has inconsistent command patterns that create confusion:

voicemode kokoro start              # 2 levels
voicemode whisper service start     # 3 levels! Why "service" in the middle?
voicemode livekit start             # 2 levels

This inconsistency makes commands hard to remember and creates a sometimes difficult UX.

✨ Solution

Introduced a unified, verb-first command structure that works consistently across all services:

voicemode start <service>       # Start whisper/kokoro/livekit
voicemode stop <service>        # Stop whisper/kokoro/livekit
voicemode restart <service>     # Restart whisper/kokoro/livekit
voicemode status [service]      # Show all or specific service
voicemode enable <service>      # Enable at boot/login
voicemode disable <service>     # Disable at boot/login
voicemode logs <service>        # View service logs
voicemode health <service>      # Check health endpoint

Why Verb-First?

  1. More natural: "start the whisper service" → voicemode start whisper
  2. Reduced cognitive load: Consistent pattern across all services
  3. Better discoverability: Commands appear at top level in --help
  4. Industry standard: Follows patterns from Docker, systemctl, kubectl, etc.

📊 Changes

File Modified

  • voice_mode/cli.py: +240 lines (8 new commands + deprecation warnings)

New Commands Added (8)

All commands accept whisper, kokoro, or livekit as the service argument:

  1. voicemode start <service> - Start a voice service
  2. voicemode stop <service> - Stop a voice service
  3. voicemode restart <service> - Restart a voice service
  4. voicemode status [service] - Show all services or specific service
  5. voicemode enable <service> - Enable service at boot/login
  6. voicemode disable <service> - Disable service from boot/login
  7. voicemode logs <service> - View service logs with optional line count (--lines/-n)
  8. voicemode health <service> - Check service health endpoint

Special Features

status command enhancement: Can now show all services at once!

# New capability: see all services
$ voicemode status
VoiceMode Service Status
==================================================

WHISPER:
✅ Whisper is running locally
   PID: 93773

KOKORO:
✅ Kokoro is running locally
   PID: 93805

LIVEKIT:
✅ Livekit is running locally
   PID: 984

health command: Direct health endpoint checks with detailed output

$ voicemode health whisper
✅ Whisper is responding
   Status: healthy
   Uptime: 2h 34m

Implementation Details

  1. VALID_SERVICES constant: Centralized list of supported services (['whisper', 'kokoro', 'livekit'])
  2. Click.Choice validation: Ensures only valid services are accepted
  3. Help options: All commands have -h/--help flags
  4. Async execution: All service commands use asyncio.run() for async tool functions
  5. Service-specific ports: Health command knows correct ports (Whisper: 2022, Kokoro: 8880, LiveKit: 7880)

Backward Compatibility

All old commands still work with helpful deprecation warnings:

$ voicemode kokoro start
⚠️  Deprecated: Use 'voicemode start kokoro' instead
✅ Kokoro service started

23 commands updated with deprecation warnings:

  • 9 Kokoro commands (voicemode kokoro <action>)
  • 9 Whisper commands (voicemode whisper service <action>)
  • 5 LiveKit commands (voicemode livekit <action>)

Each warning uses click.secho() with yellow text output to stderr, making it visible but non-intrusive.

Unchanged Commands

Service-specific commands remain under their service groups:

  • voicemode whisper model <name> - Whisper model management
  • voicemode whisper install - Whisper installation
  • voicemode whisper uninstall - Whisper uninstallation
  • voicemode kokoro install - Kokoro installation (with unique options)
  • voicemode kokoro uninstall - Kokoro uninstallation
  • voicemode livekit frontend ... - LiveKit frontend management
  • voicemode livekit install - LiveKit installation
  • voicemode livekit uninstall - LiveKit uninstallation

🎬 Before/After Comparison

Before

# Inconsistent patterns
voicemode kokoro status
voicemode whisper service status    # Extra nesting!
voicemode livekit status

voicemode kokoro start
voicemode whisper service start     # Different from others
voicemode livekit start

voicemode kokoro logs --lines 100
voicemode whisper service logs --lines 100
voicemode livekit logs --lines 100

After

# Consistent verb-first pattern
voicemode status kokoro
voicemode status whisper
voicemode status livekit
voicemode status                    # NEW: show all!

voicemode start kokoro
voicemode start whisper
voicemode start livekit

voicemode logs kokoro --lines 100
voicemode logs whisper --lines 100
voicemode logs livekit --lines 100

📈 Impact

User Experience Improvements

  • Reduced complexity: Maximum 2 levels for all commands (was 3 for Whisper)
  • Better discoverability: Core commands visible at top level in --help output
  • Consistency: Same pattern for all three services
  • Easier learning curve: New users can predict command structure
  • Enhanced functionality: status command can now show all services at once

Code Changes

  • +240 lines: 8 new verb-first commands with full implementation
  • ~23 commands: Added deprecation warnings to existing commands
  • 0 breaking changes: All old commands continue to work
  • Clean separation: New commands grouped at top, old commands marked deprecated

🔄 Migration Path

Users can migrate gradually:

  1. Now (v6.0.1+): Old commands work with yellow deprecation warnings
  2. Next releases: Documentation updated to show new commands first
  3. Future (v7.0.0?): Evaluate removing old commands based on usage data

🧪 Testing

All commands tested and verified:

# Test new verb-first commands
✅ voicemode start whisper
✅ voicemode stop whisper
✅ voicemode restart kokoro
✅ voicemode status
✅ voicemode status livekit
✅ voicemode enable kokoro
✅ voicemode disable kokoro
✅ voicemode logs whisper --lines 20
✅ voicemode health whisper

# Test backward compatibility
✅ voicemode kokoro start (shows deprecation warning)
✅ voicemode whisper service status (shows deprecation warning)
✅ voicemode livekit stop (shows deprecation warning)

# Test help output
✅ voicemode --help (shows new commands)
✅ voicemode start --help
✅ voicemode status --help

# Test validation
✅ voicemode start invalid_service (shows error with valid choices)

🚀 Next Steps

After this PR is merged:

  1. Update main README.md with new command examples
  2. Update documentation site with new command structure
  3. Add migration guide to docs
  4. Update CHANGELOG.md
  5. Announce in release notes
  6. Monitor user feedback and usage patterns
  7. Consider adding shell completion for new commands

📸 Command Examples

New Help Output

$ voicemode --help

Commands:
  config       Manage VoiceMode configuration.
  converse     Start a voice conversation with Claude.
  devices      List available audio devices.
  disable      Disable a voice service from starting at boot/login.
  enable       Enable a voice service to start at boot/login.
  health       Check health endpoint for a voice service.
  kokoro       Kokoro TTS service commands.
  livekit      LiveKit service commands.
  logs         View service logs for a voice service.
  providers    List available voice service providers.
  restart      Restart a voice service (whisper, kokoro, or livekit).
  start        Start a voice service (whisper, kokoro, or livekit).
  status       Show service status for all services or a specific service.
  stop         Stop a voice service (whisper, kokoro, or livekit).
  whisper      Whisper STT service commands.

Deprecation Warning Example

$ voicemode kokoro start
⚠️  Deprecated: Use 'voicemode start kokoro' instead
✅ Kokoro service started

New Status Command (All Services)

$ voicemode status
VoiceMode Service Status
==================================================

WHISPER:
✅ Whisper is running locally
   PID: 93773

KOKORO:
✅ Kokoro is running locally
   PID: 93805

LIVEKIT:
❌ Livekit is not running

Review Focus Areas:

  • Command naming and consistency across services
  • Deprecation message clarity and helpfulness
  • Help text quality and examples
  • Backward compatibility handling
  • Service validation logic
  • Health check implementation

@dotCipher
Copy link
Author

📓 Implementation here was prioritizing deprecation first, then migration, so all previous commands should still work as intended

@mbailey
Copy link
Owner

mbailey commented Oct 28, 2025

I'll consider it.

  1. Whisper and Kokoro are awesome third party software that would be better installed from users package managers. I added them (and great personal expense to my weekends and annual leave) to deliver an awesome experience and make it easier for people to get started with free local voice services. I would love to be able to remove them from voicemode because it's so damn easy to install them other ways. External dependencies are liabilities for unfunded FOSS maintainers.

  2. I prefer tab completion for discovery, rather than relying on memory and tend to use big endian naming.

$ voicemode kokoro [TAB TAB]
disable               health                logs                  start                 stop                  update-service-files
enable                install               restart               status                uninstall

I'm more likely to follow a voicemode kokoro command with another voicemode kokoro command so I'd rather the flapping tail of the kite to be on the right with the string on the left (we always have lefterly breezes round here).

  1. I like the following from your suggestion:
voicemode status
voicemode status kokoro
voicemode status whisper
  1. The reason voicemode whisper has service and model as subcommands is because their two things to manage.

Thanks for your suggestion.

There is an answer, but I'll have to think about it...

image

@mbailey mbailey added the enhancement New feature or request label Oct 28, 2025
@dotCipher
Copy link
Author

Sounds good, glad there's some good context and insights you got from it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants