opencode-discord-notify
v0.10.0
Published
A plugin that posts OpenCode events to a Discord webhook.
Maintainers
Readme
OPENCODE-DISCORD-NOTIFY
Requires OpenCode v1.1.1 or later (due to breaking changes in the permission event system)
Get real-time OpenCode notifications directly in your Discord server.
This plugin creates organized threads in Discord Forum channels for each OpenCode session, keeping you updated on session events, permissions, todos, and conversations.
Features
- Session tracking: Automatic thread creation for each session
- Real-time updates: Permission requests, session completion, errors
- Todo checklists: Visual todo updates with status icons
- Smart notifications: User messages sent immediately, agent responses when finalized
- Mention support: Optional
@everyoneor@herementions for important events - Fallback webhooks: Send critical mentions to text channels for guaranteed delivery
Quick Start
1. Install the plugin
Add to your opencode.json or opencode.jsonc:
{
"plugin": ["opencode-discord-notify@latest"],
}Restart OpenCode.
2. Create a Discord webhook
- Open your Discord server settings
- Go to a Forum channel (recommended) or text channel
- Navigate to Integrations → Webhooks
- Click New Webhook and copy the webhook URL
3. Set the webhook URL
Set the environment variable:
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."That's it! Start using OpenCode and watch notifications appear in Discord.
Configuration
Environment Variables
| Variable | Required | Default | Description |
| ----------------------------------------------- | -------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| DISCORD_WEBHOOK_URL | ✅ Yes | - | Discord webhook URL. Plugin is disabled if not set. |
| DISCORD_WEBHOOK_USERNAME | ❌ No | - | Custom username for webhook posts |
| DISCORD_WEBHOOK_AVATAR_URL | ❌ No | - | Custom avatar URL for webhook posts |
| DISCORD_WEBHOOK_COMPLETE_MENTION | ❌ No | - | Add @everyone or @here to session completion/error notifications |
| DISCORD_WEBHOOK_PERMISSION_MENTION | ❌ No | - | Add @everyone or @here to permission request notifications |
| DISCORD_WEBHOOK_COMPLETE_INCLUDE_LAST_MESSAGE | ❌ No | 1 | Set to 0 to exclude the last assistant message from session completion notifications |
| DISCORD_WEBHOOK_EXCLUDE_INPUT_CONTEXT | ❌ No | 1 | Set to 0 to include file context in notifications |
| DISCORD_WEBHOOK_SHOW_ERROR_ALERT | ❌ No | 1 | Set to 0 to disable error toast notifications |
| DISCORD_SEND_PARAMS | ❌ No | - | Comma-separated embed fields: sessionID,permissionID,permission,patterns,messageID,callID,partID,role,directory,projectID |
| DISCORD_WEBHOOK_FALLBACK_URL | ❌ No | - | Fallback webhook URL for text channel (sends mentions here too for guaranteed ping) |
| DISCORD_NOTIFY_QUEUE_DB_PATH | ❌ No | ~/.config/opencode/discord-notify-queue.db | Custom path for the persistent queue database |
Example Configuration
Basic usage:
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/your-webhook-url"With mentions and fallback:
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/forum-webhook-url"
export DISCORD_WEBHOOK_FALLBACK_URL="https://discord.com/api/webhooks/text-channel-webhook-url"
export DISCORD_WEBHOOK_COMPLETE_MENTION="@everyone"
export DISCORD_WEBHOOK_PERMISSION_MENTION="@here"With custom appearance:
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/your-webhook-url"
export DISCORD_WEBHOOK_USERNAME="OpenCode Bot"
export DISCORD_WEBHOOK_AVATAR_URL="https://example.com/avatar.png"Advanced
Supported Events
session.created: Queues session start notification (sent when thread info is available)permission.asked: Posts permission request immediatelysession.idle: Posts session completion notification- Includes the last assistant message in the embed description by default (customizable via
DISCORD_WEBHOOK_COMPLETE_INCLUDE_LAST_MESSAGE) - Message is truncated to 4096 characters if needed
- Includes the last assistant message in the embed description by default (customizable via
session.error: Posts error notification (skipped ifsessionIDmissing)todo.updated: Posts checklist with[▶](in progress),[✓](completed); excludes cancelledmessage.updated: Tracked internally for role detection (not posted)message.part.updated:text: User messages posted immediately; agent messages posted when finalizedtool: Not postedreasoning: Not posted
Thread Naming Priority
Thread names use the first available option (max 100 chars):
- First user text message
- Session title
session <sessionID>untitled
Forum vs Text Channel
- Forum channels: Creates a new thread per session using
thread_name - Text channels: Posts directly (threads not supported)
- Fallback: If thread creation fails, falls back to direct channel posting
Why Fallback Webhooks?
Discord Forum webhooks do not trigger pings for @everyone or @here mentions. They appear as plain text.
To ensure you get notified:
- Set
DISCORD_WEBHOOK_URLto your Forum webhook (for organized threads) - Set
DISCORD_WEBHOOK_FALLBACK_URLto a text channel webhook (for actual pings) - Messages with mentions will be sent to both webhooks
Fallback Message Format
Fallback messages always include:
sessionIDfieldthread titlefield (same as Forum thread name)
This provides context when viewing notifications in the text channel.
Persistent Queue (v0.7.0+)
All notifications are stored in a local SQLite database before sending:
- Database location:
~/.config/opencode/discord-notify-queue.db(customizable viaDISCORD_NOTIFY_QUEUE_DB_PATH) - Worker process: Automatically processes queued messages in the background
- Auto-start: Worker starts when first user message is sent
- Auto-stop: Worker stops when queue is empty
- Batch size: Processes 1 message at a time to ensure thread ID consistency
Benefits:
- Messages survive OpenCode restarts
- Prevents data loss during network issues
- Ensures correct thread naming with user's first message
Retry Logic
All failed requests are automatically retried with the following behavior:
- Max retries: 5 attempts per message
- Retry tracking: Each retry updates
retry_countandlast_errorin the queue database - Warning notifications: Shows toast with retry count (e.g., "Retry 3/5. Error: ...")
- Final failure: After 5 failed retries, message is deleted and error notification is shown
HTTP 429 (Rate Limit)
- Waits for
retry_afterseconds (or ~10s if not provided) - Automatically retries up to 5 times before discarding
- Messages remain in queue database during retry period
Other Failed Requests
- Shows OpenCode TUI toast notification (controlled by
DISCORD_WEBHOOK_SHOW_ERROR_ALERT) - Logs error details for debugging
- Messages persist in queue for up to 5 retry attempts
DISCORD_SEND_PARAMS
Controls which metadata fields appear in embeds.
Allowed keys:
sessionID,permissionID,permission,patterns,messageID,callID,partID,role,directory,projectID
Default behavior (unset/empty):
- No fields sent (cleaner embeds)
To send all fields:
export DISCORD_SEND_PARAMS="sessionID,permissionID,permission,patterns,messageID,callID,partID,role,directory,projectID"Note: session.created always includes sessionID regardless of this setting.
Development
Setup
npm installFormat Code
npx prettier . --writePlugin Source
Main implementation: src/index.ts
Roadmap
- [ ] Support multiple webhooks for routing by event type
- [ ] Message filtering/customization
- [x] Customizable notification templates
- [x] Configuration file support (e.g.,
opencode-discord-notify.config.json) - [x] Enhanced rate limit handling (smarter retry logic, message queuing)
- [x] CI/CD (automated linting, formatting, testing)
Contributing
PRs and issues are welcome! Please feel free to:
- Report bugs
- Request features
- Submit improvements
- Share feedback
License: MIT
