跳到主要内容
    ↑↓ 选择↵ 打开esc 关闭
    中文English
    lannuttia

    Ntfy.Sh

    v1.1.0通知与集成
    opencode-ntfy.sh

    OpenCode plugin that sends push notifications via ntfy.sh

    GitHub 星标

    34

    月装机量

    354

    近 7 天 57

    综合评分SCORE

    47.6

    生态多维模型

    最近提交

    19 天前

    2026-08-01

    快速安装与配置

    opencode.json

    写入当前项目的 opencode.json,只对这个仓库生效。

    opencode.json

    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": ["opencode-ntfy.sh@1.1.0"]
    }

    opencode 启动时会通过内嵌运行时自动加载 npm 依赖并缓存至本地目录,无需手动在全局环境执行安装。

    CI codecov License: MIT Snyk Vulnerabilities

    An OpenCode notification backend plugin for ntfy.sh. Built on the opencode-notification-sdk, this plugin delivers push notifications to your phone or desktop when your AI coding session finishes, encounters an error, or needs permission. Start a long-running task, walk away, and get notified when it needs your attention.

    How It Works

    This plugin is a notification backend for the opencode-notification-sdk. The SDK handles common notification logic:

    • Event routing -- classifying OpenCode events into notification types
    • Subagent suppression -- silently suppressing notifications from sub-agent (child) sessions for session.idle and session.error events
    • Configuration loading -- reading and parsing the config file, handling the enabled and events sections

    This plugin is responsible for the ntfy.sh-specific concerns: producing notification content (title and message), formatting and sending the HTTP POST request, validating ntfy-specific configuration, and resolving the notification icon URL.

    Notifications

    The plugin sends notifications for three events:

    • Session Idle -- The AI agent has finished its work and is waiting for input.
    • Session Error -- The session encountered an error.
    • Permission Asked -- The agent needs permission to perform an action.

    Default Tags

    Each event type has a default tag corresponding to an emoji shortcode supported by ntfy.sh:

    Event Default Tag Emoji
    session.idle hourglass_done
    session.error warning ⚠️
    permission.asked lock 🔒

    Install

    Add the package name to the plugin array in your OpenCode config file.

    opencode.json:

    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": ["opencode-ntfy.sh"]
    }
    

    Configuration

    Configuration is done through a JSON file at ~/.config/opencode/notification-ntfy.json.

    You can reference the bundled JSON Schema for editor autocompletion and validation by adding a $schema property:

    {
      "$schema": "node_modules/opencode-ntfy.sh/notification-ntfy.schema.json",
      "backend": {
        "topic": "my-notifications"
      }
    }
    

    Full Configuration Structure

    The config file follows the SDK's configuration schema at the top level, with ntfy-specific settings under the backend key.

    Property Type Required Default Description
    enabled boolean No true Global kill switch for all notifications (handled by SDK).
    events object No (all enabled) Per-event enable/disable toggles (handled by SDK).
    events.<type>.enabled boolean No true Whether this event type triggers notifications (handled by SDK).
    backend object No {} ntfy.sh-specific configuration (see below).

    Backend Configuration Properties

    The backend object contains all ntfy.sh-specific settings:

    Property Type Required Default Description
    backend.topic string Yes -- The ntfy.sh topic to publish to.
    backend.server string No https://ntfy.sh The ntfy server URL.
    backend.token string No -- Bearer token for authentication.
    backend.priority string No default Notification priority (min, low, default, high, max).
    backend.icon object No -- Icon configuration object.
    backend.icon.mode string No dark Whether the target device uses light or dark mode.
    backend.icon.variant object No -- Custom icon URL overrides per mode variant.
    backend.icon.variant.light string No -- Custom icon URL override for light mode.
    backend.icon.variant.dark string No -- Custom icon URL override for dark mode.
    backend.fetchTimeout string No -- ISO 8601 duration for the HTTP request timeout (e.g., PT10S).
    backend.title object No (see defaults) Title configuration per event type.
    backend.title.<event> object No (see defaults) Content template for the notification title. Must contain exactly one of value or command.
    backend.title.<event>.value string No -- A template string rendered with {var_name} substitution.
    backend.title.<event>.command string No -- A template string rendered and executed as a shell command; stdout is used as the title.
    backend.message object No (see defaults) Message configuration per event type.
    backend.message.<event> object No (see defaults) Content template for the notification message. Must contain exactly one of value or command.
    backend.message.<event>.value string No -- A template string rendered with {var_name} substitution.
    backend.message.<event>.command string No -- A template string rendered and executed as a shell command; stdout is used as the message.

    Variable Substitution

    All string values in the config file support two placeholder syntaxes, expanded by the SDK before validation:

    • {env:VAR_NAME} -- replaced with the value of the corresponding environment variable. If the variable is not set, the placeholder is replaced with an empty string.
    • {file:path/to/file} -- replaced with the trimmed contents of the specified file. Paths can be absolute (/), home-relative (~), or relative to the config file's directory. If the file does not exist or cannot be read, the placeholder is replaced with an empty string.

    This allows sensitive values like topics and tokens to be externalized, making the config safe to commit to version control:

    {
      "backend": {
        "topic": "{env:NTFY_TOPIC}",
        "token": "{file:~/.secrets/ntfy-token}"
      }
    }
    

    Notification Content

    The notification title and message are configurable per event type via backend.title and backend.message. Each key is an event type (session.idle, session.error, permission.asked), and the value specifies how to produce the content:

    • value -- A template string with {var_name} placeholders, resolved via the SDK's renderTemplate. No shell execution.
    • command -- A template string with {var_name} placeholders, resolved and then executed as a shell command. The trimmed stdout is used as the content.

    Each per-event object must contain exactly one of value or command.

    Available Template Variables

    Variable Description
    {event} Event type (e.g., session.idle)
    {time} ISO 8601 timestamp
    {project} Project directory basename
    {session_id} Session ID (empty if unavailable)
    {error} Error message (empty if not an error event)
    {permission_type} Permission type (empty if not a permission event)
    {permission_patterns} Comma-separated patterns (empty if not a permission event)

    Default Values

    When no title or message template is configured for an event type, these defaults are used:

    Event Default Title Default Message
    session.idle Agent Idle The agent has finished and is waiting for input.
    session.error Agent Error An error has occurred. Check the session for details.
    permission.asked Permission Asked The agent needs permission to continue. Review and respond.

    Example Configurations

    Minimal configuration (~/.config/opencode/notification-ntfy.json):

    {
      "backend": {
        "topic": "my-opencode-notifications"
      }
    }
    

    With authentication and a self-hosted server:

    {
      "backend": {
        "topic": "my-opencode-notifications",
        "server": "https://ntfy.example.com",
        "token": "tk_mytoken",
        "priority": "high"
      }
    }
    

    Full configuration:

    {
      "enabled": true,
      "events": {
        "session.idle": { "enabled": true },
        "session.error": { "enabled": true },
        "permission.asked": { "enabled": true }
      },
      "backend": {
        "topic": "{env:NTFY_TOPIC}",
        "server": "https://ntfy.sh",
        "priority": "default",
        "token": "{file:~/.secrets/ntfy-token}",
        "title": {
          "session.idle": { "value": "{project}: Agent Idle" },
          "session.error": { "value": "{project}: Agent Error" }
        },
        "message": {
          "session.error": { "value": "Error in {project}: {error}" }
        },
        "icon": {
          "mode": "dark"
        },
        "fetchTimeout": "PT10S"
      }
    }
    

    With command templates:

    {
      "backend": {
        "topic": "my-notifications",
        "title": {
          "session.idle": { "command": "echo Agent finished in {project}" }
        },
        "message": {
          "permission.asked": { "command": "echo Permission {permission_type} requested" }
        }
      }
    }
    

    Subscribing to Notifications

    To receive notifications, subscribe to your topic using any ntfy client:

    • Phone: Install the ntfy app (Android, iOS) and subscribe to your topic.
    • Desktop: Open https://ntfy.sh/<your-topic> in a browser.
    • CLI: curl -s ntfy.sh/<your-topic>/json

    Development

    Prerequisites

    Setup

    git clone https://github.com/lannuttia/opencode-ntfy.sh.git
    cd opencode-ntfy.sh
    bun install
    

    Build

    bun run build
    

    This compiles TypeScript from src/ to dist/ via tsc.

    Test

    bun run test
    

    Or in watch mode:

    bun run test:watch
    

    License

    MIT