pi-smart-voice-notify

June 22, 2026 · View on GitHub

pi-smart-voice-notify

npm version License Platform

ko-fi

Windows-optimized smart notification extension for the Pi coding agent. pi-smart-voice-notify monitors Pi session and tool events to alert you via multi-engine TTS, sound playback, desktop toast notifications, and optional webhook/AI-assisted messaging when the agent requires your attention. image

Features

  • Multi-channel notifications

    • Sound – local sound playback with fallback beeps and reusable reminder playback control
    • Voice – auto-selectable TTS engines: Edge, espeak-ng, ElevenLabs, OpenAI-compatible, and Windows SAPI
    • Desktop toasts – cross-platform notifications via node-notifier (Windows/macOS/Linux)
    • Webhook delivery – optional Discord or generic HTTP webhook notifications
      • Validates webhook targets as public HTTP(S) destinations and blocks localhost/private/reserved networks before dispatch
  • Intelligent event detection

    • Task completion (idle)
    • Authoritative permission-system wait events plus current-session forwarded subagent permission requests
    • Questions requiring input (when custom question tool is loaded)
    • Errors
  • Reminder system

    • Configurable per-event reminder delays with follow-up scheduling
    • Exponential backoff multiplier for follow-ups
    • Auto-cancel reminders on user activity or resolution
  • Focus and wake handling

    • Wakes display from sleep before notifications
    • Optional focused-terminal suppression on Linux
    • Cross-platform wake strategies for Windows, macOS, and Linux sessions
  • Sound customization

    • Direct per-event sound files
    • Theme-based sound selection and optional per-project sound discovery
    • Theme randomization and default volume controls
  • AI message generation

    • Optional AI-generated notification text with caching and template fallback
  • Interactive settings UI

    • /voice-notify command opens a modal for live configuration
    • Settings persist to disk automatically
  • Debug logging

    • Optional JSONL debug output for troubleshooting

Installation

Local Extension Folder

Place this folder in either location (Pi auto-discovers both):

  • Global default: ~/.pi/agent/extensions/pi-smart-voice-notify (respects PI_CODING_AGENT_DIR)
  • Project: .pi/extensions/pi-smart-voice-notify

As an npm Package

pi install npm:pi-smart-voice-notify

From Git

pi install git:github.com/MasuRii/pi-smart-voice-notify

Usage

Commands

CommandDescription
/voice-notifyOpens the settings modal (interactive mode) or prints config summary
/voice-notify statusDisplays current configuration and question tool availability
/voice-notify reloadReloads config from disk and resets reminder state
/voice-notify onEnables the extension
/voice-notify offDisables the extension
/voice-notify test [type]Triggers a test notification (bypasses throttling)

Test types: idle, permission, question, error

Example

/voice-notify test idle
/voice-notify test permission

Configuration

Configuration is stored at:

Default global path: ~/.pi/agent/extensions/pi-smart-voice-notify/config.json
Actual global path: $PI_CODING_AGENT_DIR/extensions/pi-smart-voice-notify/config.json when PI_CODING_AGENT_DIR is set
Local config path: <repo>/.pi/extensions/pi-smart-voice-notify/config.json

A starter template is provided in config/config.example.json. On startup, the extension creates config.json with defaults if missing.

Configuration Options

OptionTypeDefaultDescription
enabledbooleantrueMaster on/off switch
windowsOptimizedbooleantrueShow a compatibility notice on platforms other than Windows/Linux
notificationModestring"sound-first"Mode: sound-first, tts-first, both, sound-only
enableSoundbooleantrueEnable sound playback
enableTtsbooleantrueEnable text-to-speech delivery
ttsEnginestring"auto"Engine: auto, edge, espeak-ng, elevenlabs, openai, sapi
enableDesktopNotificationbooleantrueEnable desktop toast notifications
desktopNotificationTimeoutnumber8Toast display duration in seconds (1–60)
wakeMonitorbooleantrueWake display from sleep before notifying
idleThresholdSecondsnumber30System idle threshold before waking monitor (5–600)
skipWhenFocusedbooleanfalseSuppress notifications while the active Linux terminal/editor is focused

