Desktop notifications for OpenCode that stay quiet when auto-approve already handled the request.
--auto and Enable auto-approve permissions still emit permission events. Other notifiers pop on every ask. This plugin waits a short settle window and only notifies if the request is still waiting.
Linux, macOS, and Windows. Use 0.1.1 or later — 0.1.0 does not load.
| Event | Notification |
|---|---|
| Permission request still pending after the settle window | opencode request |
| Auto-approved / already-replied request | none |
User question (askuserquestion) |
opencode question |
| Session error | opencode error |
Agent finished (session.status idle) |
opencode idle |
ESC / MessageAbortedError |
none |
| Subagent / child-session events | none unless notifySubagents |
A request popup already on screen is retracted when permission.replied arrives (Linux and Windows). macOS Notification Center cannot dismiss a posted banner from a script.
Clicking a notification focuses running Zed (zed://), else a running OpenCode TUI. It does not start Zed and does not send zed://agent. Override with clickCommand if you need a different handler.
The package ships TypeScript. OpenCode loads it with Bun; there is no dist/ build.
Add the plugin to ~/.config/opencode/opencode.json or opencode.jsonc:
OpenCode installs it from the npm registry on startup.
With options:
{
"plugin": [["opencode-smart-notify@0.3.1", { "notifyErrors": false }]]
}Restart OpenCode after changing plugin config.
Do not run this alongside opencode-notify or you will get duplicate popups.
{
"plugin": ["github:gabparrot/opencode-smart-notify#v0.3.1"]
}Local checkout:
{
"plugin": ["file:///absolute/path/to/opencode-smart-notify/src/index.ts"]
}Do not copy only src/index.ts into ~/.config/opencode/plugins/ — the plugin is several files.
permission.asked/permission.updatedstarts a 250ms settle timer. Both events are the same request when they share an ID.permission.repliedcancels that timer, records the ID (so a late ask stays silent), and retracts a popup already on screen.- If the timer fires, the request is still waiting on you, so a notification is sent.
MessageAbortedErroris ignored. It is not anopencode errorpopup.- After a user message or
session.statusbusy,session.statusidle /session.idlesendsopencode idle. ESC, a real error, or an idle with no prior turn stays silent. Title or background work does not retract that popup or send a second one. A new user message starts the next turn. - Child sessions (
Session.parentIDset, Task metadata, or a(@… subagent)title) are skipped by default. Existing children are hydrated from the session list on start. Parent idle still notifies when the parent finishes. - Clicking a popup focuses running Zed (
zed://), else a running OpenCode TUI. The GNOME/Wayland activation token is used when the compositor sends one; TUI raise is compositor best-effort (hyprctl / sway / niri / DBusActivatable terminal / wmctrl). It does not start Zed and does not openzed://agent.
That covers opencode --auto, the TUI auto-approve toggle, and any other path that replies before you need to look.
Optional ~/.config/opencode/opencode-smart-notify.json. Plugin tuple options in opencode.json override the file.
| Option | Default | Meaning |
|---|---|---|
settleMs |
250 |
Wait this long before a permission popup |
notifyRequests |
true |
Permission requests |
notifyQuestions |
true |
askuserquestion |
notifyErrors |
true |
Session errors (not cancel) |
notifyIdle |
true |
Agent finished (session.status idle) |
notifySubagents |
false |
Task / child-session events |
urgency |
"critical" |
low, normal, or critical |
clickCommand |
(auto) | Argv run on click. {sessionId} is substituted. Default: focus Zed if running, else focus OpenCode TUI |
{
"plugin": [["opencode-smart-notify@0.3.1", { "notifyErrors": false }]]
}- OpenCode
- Linux:
notify-sendonPATH(libnotify-binon Debian/Ubuntu) - macOS: Notification Center (
osascript, built in) - Windows 10/11: inbox
powershell.exe(Windows PowerShell 5.1). No extra PowerShell install.
{ "plugin": ["opencode-smart-notify@0.3.1"] }