This guide shows how to create an OpenCode CLI plugin that plays an audio notification when OpenCode needs user permissions. The solution consists of two components:
- A shell script to play system audio
- An OpenCode plugin that listens for the
permission.askedevent
Create ~/opencode-notify.sh:
#!/bin/bash
# Plays system notification sound
if command -v aplay &> /dev/null; then
# Linux (ALSA)
aplay /usr/share/sounds/freedesktop/stereo/message.oga
elif command -v afplay &> /dev/null; then
# macOS
afplay /System/Library/Sounds/Glass.aiff
elif command -v powershell.exe &> /dev/null; then
# WSL2 on Windows
powershell.exe -c "[System.Media.SystemSounds]::Asterisk.Play()" 2>/dev/null
fiMake it executable:
chmod +x ~/opencode-notify.shTest it:
~/opencode-notify.shmkdir -p ~/.config/opencode/pluginCreate ~/.config/opencode/plugin/notify.js:
import { exec } from "child_process";
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
if (event.type === "permission.asked") {
exec("~/opencode-notify.sh");
}
},
};
};Restart OpenCode. Verify plugin loading:
opencode debug configYou should see:
{
"plugin": [
"file:///home/<user>/.config/opencode/plugin/notify.js"
]
}SEE: https://opencode.ai/docs/plugins/
Extend your plugin to handle multiple events:
export const NotificationPlugin = async (ctx) => {
return {
event: async ({ event }) => {
// Permission requested
if (event.type === "permission.asked") {
exec("~/opencode-notify.sh");
}
// Session idle
if (event.type === "session.idle") {
exec("~/opencode-notify.sh");
}
// Prompt appended
if (event.type === "tui.prompt.append") {
exec("~/opencode-notify.sh");
}
},
};
};Test your notification script:
~/opencode-notify.shCheck plugin syntax:
node -c ~/.config/opencode/plugin/notify.jsAdd debug logging:
import { appendFileSync } from "fs";
const LOG_FILE = "/home/<user>/opencode-notify.log";
export const NotificationPlugin = async (ctx) => {
return {
event: async ({ event }) => {
appendFileSync(LOG_FILE, `${new Date().toISOString()} - ${event.type}\n`);
if (event.type === "permission.asked") {
exec("~/opencode-notify.sh");
}
},
};
};- OpenCode fires the
permission.askedevent when requiring permission - The plugin receives the event and executes
~/opencode-notify.sh - The script plays the appropriate system notification sound
- You get alerted acoustically even when the terminal is in the background
Visual Notification with MessageBox:
#!/bin/bash
powershell.exe -c "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('OpenCode needs your attention', 'OpenCode')"Combine Audio + Visual:
#!/bin/bash
powershell.exe -c "[System.Media.SystemSounds]::Asterisk.Play()"
powershell.exe -c "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('OpenCode needs your attention', 'OpenCode')"