npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-bark

v0.0.1

Published

OpenCode plugin that sends push notifications via Bark

Readme

opencode-bark

CI codecov License: MIT

An OpenCode notification backend plugin for Bark. Built on the opencode-notification-sdk, this plugin delivers push notifications to your iPhone when your AI coding session finishes, encounters an error, or needs permission.

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 Bark-specific concerns: producing notification content (title and message), formatting and sending the HTTP POST request, validating Bark-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 Titles

| Event | Default Title | |---|---| | session.idle | 任务完成 | | session.error | 任务失败 | | permission.asked | 需要确认 |

Install

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

opencode.json:

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

Configuration

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

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

{
  "$schema": "node_modules/opencode-bark/notification-bark.schema.json",
  "backend": {
    "deviceKey": "your-device-key"
  }
}

Full Configuration Structure

The config file follows the SDK's configuration schema at the top level, with Bark-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 | {} | Bark-specific configuration (see below). |

Backend Configuration Properties

The backend object contains all Bark-specific settings:

| Property | Type | Required | Default | Description | |---|---|---|---|---| | backend.deviceKey | string | Yes | -- | The Bark device key to send notifications to. | | backend.server | string | No | https://api.day.app | The Bark server URL. | | backend.group | string | No | opencode | The notification group name. | | backend.sound | string | No | default | The notification sound. | | 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.url | string | No | -- | URL to open when the notification is clicked. | | 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 device keys to be externalized, making the config safe to commit to version control:

{
  "backend": {
    "deviceKey": "{env:BARK_DEVICE_KEY}"
  }
}

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 | 任务完成 | AI已完成任务,正在等待您的输入 | | session.error | 任务失败 | 任务执行过程中发生错误 | | permission.asked | 需要确认 | AI需要您的确认才能继续操作 |

Example Configurations

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

{
  "backend": {
    "deviceKey": "your-device-key"
  }
}

With custom server and group:

{
  "backend": {
    "deviceKey": "your-device-key",
    "server": "https://your-bark-server.com",
    "group": "my-opencode-notifications"
  }
}

Full configuration:

{
  "enabled": true,
  "events": {
    "session.idle": { "enabled": true },
    "session.error": { "enabled": true },
    "permission.asked": { "enabled": true }
  },
  "backend": {
    "deviceKey": "{env:BARK_DEVICE_KEY}",
    "server": "https://api.day.app",
    "group": "opencode",
    "sound": "default",
    "title": {
      "session.idle": { "value": "✅ {project}: 任务完成" },
      "session.error": { "value": "❌ {project}: 任务失败" },
      "permission.asked": { "value": "🔒 {project}: 需要确认" }
    },
    "message": {
      "session.error": { "value": "错误信息: {error}" }
    },
    "icon": {
      "mode": "dark"
    },
    "fetchTimeout": "PT10S"
  }
}

With command templates:

{
  "backend": {
    "deviceKey": "your-device-key",
    "title": {
      "session.idle": { "command": "echo Agent finished in {project}" }
    },
    "message": {
      "permission.asked": { "command": "echo Permission {permission_type} requested" }
    }
  }
}

Getting Your Device Key

  1. Install the Bark app on your iPhone (App Store)
  2. Open the app and copy your device key
  3. Add the device key to your configuration file

Development

Prerequisites

Setup

git clone https://github.com/dirkwei/opencode-bark.git
cd opencode-bark
npm install

Build

npm run build

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

Test

npm test

Or in watch mode:

npm run test:watch

License

MIT