diff --git a/src/hooks/session-notification-sender.ts b/src/hooks/session-notification-sender.ts index 8c5cf1df..4ac0c4d8 100644 --- a/src/hooks/session-notification-sender.ts +++ b/src/hooks/session-notification-sender.ts @@ -7,6 +7,7 @@ import { getAfplayPath, getPaplayPath, getAplayPath, + getTerminalNotifierPath, } from "./session-notification-utils" import { buildWindowsToastScript, escapeAppleScriptText, escapePowerShellSingleQuotedText } from "./session-notification-formatting" @@ -39,6 +40,19 @@ export async function sendSessionNotification( ): Promise { switch (platform) { case "darwin": { + // Try terminal-notifier first — deterministic click-to-focus + const terminalNotifierPath = await getTerminalNotifierPath() + if (terminalNotifierPath) { + const bundleId = process.env.__CFBundleIdentifier + const args = [terminalNotifierPath, "-title", title, "-message", message] + if (bundleId) { + args.push("-activate", bundleId) + } + await ctx.$`${args}`.catch(() => {}) + break + } + + // Fallback: osascript (click may open Finder instead of terminal) const osascriptPath = await getOsascriptPath() if (!osascriptPath) return diff --git a/src/hooks/session-notification-utils.ts b/src/hooks/session-notification-utils.ts index 0c09fd8f..5f9d572f 100644 --- a/src/hooks/session-notification-utils.ts +++ b/src/hooks/session-notification-utils.ts @@ -32,11 +32,13 @@ export const getPowershellPath = createCommandFinder("powershell") export const getAfplayPath = createCommandFinder("afplay") export const getPaplayPath = createCommandFinder("paplay") export const getAplayPath = createCommandFinder("aplay") +export const getTerminalNotifierPath = createCommandFinder("terminal-notifier") export function startBackgroundCheck(platform: Platform): void { if (platform === "darwin") { getOsascriptPath().catch(() => {}) getAfplayPath().catch(() => {}) + getTerminalNotifierPath().catch(() => {}) } else if (platform === "linux") { getNotifySendPath().catch(() => {}) getPaplayPath().catch(() => {})