windowsOptimized keeps compatibility messaging for platforms that do not have Linux/Windows-native behavior. Linux users no longer see this notice.

Event Toggles

OptionTypeDefaultDescription
enableIdleNotificationbooleantrueNotify when agent finishes a task
enablePermissionNotificationbooleantrueNotify when the permission system reports requests waiting for approval
enableForwardedPermissionWatcherbooleantrueWatch current-session forwarded permission request/response files and notify when new requests arrive
includeForwardedPermissionAgentNamebooleantrueInclude sanitized requester agent name in forwarded permission notification text
watchLegacyForwardedPermissionPathbooleantrueRetained for config compatibility; unscoped legacy forwarded-permission paths are ignored because they cannot prove the current target session
enableQuestionNotificationbooleantrueNotify when agent asks a question*
enableErrorNotificationbooleantrueNotify on errors
suppressIdleAfterErrorbooleantrueSkip idle notification if turn had errors

Error notifications are delayed briefly before delivery so Pi can settle related turn state and suppress a redundant idle alert. Override the default 10000 ms delay with PI_SMART_NOTIFY_AGENT_ERROR_GRACE_MS when you need faster or slower error alerts.

*Question notifications only work when a custom question tool is loaded.

Forwarded permission watcher notifications use privacy-safe text, require the request targetSessionId to match the active Pi session, and never include raw forwarded message content.

Reminder Settings

OptionTypeDefaultDescription
reminderEnabledbooleantrueEnable reminder notifications
reminderDelaySecondsnumber30Initial delay before first reminder (5–300)
followUpEnabledbooleantrueEnable follow-up reminders
maxFollowUpsnumber3Maximum follow-up count (1–10)
followUpBackoffMultipliernumber1.5Delay multiplier for each follow-up

TTS Settings

OptionTypeDefaultDescription
voicestring"Microsoft Zira Desktop"Generic preferred voice label
ratenumber-1Generic speaking rate
volumenumber85Preferred playback volume percentage
fallbackChainarray["edge", "espeak-ng", "sapi"]TTS engines tried when ttsEngine is auto
ttsVoicestring"Microsoft Zira Desktop"Legacy SAPI-compatible alias
ttsRatenumber-1Legacy SAPI-compatible alias
edgeVoicestring"en-US-JennyNeural"Microsoft Edge voice
espeakVoicestring"en"espeak-ng voice for Linux fallback
elevenLabsVoiceIdstring"cgSgspJ2msm6clMCkdW9"ElevenLabs voice id
openaiTtsVoicestring"alloy"OpenAI-compatible voice

Sound File Paths

OptionTypeDefault
idleSoundFilestring"assets/soft-notification.mp3"
permissionSoundFilestring"assets/attention-alert.mp3"
questionSoundFilestring"assets/attention-alert.mp3"
errorSoundFilestring"assets/attention-alert.mp3"

Paths can be absolute or relative to the extension directory.

Sound, Webhook, and AI Settings

OptionTypeDefaultDescription
themeNamestring"default"Preferred sound theme name
enablePerProjectSoundsbooleanfalseSearch the current project for matching notification sounds
randomizeThemeSoundsbooleantrueRandomize among matching themed sounds
webhook.enabledbooleanfalseEnable Discord/generic webhook delivery
webhook.eventsarray["idle", "permission", "question", "error"]Notification types sent through webhooks
aiMessages.enabledbooleanfalseEnable AI-generated notification copy
aiMessages.modelstring"llama3"Model id used for AI notification generation
aiMessages.caching.enabledbooleantrueCache generated messages to reduce repeat calls
minNotificationIntervalMsnumber1500Throttle interval between same-type notifications
debugLogbooleanfalseEnable debug logging to file

