Last active
May 6, 2026 10:57
-
-
Save maoyeedy/4c2726a6b87e28ff74e4603d7ae12ec7 to your computer and use it in GitHub Desktop.
Toast when action complete with actual files modified. Windows only and requires toast.exe on path. https://github.com/shanselman/toasty
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { Plugin } from "@opencode-ai/plugin"; | |
| // Plays a small toast when OpenCode goes idle. | |
| // Customize the command, title, and messages with OPENCODE_BELL_* env vars. | |
| declare const process: { | |
| env: Record<string, string | undefined>; | |
| }; | |
| type OpenCodeEvent = { | |
| type?: string; | |
| properties?: { | |
| filesModified?: number | readonly unknown[]; | |
| files?: number | readonly unknown[]; | |
| }; | |
| }; | |
| type NotificationConfig = { | |
| command: string; | |
| title: string; | |
| taskCompleteMessage: string; | |
| idleMessage: string; | |
| }; | |
| const DEFAULT_CONFIG: NotificationConfig = { | |
| command: "toasty.exe", | |
| title: "OpenCode", | |
| taskCompleteMessage: "Task complete", | |
| idleMessage: "Idle prompt", | |
| }; | |
| function readNotificationConfig(): NotificationConfig { | |
| const env = process.env; | |
| return { | |
| command: env.OPENCODE_BELL_COMMAND?.trim() || DEFAULT_CONFIG.command, | |
| title: env.OPENCODE_BELL_TITLE?.trim() || DEFAULT_CONFIG.title, | |
| taskCompleteMessage: | |
| env.OPENCODE_BELL_TASK_COMPLETE_MESSAGE?.trim() || DEFAULT_CONFIG.taskCompleteMessage, | |
| idleMessage: env.OPENCODE_BELL_IDLE_MESSAGE?.trim() || DEFAULT_CONFIG.idleMessage, | |
| }; | |
| } | |
| function hasChanges(value: number | readonly unknown[] | undefined): boolean { | |
| if (typeof value === "number") { | |
| return value > 0; | |
| } | |
| return Array.isArray(value) && value.length > 0; | |
| } | |
| function selectNotificationMessage( | |
| files: number | readonly unknown[] | undefined, | |
| config: NotificationConfig, | |
| ): string { | |
| return hasChanges(files) ? config.taskCompleteMessage : config.idleMessage; | |
| } | |
| export const OpenCodeToast: Plugin = async ({ $ }) => { | |
| const config = readNotificationConfig(); | |
| return { | |
| event: async ({ event }) => { | |
| const e = event as OpenCodeEvent; | |
| if (e.type !== "session.idle") { | |
| return; | |
| } | |
| const props = e.properties ?? {}; | |
| const files = props.filesModified ?? props.files; | |
| const message = selectNotificationMessage(files, config); | |
| await $`${config.command} ${message} -t ${config.title}`.quiet().nothrow(); | |
| }, | |
| }; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment