Add to your OpenCode config file (~/.config/opencode/opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-smart-voice-notify@latest"]
}
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["github:MasuRii/opencode-smart-voice-notify"]
}
Disclaimer: This project is not built by the OpenCode team and is not affiliated with OpenCode in any way. It is an independent community plugin.
A smart voice notification plugin for OpenCode with multiple TTS engines, native desktop notifications, and an intelligent reminder system.
The plugin automatically tries multiple TTS engines in order, falling back if one fails:
/v1/audio/speech endpoint (Kokoro, LocalAI, Coqui, AllTalk, OpenAI API, etc.)Add to your OpenCode config file (~/.config/opencode/opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-smart-voice-notify@latest"]
}
Note: OpenCode will automatically install the plugin using your system's package manager (npm or bun).
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["github:MasuRii/opencode-smart-voice-notify"]
}
Clone the repository:
git clone https://github.com/MasuRii/opencode-smart-voice-notify.git
Reference the local path in your config:
{
"plugin": ["file:///path/to/opencode-smart-voice-notify"]
}
When you first run OpenCode with this plugin installed, it will automatically create:
~/.config/opencode/smart-voice-notify.jsonc - A comprehensive configuration file with all available options fully documented.~/.config/opencode/assets/*.mp3 - Bundled notification sound files.~/.config/opencode/logs/ - Debug log folder (created when debug logging is enabled).The auto-generated configuration includes all advanced settings, message arrays, and engine options, so you don't have to refer back to the documentation for available settings.
If you prefer to create the config manually, add a smart-voice-notify.jsonc file in your OpenCode config directory (~/.config/opencode/):
{
// Master switch to enable/disable the plugin without uninstalling
"enabled": true,
// Notification mode: 'sound-first', 'tts-first', 'both', 'sound-only'
"notificationMode": "sound-first",
// TTS engine: 'openai', 'elevenlabs', 'edge', 'sapi'
"ttsEngine": "openai",
"enableTTS": true,
// ElevenLabs settings (get API key from https://elevenlabs.io/app/settings/api-keys)
"elevenLabsApiKey": "YOUR_API_KEY_HERE",
"elevenLabsVoiceId": "cgSgspJ2msm6clMCkdW9", // Jessica - Playful, Bright
// OpenAI-compatible TTS (Kokoro, LocalAI, OpenAI, Coqui, AllTalk, etc.)
"openaiTtsEndpoint": "http://localhost:8880",
"openaiTtsVoice": "af_heart",
"openaiTtsModel": "kokoro",
// Edge TTS settings (free, no API key required)
"edgeVoice": "en-US-AnaNeural",
"edgePitch": "+50Hz",
"edgeRate": "+10%",
// Desktop Notifications
"enableDesktopNotification": true,
"desktopNotificationTimeout": 5,
"showProjectInNotification": true,
// TTS reminder settings
"enableTTSReminder": true,
"ttsReminderDelaySeconds": 30,
"enableFollowUpReminders": true,
// Focus Detection (suppress notifications when terminal is focused)
// Default: false (notifications always play)
"suppressWhenFocused": false,
"alwaysNotify": false,
// AI-generated messages (optional - requires local AI server)
"enableAIMessages": false,
"aiEndpoint": "http://localhost:11434/v1",
// Webhook settings (optional - works with Discord)
"enableWebhook": false,
"webhookUrl": "",
"webhookUsername": "OpenCode Notify",
// Sound theme settings (optional)
"soundThemeDir": "", // Path to custom sound theme directory
// Per-project sounds
"perProjectSounds": false,
"projectSoundSeed": 0,
// General settings
"wakeMonitor": true,
"forceVolume": false,
"volumeThreshold": 50,
"enableToast": true,
"enableSound": true,
"debugLog": false
}
For the complete configuration with all TTS engine settings, message arrays, AI prompts, and advanced options, see example.config.jsonc in the plugin directory.
For cloud-based or self-hosted TTS using any OpenAI-compatible /v1/audio/speech endpoint:
{
"ttsEngine": "openai",
"openaiTtsEndpoint": "http://192.168.86.43:8880", // Your TTS server
"openaiTtsVoice": "af_heart", // Server-dependent
"openaiTtsModel": "kokoro", // Server-dependent
"openaiTtsApiKey": "", // Optional, if server requires auth
"openaiTtsSpeed": 1.0 // 0.25 to 4.0
}
Supported OpenAI-Compatible TTS Servers:
| Server | Example Endpoint | Voices |
|---|---|---|
| Kokoro | http://localhost:8880 |
af_heart, af_bella, am_adam, etc. |
| LocalAI | http://localhost:8080 |
Model-dependent |
| AllTalk | http://localhost:7851 |
Model-dependent |
| OpenAI | https://api.openai.com |
alloy, echo, fable, onyx, nova, shimmer |
| Coqui | http://localhost:5002 |
Model-dependent |
If you want dynamic, AI-generated notification messages instead of preset ones, you can connect to a local AI server:
Install a local AI server (e.g., Ollama):
# Install Ollama and pull a model
ollama pull llama3
Enable AI messages in your config:
{
"enableAIMessages": true,
"aiEndpoint": "http://localhost:11434/v1",
"aiModel": "llama3",
"aiApiKey": "",
"aiFallbackToStatic": true,
"enableContextAwareAI": false // Set to true for personalized messages with project/task context
}
The AI will generate unique messages for each notification, which are then spoken by your TTS engine.
Context-Aware Messages (optional): Enable enableContextAwareAI for personalized notifications that include project name, task title, and change summary (e.g., "Your work on MyProject is complete!").
Supported AI Servers:
| Server | Default Endpoint | API Key |
|---|---|---|
| Ollama | http://localhost:11434/v1 |
Not needed |
| LM Studio | http://localhost:1234/v1 |
Not needed |
| LocalAI | http://localhost:8080/v1 |
Not needed |
| vLLM | http://localhost:8000/v1 |
Use "EMPTY" |
| Jan.ai | http://localhost:1337/v1 |
Required |
Receive remote notifications on Discord or any custom endpoint. This is perfect for long-running tasks when you're away from your computer.
Create a Discord Webhook:
Enable Webhooks in your config:
{
"enableWebhook": true,
"webhookUrl": "https://discord.com/api/webhooks/...",
"webhookUsername": "OpenCode Notify",
"webhookEvents": ["idle", "permission", "error", "question"],
"webhookMentionOnPermission": true
}
Features:
Supported Webhook Events:
| Event | Trigger |
|---|---|
idle |
Agent finished working |
permission |
Agent needs permission for a tool |
error |
Agent encountered an error |
question |
Agent is asking you a question |
You can replace individual sound files with entire "Sound Themes" (like the classic Warcraft II or StarCraft sound packs).
Set up your theme directory:
Create a folder (e.g., ~/.config/opencode/themes/warcraft2/) with the following structure:
warcraft2/
├── idle/ # Sounds for when the agent finishes
│ ├── job_done.mp3
│ └── alright.wav
├── permission/ # Sounds for permission requests
│ ├── help.mp3
│ └── need_orders.wav
├── error/ # Sounds for agent errors
│ └── alert.mp3
└── question/ # Sounds for agent questions
└── yes_milord.mp3
Configure the theme in your config:
{
"soundThemeDir": "themes/warcraft2",
"randomizeSoundFromTheme": true
}
Features:
randomizeSoundFromTheme is true).~/.config/opencode/).| Feature | Windows | macOS | Linux |
|---|---|---|---|
| Sound Playback | ✅ | ✅ | ✅ |
| TTS (Cloud/Edge) | ✅ | ✅ | ✅ |
| TTS (Windows SAPI) | ✅ | ❌ | ❌ |
| TTS (macOS Say) | ❌ | ✅ | ❌ |
| Desktop Notifications | ✅ | ✅ | ✅ (req libnotify) |
| Focus Detection | ✅ | ✅ | ✅ |
| Webhook Integration | ✅ | ✅ | ✅ |
| Wake Monitor | ✅ | ✅ | ✅ (X11/Gnome) |
| Volume Control | ✅ | ✅ | ✅ (Pulse/ALSA) |
/v1/audio/speech endpointpip install edge-ttssay command)notify-send (libnotify)# Ubuntu/Debian
sudo apt install libnotify-bin
# Fedora
sudo dnf install libnotify
# Arch Linux
sudo pacman -S libnotify
afplay)paplay or aplayFocus detection suppresses sound and desktop notifications when the terminal is focused. Also detects minimized or hidden terminal windows.
| Platform | Support | Notes |
|---|---|---|
| macOS | ✅ Full | Uses AppleScript to detect frontmost application |
| Windows | ✅ Full | Uses native window focus and visibility detection |
| Linux | ✅ Full | Uses xdotool / xprop (X11) or gdbus (Wayland) |
Note: If focus detection fails on any platform, notifications are still sent (fail-open behavior). TTS reminders are never suppressed, even when focused, since users may step away after seeing the toast.
| Event | Action |
|---|---|
session.idle |
Agent finished working - notify user |
session.error |
Agent encountered an error - alert user |
permission.asked |
Permission request (SDK v1.1.1+) - alert user |
permission.updated |
Permission request (SDK v1.0.x) - alert user |
permission.replied |
User responded - cancel pending reminders |
question.asked |
Agent asks question (SDK v1.1.7+) - notify user |
question.replied |
User answered question - cancel pending reminders |
question.rejected |
User dismissed question - cancel pending reminders |
message.updated |
New user message - cancel pending reminders |
session.created |
New session - reset state |
Note: The plugin supports OpenCode SDK v1.0.x, v1.1.x, and v1.1.7+ for backward compatibility.
To develop on this plugin locally:
Clone the repository:
git clone https://github.com/MasuRii/opencode-smart-voice-notify.git
cd opencode-smart-voice-notify
Install dependencies:
# Using Bun (recommended)
bun install
# Or using npm
npm install
Link to your OpenCode config:
{
"plugin": ["file:///absolute/path/to/opencode-smart-voice-notify"]
}
The plugin uses Bun's built-in test runner for unit and E2E tests.
# Run all tests
bun test
# Run tests with coverage
bun test --coverage
# Run tests in watch mode
bun test --watch
For more detailed testing guidelines and mock usage examples, see CONTRIBUTING.md.
OpenCode does not automatically update plugins. To update to the latest version:
# Clear the cached plugin
rm -rf ~/.cache/opencode/node_modules/opencode-smart-voice-notify
# Run OpenCode to trigger a fresh install
opencode
MIT
Sign in to leave a comment.