Ghostty natively supports the OSC 9 desktop-notification escape
(ESC ] 9 ; <message> BEL), the same sequence already used for iTerm2.
Previously only TERM_PROGRAM === 'iTerm.app' took the escape path, so
Ghostty users fell through to the osascript path. That makes Script
Editor the notification owner, and clicking the notification just
launches Script Editor instead of focusing the terminal.
Adding 'ghostty' to the OSC 9-capable check makes Ghostty the owner,
so clicking the notification focuses the Ghostty window/tab where
Claude Code is running. Verified on Ghostty (TERM_PROGRAM=ghostty).
Co-authored-by: 高野智史 <satoshitakano@takanosatoshinoMacBook-Pro-522.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(hooks): add WSL desktop notification support via PowerShell + BurntToast
Adds WSL (Windows Subsystem for Linux) desktop notification support to the
existing desktop-notify hook. The hook now detects WSL, finds available
PowerShell (7 or Windows PowerShell), checks for BurntToast module, and
sends Windows toast notifications.
New functions:
- isWSL(): detects WSL environment
- findPowerShell(): finds PowerShell 7 or Windows PowerShell on WSL
- isBurntToastAvailable(): checks if BurntToast module is installed
- notifyWindows(): sends Windows toast notification via BurntToast
If BurntToast is not installed, logs helpful tip for installation.
Falls back silently on non-WSL/non-macOS platforms.
* docs(hooks): update desktop-notify description to include WSL
Updates the hook description in hooks.json to reflect the newly
added WSL notification support alongside macOS.
* fix(hooks): capture stderr properly in notifyWindows
Change stdio to ['ignore', 'pipe', 'pipe'] so stderr is captured
and can be logged on errors. Without this, result.stderr is null
and error logs show 'undefined' instead of the actual error.
* fix(hooks): quote PowerShell path in install tip for shell safety
The PowerShell path contains spaces and needs to be quoted
when displayed as a copy-pasteable command.
* fix(hooks): remove external repo URL from tip message
BurntToast module is a well-known Microsoft module but per project
policy avoiding unvetted external links in user-facing output.
* fix(hooks): probe WSL interop PATH before hardcoded paths
Adds 'pwsh.exe' and 'powershell.exe' as candidates to leverage
WSL's Windows interop PATH resolution, making the hook work with
non-default WSL mount prefixes or Windows drives.
* perf(hooks): memoize isWSL detection at module load
Avoids reading /proc/version twice (once in run(), once in findPowerShell())
by computing the result once when the module loads.
* perf(hooks): reduce PowerShell spawns from 3 to 1 per notification
Merge findPowerShell version check and isBurntToastAvailable check
into a single notifyWindows call. Now just tries to send directly;
if it fails, tries next PowerShell path. Version field was unused.
Net effect: up to 3 spawns reduced to 1 in the happy path.
* fix(hooks): remove duplicate notifyWindows declaration
There were two notifyWindows function declarations due to incomplete
refactoring. Keeps only the version that returns true/false for the
call site. Node.js would throw SyntaxError with 'use strict'.
* fix(hooks): improve error handling and detection robustness
- Increase PowerShell detection timeout from 1s to 3s to avoid false
negatives on slower/cold WSL interop startup
- Return error reason from notifyWindows to distinguish BurntToast
module not found vs other PowerShell errors
- Log actionable error details instead of always showing install tip
---------
Co-authored-by: boss <boss@example.com>
- Check spawnSync result and log warning on failure via stderr
- Restore osascript timeout to 5000ms, increase hook deadline to 10s
for sufficient headroom
- Replace JSON.stringify with curly quote substitution for AppleScript
compatibility (AppleScript does not support \" backslash escapes)
- Reduce spawnSync timeout from 5000ms to 3000ms to leave headroom
within the 5s hook deadline
Add a new Stop hook that sends a native macOS notification with the
task summary (first line of last_assistant_message) when Claude finishes
responding. Uses osascript via spawnSync for shell injection safety.
Supports run-with-flags fast require() path. Only active on standard
and strict profiles; silently skips on non-macOS platforms.