.maestro/playbooks/Wizard-2026-02-22-2/Phase-01-Toast-Notification-Service.md
This phase installs node-notifier, creates the toast notification module, adds a settings toggle, and wires everything into the observation save pipeline. By the end, saving an observation with CLAUDE_MEM_TOAST_NOTIFICATIONS_ENABLED=true in ~/.claude-mem/settings.json will produce a native macOS notification showing the observation's title and subtitle.
Install node-notifier dependency:
npm install node-notifiernpm install --save-dev @types/node-notifierAdd toast notifications setting to SettingsDefaultsManager:
src/shared/SettingsDefaultsManager.tsCLAUDE_MEM_TOAST_NOTIFICATIONS_ENABLED: string; to the SettingsDefaults interface, in the "Feature Toggles" section (near CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED)CLAUDE_MEM_TOAST_NOTIFICATIONS_ENABLED: 'false', to the DEFAULTS object in the same section// macOS toast notifications for saved observationsCreate the ToastNotifier functional module:
src/services/worker/agents/ToastNotifier.tssrc/services/worker/agents/ObservationBroadcaster.ts (functional module, not a class)node-notifier, the logger from ../../../utils/logger.js, SettingsDefaultsManager from ../../../shared/SettingsDefaultsManager.js, and USER_SETTINGS_PATH from ../../../shared/paths.jssendObservationToast(title: string | null, subtitle: string | null): void that:
process.platform !== 'darwin' (macOS only)SettingsDefaultsManager.loadFromFile(USER_SETTINGS_PATH)CLAUDE_MEM_TOAST_NOTIFICATIONS_ENABLED — return if not 'true' (handle both string 'true' and boolean true)notifier.notify() with { title: title || 'Observation saved', message: subtitle || '', sound: false }logger.warn('TOAST', ...) but NEVER throw (fire-and-forget, must not crash the pipeline)Wire ToastNotifier into the observation broadcast pipeline:
src/services/worker/agents/ResponseProcessor.tsimport { sendObservationToast } from './ToastNotifier.js';syncAndBroadcastObservations() function, inside the for loop that iterates observations, add a call to sendObservationToast(obs.title, obs.subtitle) right after the existing broadcastObservation(worker, {...}) call (around line 247)Build the project and verify compilation:
npm run build-and-sync