opencode-notify

repository·main·Indexed 42 days ago

https://github.com/kdcokenny/opencode-notify

A plugin for OpenCode V1 that provides native OS notifications for macOS, Windows, and Linux to alert users of task completion, errors, and AI prompts. It supports custom sound configurations, quiet hours, and integration with cmux. Note: This plugin is retired and only supports OpenCode V1; OpenCode V2 users should use native terminal notification settings in cli.json.

Tokens
2.6K
Snippets
7
Records
16
Agent score
55%

What's inside opencode-notify

  1. How opencode-notify handles events

    main

    The plugin listens for specific OpenCode session events and triggers notifications based on the following logic:

    EventNotifies?SoundDescription
    Session completeYesGlassMain task is finished.
    Session errorYesBassoAn error occurred that needs attention.
    Permission neededYesSubmarineThe AI is blocked and waiting for user input.
    Question askedYesSubmarineThe AI has a direct question for the user.
    Sub-task complete/errorNo-By default, these do not notify. Set notifyChildSessions: true to enable.

    Platform-Specific Behaviors

    • macOS Focus Suppression: To prevent noise, the plugin suppresses session.idle, session.error, and permission.updated notifications if your terminal is currently the active/focused window.
    • Question Priority: Question notifications bypass macOS focus suppression to ensure direct prompts are never missed.
    • Click-to-Focus (macOS): Clicking a notification will foreground your terminal emulator.
  2. Manually install opencode-notify

    main

    If you cannot use ocx, you can manually install the plugin by copying the files into your .opencode/plugins/ directory. You must preserve the exact directory structure and manually install dependencies.

    Required File Structure

    .opencode/plugins/notify.ts
    .opencode/plugins/notify/backend.ts
    .opencode/plugins/notify/cmux.ts
    .opencode/plugins/notify/status.ts
    .opencode/plugins/notify/title.ts
    .opencode/plugins/kdco-primitives/index.ts
    .opencode/plugins/kdco-primitives/cmux.ts
    .opencode/plugins/kdco-primitives/get-project-id.ts
    .opencode/plugins/kdco-primitives/log-warn.ts
    .opencode/plugins/kdco-primitives/mutex.ts
    .opencode/plugins/kdco-primitives/shell.ts
    .opencode/plugins/kdco-primitives/temp.ts
    .opencode/plugins/kdco-primitives/terminal-detect.ts
    .opencode/plugins/kdco-primitives/types.ts
    .opencode/plugins/kdco-primitives/with-timeout.ts

    Manual Setup Steps

    1. Install Dependencies: Manually install node-notifier and detect-terminal via npm/yarn.
    2. macOS Requirement: Install alerter (e.g., brew install vjeantet/tap/alerter) and ensure it is on your PATH.
    3. cmux (Optional): Install cmux if you want to use the cmux notify path.
    4. Updates: Updates must be performed by manually re-copying the files.
  3. Configure Native OS Notification Paths

    main

    The plugin uses different backends depending on your operating system:

    • macOS: Uses alerter via the Notification Center. Requirement: You must have alerter installed and available on your PATH (e.g., brew install vjeantet/tap/alerter).
    • Windows: Uses Toast notifications via the SnoreToast backend.
    • Linux: Uses notify-send.

    cmux Integration

    If you are running inside cmux (detected via the CMUX_WORKSPACE_ID environment variable), the plugin attempts to route notifications through the cmux notify command:

    cmux notify --title "..." --subtitle "..." --body "..."

    If cmux is unavailable or the command fails, the plugin automatically falls back to the standard desktop notification paths (e.g., alerter on macOS).

  4. Install opencode-notify via OCX

    main

    To install the opencode-notify plugin for OpenCode V1, use the ocx add command pointing to the KDCO registry.

    Note: This plugin is retired and only supports OpenCode V1. For OpenCode V2, use the native terminal notification and sound settings in cli.json instead.

    To install the plugin individually:

    ocx add kdco/notify --from https://registry.kdco.dev

    To install the full kdco-workspace bundle (which includes notifications along with background agents and planning tools):

    ocx add kdco/workspace --from https://registry.kdco.dev
  5. Configure opencode-notify settings

    main

    You can customize notification behavior by creating a configuration file at ~/.config/opencode/kdco-notify.json.

    Configuration Options

    KeyTypeDefaultDescription
    notifyChildSessionsbooleanfalseIf true, includes session.idle and session.error notifications for child/sub-sessions.
    timeoutnumber0Seconds before a desktop notification disappears. 0 means no timeout. Supported on macOS and Linux (outside of cmux).
    terminalstring(auto)Override the automatically detected terminal name.
    soundsobject-Map of event types to sound names.
    quietHoursobject-Scheduled window for suppressing notifications.

    Sound Configuration

    The sounds object can map the following event keys to macOS sound names:

    • idle
    • error
    • permission
    • question (optional)

    Available macOS sounds: Basso, Blow, Bottle, Frog, Funk, Glass, Hero, Morse, Ping, Pop, Purr, Sosumi, Submarine, Tink.

    Quiet Hours

    The quietHours object requires:

    • enabled: boolean
    • start: string (e.g., "22:00")
    • end: string (e.g., "08:00")
    {
      "notifyChildSessions": false,
      "timeout": 0,
      "terminal": "ghostty",
      "sounds": {
        "idle": "Glass",
        "error": "Basso",
        "permission": "Submarine",
        "question": "Submarine"
      },
      "quietHours": {
        "enabled": false,
        "start": "22:00",
        "end": "08:00"
      }
    }
  6. Escape shell commands for different environments

    main

    The kdco-primitives module provides utility functions to ensure shell commands are safely escaped before execution, preventing injection attacks or syntax errors across different operating systems and shells.

    Available escaping utilities:

    • escapeAppleScript: For AppleScript commands.
    • escapeBash: For Bash/shell commands.
    • escapeBatch: For Windows Batch commands.
    • assertShellSafe: A validation utility to ensure a string is safe for shell execution.
  7. Handle shell command escaping with shell utilities

    main

    To ensure commands are executed safely across different operating systems and terminal environments, use the provided escaping utilities. This prevents shell injection and ensures syntax correctness for specific shells.

    Available utilities:

    • escapeAppleScript: For macOS AppleScript commands.
    • escapeBash: For Bash/Zsh environments.
    • escapeBatch: For Windows Batch environments.
    • assertShellSafe: To validate that a string is safe for shell execution.
    import { escapeBash, assertShellSafe } from "kdco-primitives";
    
    const safeCmd = escapeBash("echo 'hello world'");
    assertShellSafe(safeCmd);
  8. Detect and manage Cmux terminal contexts

    main

    The primitives provide tools to detect if the current environment is running within a cmux workflow. This is useful for determining how notifications should be routed or displayed.

    Key exports:

    • detectCmuxContext: Identifies the current CmuxContext.
    • canUseCmuxWorkflow: Boolean check for Cmux compatibility.
    • CmuxContext: Type representing the detected context.
    • CmuxEnvironment: Type representing the environment type.
    import { detectCmuxContext, canUseCmuxWorkflow } from "kdco-primitives";
    
    if (canUseCmuxWorkflow()) {
      const context = detectCmuxContext();
      // Handle cmux-specific logic
    }
  9. Retrieve project and system information

    main

    Use the following utilities to gather context about the current environment:

    • getProjectId: Retrieves the unique identifier for the current project.
    • getTempDir: Retrieves the appropriate temporary directory path for the current OS.
    • isInsideTmux: Detects if the current terminal session is running inside a tmux multiplexer.
  10. Execute operations with timeouts using withTimeout

    main

    To prevent long-running notification or shell tasks from hanging, wrap them in the withTimeout utility. If the operation exceeds the specified duration, it will throw a TimeoutError.

    import { withTimeout, TimeoutError } from "kdco-primitives";
    
    try {
      await withTimeout(async () => {
        // Perform notification or shell task
      }, 5000); // 5 second timeout
    } catch (e) {
      if (e instanceof TimeoutError) {
        console.error("Task timed out");
      }
    }