opencode-plugin-boops 1.0.0 → 2.0.2
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.
- package/README.md +251 -38
- package/boops.default.toml +70 -0
- package/cli/browse +2122 -0
- package/index.ts +389 -36
- package/package.json +19 -2
- package/sounds.json +23289 -0
package/README.md
CHANGED
|
@@ -4,18 +4,28 @@ Sound notifications for OpenCode - plays pleasant "boop" sounds when tasks compl
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- 🎵
|
|
8
|
-
- 📡
|
|
9
|
-
-
|
|
7
|
+
- 🎵 Soft, friendly notification sounds when AI completes tasks
|
|
8
|
+
- 📡 Gentle alert when AI needs your permission or input
|
|
9
|
+
- 🌐 Works out of the box with online sounds (auto-downloaded and cached)
|
|
10
|
+
- 🔄 Fully configurable - use URLs or local files
|
|
10
11
|
- 🐧 Works on Linux (with `paplay` or `aplay`)
|
|
11
|
-
- 🍎 Works on macOS (
|
|
12
|
+
- 🍎 Works on macOS (with `afplay`)
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
Add to your OpenCode config file:
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
**Global installation** (recommended):
|
|
19
|
+
```bash
|
|
20
|
+
# Edit ~/.config/opencode/opencode.json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Per-project installation**:
|
|
24
|
+
```bash
|
|
25
|
+
# Edit opencode.json in your project root
|
|
26
|
+
```
|
|
18
27
|
|
|
28
|
+
Add the plugin to the config:
|
|
19
29
|
```json
|
|
20
30
|
{
|
|
21
31
|
"$schema": "https://opencode.ai/config.json",
|
|
@@ -23,51 +33,238 @@ Add to your `opencode.json` or `~/.config/opencode/opencode.json`:
|
|
|
23
33
|
}
|
|
24
34
|
```
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
Then restart OpenCode. The plugin will be automatically downloaded and installed from npm.
|
|
27
37
|
|
|
28
|
-
|
|
38
|
+
### Quick setup
|
|
39
|
+
|
|
40
|
+
If you don't have an OpenCode config yet:
|
|
29
41
|
|
|
30
42
|
```bash
|
|
31
|
-
#
|
|
32
|
-
mkdir -p ~/.config/opencode
|
|
33
|
-
|
|
43
|
+
# Create global config
|
|
44
|
+
mkdir -p ~/.config/opencode
|
|
45
|
+
echo '{"$schema":"https://opencode.ai/config.json","plugin":["opencode-plugin-boops"]}' > ~/.config/opencode/opencode.json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or for a specific project:
|
|
34
49
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
```bash
|
|
51
|
+
# In your project directory
|
|
52
|
+
echo '{"$schema":"https://opencode.ai/config.json","plugin":["opencode-plugin-boops"]}' > opencode.json
|
|
38
53
|
```
|
|
39
54
|
|
|
40
55
|
## How it works
|
|
41
56
|
|
|
42
|
-
The plugin listens to OpenCode events:
|
|
57
|
+
The plugin listens to OpenCode events and plays sounds based on your configuration. By default, it uses online sounds that are automatically downloaded and cached:
|
|
58
|
+
|
|
59
|
+
- **`session.idle`** - AI finishes responding → soft "pristine" notification
|
|
60
|
+
- **`permission.asked`** - AI needs permission → gentle "relax" chime
|
|
61
|
+
- **`session.error`** - An error occurs → friendly "magic" alert
|
|
62
|
+
|
|
63
|
+
Sounds are downloaded once on first use and cached in `~/.cache/opencode/boops/` for instant playback.
|
|
64
|
+
|
|
65
|
+
## Configuration
|
|
66
|
+
|
|
67
|
+
The plugin automatically creates a configuration file at `~/.config/opencode/plugins/boops/boops.toml` on first install.
|
|
68
|
+
|
|
69
|
+
### Customize your config
|
|
70
|
+
|
|
71
|
+
The config is automatically created from `boops.default.toml` when you install the plugin. Edit it to customize your sounds:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Edit your config
|
|
75
|
+
$EDITOR ~/.config/opencode/plugins/boops/boops.toml
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Example configuration:
|
|
79
|
+
|
|
80
|
+
```toml
|
|
81
|
+
# ~/.config/opencode/plugins/boops/boops.toml
|
|
43
82
|
|
|
44
|
-
|
|
45
|
-
|
|
83
|
+
[sounds]
|
|
84
|
+
# Use sound names from sounds.json (recommended)
|
|
85
|
+
"session.idle" = "pristine"
|
|
86
|
+
"permission.asked" = "relax"
|
|
87
|
+
"session.error" = "magic"
|
|
46
88
|
|
|
47
|
-
|
|
89
|
+
# Or use full URLs:
|
|
90
|
+
# "session.idle" = "https://example.com/sound.ogg"
|
|
48
91
|
|
|
49
|
-
|
|
92
|
+
# Or use local file paths:
|
|
93
|
+
# "session.idle" = "/usr/share/sounds/gnome/default/alerts/drip.ogg"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Sound sources
|
|
50
97
|
|
|
51
|
-
|
|
98
|
+
The plugin supports multiple ways to specify sounds:
|
|
52
99
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
100
|
+
**1. Sound names from sounds.json (easiest):**
|
|
101
|
+
```toml
|
|
102
|
+
"session.idle" = "pristine"
|
|
103
|
+
"permission.asked" = "relax"
|
|
104
|
+
"session.error" = "magic"
|
|
56
105
|
```
|
|
57
106
|
|
|
58
|
-
|
|
107
|
+
Use the TUI browser (`~/.config/opencode/plugins/boops/browse`) to explore all 448 sounds with semantic tags!
|
|
59
108
|
|
|
60
|
-
|
|
109
|
+
**2. Full URLs:**
|
|
110
|
+
```toml
|
|
111
|
+
"session.idle" = "https://example.com/sound.ogg"
|
|
112
|
+
```
|
|
61
113
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
114
|
+
**3. Local file paths:**
|
|
115
|
+
```toml
|
|
116
|
+
"session.idle" = "/usr/share/sounds/gnome/default/alerts/drip.ogg"
|
|
65
117
|
```
|
|
66
118
|
|
|
67
|
-
|
|
119
|
+
**Caching:** Remote sounds (IDs and URLs) are cached in `~/.cache/opencode/boops/` by event name (e.g. `session-idle`, `permission-asked`). Once downloaded, they're reused instantly. If you change a sound, the cache is automatically updated on next play.
|
|
120
|
+
|
|
121
|
+
### Available events
|
|
122
|
+
|
|
123
|
+
You can configure sounds for any of the 28 OpenCode events:
|
|
124
|
+
|
|
125
|
+
**Session events (8):**
|
|
126
|
+
- `session.idle` - AI completes response
|
|
127
|
+
- `session.error` - Error occurs
|
|
128
|
+
- `session.created` - New session starts
|
|
129
|
+
- `session.deleted` - Session deleted
|
|
130
|
+
- `session.compacted` - Session compacted
|
|
131
|
+
- `session.diff` - Session diff generated
|
|
132
|
+
- `session.status` - Session status changed
|
|
133
|
+
- `session.updated` - Session updated
|
|
134
|
+
|
|
135
|
+
**Permission events (2):**
|
|
136
|
+
- `permission.asked` - AI needs permission
|
|
137
|
+
- `permission.replied` - Permission response given
|
|
138
|
+
|
|
139
|
+
**File events (2):**
|
|
140
|
+
- `file.edited` - File is edited
|
|
141
|
+
- `file.watcher.updated` - File watcher detects change
|
|
142
|
+
|
|
143
|
+
**Tool events (2):**
|
|
144
|
+
- `tool.execute.before` - Before tool execution
|
|
145
|
+
- `tool.execute.after` - After tool execution
|
|
146
|
+
|
|
147
|
+
**Message events (4):**
|
|
148
|
+
- `message.part.removed` - Message part removed
|
|
149
|
+
- `message.part.updated` - Message part updated
|
|
150
|
+
- `message.removed` - Message removed
|
|
151
|
+
- `message.updated` - Message updated
|
|
68
152
|
|
|
69
|
-
|
|
70
|
-
|
|
153
|
+
**LSP events (2):**
|
|
154
|
+
- `lsp.client.diagnostics` - LSP diagnostics received
|
|
155
|
+
- `lsp.updated` - LSP server updated
|
|
156
|
+
|
|
157
|
+
**TUI events (3):**
|
|
158
|
+
- `tui.prompt.append` - Text appended to prompt
|
|
159
|
+
- `tui.command.execute` - TUI command executed
|
|
160
|
+
- `tui.toast.show` - Toast notification shown
|
|
161
|
+
|
|
162
|
+
**Other events (5):**
|
|
163
|
+
- `command.executed` - Command executed
|
|
164
|
+
- `todo.updated` - Todo list updated
|
|
165
|
+
- `installation.updated` - Installation/package updated
|
|
166
|
+
- `server.connected` - Connected to server
|
|
167
|
+
|
|
168
|
+
See the [default config](boops.default.toml) for the complete list with descriptions.
|
|
169
|
+
|
|
170
|
+
### Event filters
|
|
171
|
+
|
|
172
|
+
For advanced use cases, you can add filters to play sounds only when certain conditions match. This is useful for events that fire frequently or in different contexts.
|
|
173
|
+
|
|
174
|
+
**Example: Only play sound for main session, not subagents:**
|
|
175
|
+
|
|
176
|
+
```toml
|
|
177
|
+
[sounds.session.idle]
|
|
178
|
+
sound = "pristine"
|
|
179
|
+
not_if = { agent = "explore" } # Skip subagent completions
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**How to find available properties:**
|
|
183
|
+
|
|
184
|
+
1. Check OpenCode logs when the event fires:
|
|
185
|
+
```bash
|
|
186
|
+
tail -f ~/.local/share/opencode/log/*.log | grep "session.idle event"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
2. The logs will show all event properties you can filter on
|
|
190
|
+
|
|
191
|
+
**Filter syntax:**
|
|
192
|
+
|
|
193
|
+
```toml
|
|
194
|
+
[sounds.event-name]
|
|
195
|
+
sound = "/path/to/sound"
|
|
196
|
+
only_if = { property = "value" } # Only play if property equals value
|
|
197
|
+
not_if = { property = "value" } # Don't play if property equals value
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Testing sounds
|
|
201
|
+
|
|
202
|
+
You can test sounds without restarting OpenCode using the custom tool:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Test a configured event (reloads config automatically)
|
|
206
|
+
test-sound session.idle
|
|
207
|
+
|
|
208
|
+
# Test a sound ID directly
|
|
209
|
+
# Test by sound name
|
|
210
|
+
test-sound pristine
|
|
211
|
+
test-sound "access granted computer voice"
|
|
212
|
+
|
|
213
|
+
# Test a URL directly
|
|
214
|
+
test-sound https://example.com/sound.ogg
|
|
215
|
+
|
|
216
|
+
# Test a local file directly
|
|
217
|
+
test-sound /usr/share/sounds/alert.ogg
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
This is helpful when:
|
|
221
|
+
- Configuring new sounds
|
|
222
|
+
- Trying different sound files before committing to config
|
|
223
|
+
- Testing event filters
|
|
224
|
+
- Verifying URLs/IDs work
|
|
225
|
+
|
|
226
|
+
The test command automatically reloads your config file, so you can edit `boops.toml` and test immediately!
|
|
227
|
+
|
|
228
|
+
### Browse sounds interactively
|
|
229
|
+
|
|
230
|
+
The plugin includes a beautiful TUI for browsing and assigning sounds:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# If plugin is installed
|
|
234
|
+
~/.config/opencode/plugins/boops/browse
|
|
235
|
+
|
|
236
|
+
# Or try it with npx (browse-only, saving disabled)
|
|
237
|
+
npx opencode-plugin-boops browse
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Features:
|
|
241
|
+
- 🎨 Browse 448 sounds with tags and descriptions
|
|
242
|
+
- 🏷️ Filter by tags (music, bell, quiet, etc.)
|
|
243
|
+
- 🔍 Search by name
|
|
244
|
+
- 🎵 Preview sounds before assigning
|
|
245
|
+
- ⚡ Assign sounds to OpenCode events (if plugin installed)
|
|
246
|
+
- 🖱️ Full mouse support with hover effects
|
|
247
|
+
- ⌨️ Keyboard navigation
|
|
248
|
+
|
|
249
|
+
**Note**: When running via `npx`, you can browse and preview sounds, but saving assignments requires the plugin to be installed.
|
|
250
|
+
|
|
251
|
+
### Custom sound player
|
|
252
|
+
|
|
253
|
+
By default, the plugin auto-detects `paplay` (PulseAudio), `aplay` (ALSA), or `afplay` (macOS). You can override this:
|
|
254
|
+
|
|
255
|
+
```toml
|
|
256
|
+
player = "afplay" # Force specific player
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### macOS example
|
|
260
|
+
|
|
261
|
+
```toml
|
|
262
|
+
player = "afplay"
|
|
263
|
+
|
|
264
|
+
[sounds]
|
|
265
|
+
"session.idle" = "/System/Library/Sounds/Glass.aiff"
|
|
266
|
+
"permission.asked" = "/System/Library/Sounds/Ping.aiff"
|
|
267
|
+
"session.error" = "/System/Library/Sounds/Basso.aiff"
|
|
71
268
|
```
|
|
72
269
|
|
|
73
270
|
## Requirements
|
|
@@ -75,28 +272,40 @@ await Bun.$`afplay ${primaryFile}`.quiet()
|
|
|
75
272
|
- OpenCode 1.0+
|
|
76
273
|
- Linux: `paplay` (PulseAudio) or `aplay` (ALSA)
|
|
77
274
|
- macOS: `afplay` (built-in)
|
|
78
|
-
-
|
|
275
|
+
- Internet connection (only for initial sound download)
|
|
79
276
|
|
|
80
277
|
## Troubleshooting
|
|
81
278
|
|
|
82
279
|
### No sound playing
|
|
83
280
|
|
|
84
|
-
1.
|
|
281
|
+
1. **Use the test command first:**
|
|
85
282
|
```bash
|
|
86
|
-
|
|
87
|
-
ls /usr/share/sounds/gnome/default/alerts/sonar.ogg
|
|
283
|
+
test-sound event="session.idle"
|
|
88
284
|
```
|
|
89
285
|
|
|
90
|
-
2.
|
|
286
|
+
2. **Check if sound player is installed:**
|
|
91
287
|
```bash
|
|
92
|
-
paplay
|
|
288
|
+
which paplay # Linux (PulseAudio)
|
|
289
|
+
which aplay # Linux (ALSA)
|
|
290
|
+
which afplay # macOS
|
|
93
291
|
```
|
|
94
292
|
|
|
95
|
-
3. Check OpenCode logs
|
|
293
|
+
3. **Check OpenCode logs:**
|
|
96
294
|
```bash
|
|
97
295
|
tail -f ~/.local/share/opencode/log/*.log | grep boops
|
|
98
296
|
```
|
|
99
297
|
|
|
298
|
+
4. **Check cached sounds:**
|
|
299
|
+
```bash
|
|
300
|
+
ls -la ~/.cache/opencode/boops/
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
5. **Clear cache and re-download:**
|
|
304
|
+
```bash
|
|
305
|
+
rm -rf ~/.cache/opencode/boops/
|
|
306
|
+
# Then use test-sound to re-download
|
|
307
|
+
```
|
|
308
|
+
|
|
100
309
|
### Sounds too loud/quiet
|
|
101
310
|
|
|
102
311
|
Adjust your system volume or use different sound files.
|
|
@@ -109,6 +318,10 @@ Contributions welcome! Feel free to:
|
|
|
109
318
|
- Improve cross-platform compatibility
|
|
110
319
|
- Add more event triggers
|
|
111
320
|
|
|
321
|
+
## Credits
|
|
322
|
+
|
|
323
|
+
Sounds from [Notification Sounds](https://notificationsounds.com) - a wonderful collection of free notification sounds provided under Creative Commons Attribution license.
|
|
324
|
+
|
|
112
325
|
## License
|
|
113
326
|
|
|
114
327
|
MIT
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# OpenCode Boops Plugin Configuration
|
|
2
|
+
# Sounds can be local file paths OR URLs (automatically downloaded and cached)
|
|
3
|
+
|
|
4
|
+
# player = "paplay" # Auto-detected if not set (paplay/aplay/afplay)
|
|
5
|
+
|
|
6
|
+
[sounds]
|
|
7
|
+
"session.idle" = "pristine" # AI completes response
|
|
8
|
+
"permission.asked" = "relax" # AI needs permission
|
|
9
|
+
"session.error" = "magic" # Error occurs
|
|
10
|
+
|
|
11
|
+
# You can use:
|
|
12
|
+
# - Sound names: "pristine" (searches sounds.json by name)
|
|
13
|
+
# - Full URLs: "https://example.com/sound.ogg"
|
|
14
|
+
# - Local paths: "/usr/share/sounds/..."
|
|
15
|
+
|
|
16
|
+
# Advanced: Event filters (play sound only when conditions match)
|
|
17
|
+
# Uncomment and adjust after checking logs to see available properties
|
|
18
|
+
# [sounds.session.idle]
|
|
19
|
+
# sound = "pristine"
|
|
20
|
+
# not_if = { agent = "explore" } # Don't play for subagent completions
|
|
21
|
+
|
|
22
|
+
# Optional events (uncomment to enable):
|
|
23
|
+
# Command events
|
|
24
|
+
# "command.executed" = "/path/to/sound" # Command executed
|
|
25
|
+
|
|
26
|
+
# File events
|
|
27
|
+
# "file.edited" = "/path/to/sound" # File edited
|
|
28
|
+
# "file.watcher.updated" = "/path/to/sound" # File watcher detected change
|
|
29
|
+
|
|
30
|
+
# Installation events
|
|
31
|
+
# "installation.updated" = "/path/to/sound" # Installation/package updated
|
|
32
|
+
|
|
33
|
+
# LSP events
|
|
34
|
+
# "lsp.client.diagnostics" = "/path/to/sound" # LSP diagnostics received
|
|
35
|
+
# "lsp.updated" = "/path/to/sound" # LSP server updated
|
|
36
|
+
|
|
37
|
+
# Message events
|
|
38
|
+
# "message.part.removed" = "/path/to/sound" # Message part removed
|
|
39
|
+
# "message.part.updated" = "/path/to/sound" # Message part updated
|
|
40
|
+
# "message.removed" = "/path/to/sound" # Message removed
|
|
41
|
+
# "message.updated" = "/path/to/sound" # Message updated
|
|
42
|
+
|
|
43
|
+
# Permission events
|
|
44
|
+
# "permission.replied" = "/path/to/sound" # Permission response given
|
|
45
|
+
|
|
46
|
+
# Server events
|
|
47
|
+
# "server.connected" = "/path/to/sound" # Connected to server
|
|
48
|
+
|
|
49
|
+
# Session events
|
|
50
|
+
# "session.created" = "/path/to/sound" # New session created
|
|
51
|
+
# "session.compacted" = "/path/to/sound" # Session compacted
|
|
52
|
+
# "session.deleted" = "/path/to/sound" # Session deleted
|
|
53
|
+
# "session.diff" = "/path/to/sound" # Session diff generated
|
|
54
|
+
# "session.status" = "/path/to/sound" # Session status changed
|
|
55
|
+
# "session.updated" = "/path/to/sound" # Session updated
|
|
56
|
+
|
|
57
|
+
# Todo events
|
|
58
|
+
# "todo.updated" = "/path/to/sound" # Todo list updated
|
|
59
|
+
|
|
60
|
+
# Tool events
|
|
61
|
+
# "tool.execute.before" = "/path/to/sound" # Before tool execution
|
|
62
|
+
# "tool.execute.after" = "/path/to/sound" # After tool execution
|
|
63
|
+
|
|
64
|
+
# TUI events
|
|
65
|
+
# "tui.prompt.append" = "/path/to/sound" # Text appended to prompt
|
|
66
|
+
# "tui.command.execute" = "/path/to/sound" # TUI command executed
|
|
67
|
+
# "tui.toast.show" = "/path/to/sound" # Toast notification shown
|
|
68
|
+
|
|
69
|
+
[fallbacks]
|
|
70
|
+
# default = "/usr/share/sounds/alsa/Front_Center.wav" # Optional: local fallback if download fails
|