Webhook dispatch only attempts public http/https URLs. The extension rejects localhost-style names, .local/.internal/.lan/.home.arpa hosts, private or reserved IP literals, and hostnames whose DNS results include private or reserved addresses; validated DNS results are pinned for the outbound request. Use PI_SMART_NOTIFY_WEBHOOK_TIMEOUT_MS to override the default 8000 ms webhook request timeout.

Notification Modes

ModeBehavior
sound-firstPlay sound first; fall back to TTS on failure
tts-firstSpeak TTS first; fall back to sound on failure
bothPlay sound and speak TTS simultaneously
sound-onlyPlay sound only, no TTS or reminders

Troubleshooting

Settings modal doesn't appear

The modal requires interactive UI mode (ctx.hasUI). In non-interactive contexts, /voice-notify prints a config summary instead.

Desktop notifications not showing

  1. Ensure enableDesktopNotification is true
  2. Check that node-notifier is installed
  3. Enable debugLog and check debug/pi-smart-voice-notify.log for desktop.notify.failed events

No sound or voice on Windows

  1. Sound and TTS are Windows-only (process.platform === "win32")
  2. The extension uses PowerShell for audio playback and SAPI—ensure PowerShell is available
  3. Enable debugLog and search for powershell.exec entries

Question notifications never trigger

Question notifications require a custom question tool to be loaded. Run /voice-notify status to verify questionToolAvailable=true.

Wake monitor not working

  • Windows: Uses SendKeys (F15) via PowerShell
  • macOS: Uses caffeinate -u -t 1
  • Linux: Uses xset dpms force on or GNOME D-Bus

Ensure system idle time exceeds idleThresholdSeconds for wake to trigger.

Technical Details

Architecture

index.ts                    → Extension entrypoint (re-exports src/index.ts)
src/
├── index.ts                → Main extension logic, event handlers, command registration
├── config-store.ts         → Config paths, normalization, env overrides, load/save utilities
├── types.ts                → Shared configuration and runtime types
├── notify-audio.ts         → Audio dispatch and Windows/SAPI playback integration
├── tts.ts                  → Multi-engine TTS selection and speech dispatch
├── desktop-notify.ts       → Desktop toast notifications via node-notifier
├── permission-forwarding-watcher.ts → Watches forwarded permission request directories
├── reminder-playback.ts    → Deduplicates/cancels overlapping reminder playback
├── sound-theme.ts          → Theme and sound file resolution
├── per-project-sound.ts    → Project-local sound discovery helpers
├── webhook.ts              → Discord and generic HTTP webhook delivery
├── ai-messages.ts          → AI-generated notification message generation and caching
├── linux.ts                → Linux wake/audio/focus helpers
├── focus-detect.ts         → Terminal focus detection cache
├── logging.ts              → Debug logger with JSONL output
└── zellij-modal.ts         → Settings modal UI components

Event Hooks

EventBehavior
session_startLoad config, reset state, update status bar. Handles all session lifecycle transitions via reason (startup, reload, new, resume, fork).
session_shutdownCancel reminders, clear status
inputTrack user activity, cancel pending reminders
agent_startReset error tracking
tool_callDetect permission blocks
tool_resultClassify results (question/permission/error)
agent_endTrigger idle notification (if enabled)

Debug Logging

When debugLog: true, JSONL events are written to:

Default global debug log path: ~/.pi/agent/extensions/pi-smart-voice-notify/debug/pi-smart-voice-notify.log (respects PI_CODING_AGENT_DIR)

Events include: config changes, notifications triggered, audio dispatch, reminders, and errors.

Development

npm install
npm run build      # TypeScript compilation
npm run lint       # Alias for build
npm run test       # Node test runner with built-in TypeScript stripping
npm run check      # build + test

Requirements: Node.js ≥ 24

License

MIT