Forked from MasuRii/pi-smart-voice-notify.
Receive Pi notifications through terminal-native notifications, the desktop, or webhooks.
English | 简体中文
The extension notifies you when Pi needs your attention through:
- Desktop notifications: disabled by default; supports macOS, Windows, and Linux through
node-notifier. - Terminal notifications: the primary channel, enabled by default; supports iTerm2 (OSC 9), Kitty (OSC 99), Ghostty/WezTerm/Otty (OSC 777), and tmux passthrough.
- Webhooks: optional Discord and generic HTTP webhook delivery.
Notifications cover these events:
- The conversation has fully settled (
agent_settled) - A question tool or recognized input prompt requests user input
- A permission request from
pi-permission-system,@gotgenes/pi-permission-system, or@aliou/pi-guardrailsis waiting for approval, including subagent requests forwarded by@gotgenes/pi-permission-system - The agent finishes with an error
pi install https://github.com/kaiwishc/pi-agent-notifyYou can also clone the repository into a Pi auto-discovery directory and install its runtime dependencies:
git clone https://github.com/kaiwishc/pi-agent-notify \
~/.pi/agent/extensions/pi-agent-notify
cd ~/.pi/agent/extensions/pi-agent-notify
npm install --omit=devFor a project installation, use .pi/extensions/pi-agent-notify instead. Project-level configuration is read only when the project is trusted.
Terminal notifications are enabled by default; desktop notifications and webhooks are disabled. Focus filtering is disabled by default. Set onlyWhenTerminalUnfocused to true to send notifications only while the terminal window is unfocused.
When Pi runs in Otty with Otty's Pi integration extension installed, Otty owns agent lifecycle notifications. This extension suppresses duplicate idle/error terminal and desktop notifications there; questions, permissions, and webhooks remain enabled.
Terminal notifications are sent only in TUI mode. The extension sends only the terminal notification protocol and leaves sound behavior to the terminal. Otty is the exception: because it owns lifecycle notifications but does not provide an audible alert, the extension plays one macOS system alert sound independently of the terminal channel setting.
Global configuration path:
$PI_CODING_AGENT_DIR/extensions/pi-agent-notify/config.json
When PI_CODING_AGENT_DIR is not set, the default is:
~/.pi/agent/extensions/pi-agent-notify/config.json
A trusted project can provide a read-only override at:
<project>/.pi/extensions/pi-agent-notify/config.json
Default configuration:
{
"version": 4,
"enabled": true,
"debug": false,
"onlyWhenTerminalUnfocused": false,
"terminal": {
"enabled": true
},
"desktop": {
"enabled": false,
"sound": true
},
"webhook": {
"enabled": false,
"discordUrl": "",
"genericUrl": "",
"mentionOnPermission": false,
"username": "Pi",
"allowLanWebhook": false
}
}Debug logging is disabled by default. Set "debug": true and run /notify reload to write JSON Lines logs to:
$PI_CODING_AGENT_DIR/extensions/pi-agent-notify/debug.log
Secrets such as webhook URLs should be supplied through environment variables:
| Environment variable | Purpose |
|---|---|
PI_AGENT_NOTIFY_WEBHOOK_ENABLED / WEBHOOK_ENABLED |
Enable or disable webhooks |
PI_AGENT_NOTIFY_DISCORD_WEBHOOK_URL |
Discord webhook URL |
PI_AGENT_NOTIFY_WEBHOOK_URL |
Generic webhook URL |
DISCORD_WEBHOOK_URL |
Compatible Discord URL alias |
WEBHOOK_URL |
Compatible generic URL alias |
By default, webhooks accept public HTTP(S) destinations only. The extension blocks localhost, private or reserved addresses, and DNS rebinding, then pins validated DNS addresses for outbound requests. Set allowLanWebhook: true only when LAN destinations are explicitly required.
| Command | Description |
|---|---|
/notify, /notify status |
Show the current status |
/notify on |
Enable the master switch and save it |
/notify off |
Disable the master switch and save it |
/notify reload |
Reload configuration from disk |
/notify test [idle|permission|question|error] |
Test all currently enabled channels |
Node.js 24 or newer is required.
npm install
npm run check
npm pack --dry-runindex.ts
src/
├── index.ts # Event coordination, deduplication, channels, commands
├── config-store.ts # Version 4 global/project/env configuration
├── terminal-notify.ts # OSC 9/99/777 and tmux passthrough
├── desktop-notify.ts # node-notifier desktop delivery
├── webhook.ts # Discord/generic webhooks, queue, SSRF protection
├── permission-forwarding-watcher.ts # Current-session forwarded permissions
├── gotgenes-permission-adapter.ts
├── guardrails-permission-adapter.ts
├── agent-dir.ts
└── types.ts
A failure in one notification channel does not block another channel or interrupt the Pi conversation. The webhook queue is flushed during session_shutdown.
- Confirm that both
enabledanddesktop.enabledaretrue. - With the default configuration, ensure the terminal window is unfocused when the event occurs. Terminals that do not report focus automatically fall back to sending notifications.
- Check whether the operating system permits notifications from the terminal or
node-notifier. - Linux desktop environments require an available notification service.
- Terminal notifications are sent only in Pi TUI mode.
- Confirm that
terminal.enabledistrue. - Allow notifications and sounds in the terminal and operating-system settings.
- Confirm that
webhook.enabledistrueand at least one valid URL is configured. - LAN URLs require
allowLanWebhook: true. - Discord URLs must use the standard
/api/webhooks/endpoint format.
MIT