feat(hooks): add WSL desktop notification support via PowerShell + BurntToast#1019
Conversation
…ntToast 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.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds WSL support to the desktop notification hook: detects WSL, locates PowerShell, attempts BurntToast-based Windows toasts via PowerShell, falls back to logging install guidance, and still sends native macOS notifications when on macOS. Changes
Sequence DiagramsequenceDiagram
participant Client
participant Hook as run(raw)
participant Platform as PlatformCheck
participant WSL as WSLCheck
participant PS as PowerShellFinder
participant BT as BurntToastCheck
participant Windows as WindowsToast
Client->>Hook: invoke run(raw)
Hook->>Platform: is macOS?
alt macOS
Platform-->>Hook: true
Hook->>Windows: send macOS native notification
else not macOS
Platform-->>Hook: false
Hook->>WSL: check /proc/version contains "microsoft"
alt WSL
WSL-->>Hook: true
Hook->>PS: probe candidate pwsh/powershell paths
alt PowerShell found
PS-->>Hook: pwsh path
Hook->>BT: run PowerShell to Import-Module BurntToast
alt BurntToast import succeeds
BT-->>Hook: loaded
Hook->>Windows: New-BurntToastNotification(title, body)
Windows-->>Hook: result
else BurntToast import fails
BT-->>Hook: import failed
Hook-->>Client: log BurntToast installation guidance
end
else PowerShell not found
PS-->>Hook: not found
Hook-->>Client: log PowerShell/BurntToast guidance
end
else not WSL
WSL-->>Hook: false
Hook-->>Client: no-op / preserved macOS behavior
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR adds WSL desktop notification support to All six previously flagged P1 issues are resolved in this iteration:
Remaining minor issue:
Confidence Score: 5/5Safe to merge; all prior P1 issues are resolved and only a minor tip-text wording issue remains. All six previously raised P1 findings (SyntaxError from duplicate declaration, missing return value, stdio discard, hardcoded C: drive, double isWSL reads, excessive spawns) are addressed in the current commit. The single remaining finding is a P2 UX string issue that does not affect correctness or reliability. Per the confidence guidance, a P2-only result warrants 5/5. No files require special attention for merge safety. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[run] --> B{isMacOS?}
B -- yes --> C[notifyMacOS via osascript]
B -- no --> D{isWSL?}
D -- no --> E[silent return]
D -- yes --> F[findPowerShell]
F --> G{found?}
G -- null --> H[log install PowerShell tip]
G -- path --> I[notifyWindows via BurntToast]
I --> J{success?}
J -- true --> K[notification sent]
J -- reason has burnttoast --> L[log install BurntToast tip]
J -- other reason --> M[log notification failed]
Reviews (6): Last reviewed commit: "fix(hooks): improve error handling and d..." | Re-trigger Greptile |
There was a problem hiding this comment.
2 issues found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/hooks/desktop-notify.js">
<violation number="1" location="scripts/hooks/desktop-notify.js:144">
P2: Installation tip command is not shell-safe: PowerShell path is unquoted even though candidate path contains spaces.</violation>
<violation number="2" location="scripts/hooks/desktop-notify.js:148">
P2: User-facing runtime output includes a direct external repository link, conflicting with the project policy against unvetted external repo links.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Updates the hook description in hooks.json to reflect the newly added WSL notification support alongside macOS.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/hooks/desktop-notify.js`:
- Around line 6-10: Update the hooks registry entry for the "desktop-notify"
hook in hooks.json so its description matches scripts/hooks/desktop-notify.js:
change the metadata text (currently macOS-only) to advertise both macOS
(osascript) and WSL (PowerShell 7 or Windows PowerShell + BurntToast), and
mention the WSL tip when BurntToast is missing so the catalog/help text aligns
with the hook's actual behavior.
- Around line 41-47: findPowerShell currently only checks hard-coded /mnt/c/...
paths so it can miss valid WSL setups; update findPowerShell to first probe for
executables by name (try "pwsh.exe" then "powershell.exe") using a PATH/command
lookup (e.g., child_process.execSync('command -v ...') or fs access via
which-like resolution) and return the first found, and only if those fail fall
back to the existing candidates array of absolute paths; keep the isWSL() guard
and preserve the original candidates list so the function still handles systems
where executables are not on PATH.
- Around line 67-75: isBurntToastAvailable currently swallows all errors and
returns a boolean, and notifyWindows uses stdio: 'ignore' then reads
result.stderr (null); change isBurntToastAvailable to return an object like {
available, reason } where you set available = true when exit code 0, available =
false and reason = stderr/exception message when non-zero/exception, and adjust
spawnSync stdio to ['ignore','pipe','pipe'] to capture stderr; then update
callers (e.g., the call at the former line 139) to check .available and use the
.reason when logging errors and only show the BurntToast install guidance when
reason indicates the module is missing rather than for timeouts or other
failures.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: dbce2581-c602-4597-b965-4f76755e0a5e
📒 Files selected for processing (1)
scripts/hooks/desktop-notify.js
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.
|
Thanks for the review! Addressing the points: Issue #1 (stderr): Fixed in latest commit. Changed Issue #2 (hardcoded paths): Valid P2 concern. The current implementation covers the default WSL installation path. Non-default mounts would need additional path probing - keeping as P2 for a follow-up improvement. Issue #3 (isWSL() called twice): Acknowledged as P2 optimization. Could memoize the result, but the I/O is minimal. Issue #4 (sequential spawnSync): Acknowledged as P2 perf concern. The hook runs async so it doesn't block Claude Code. Thanks for the thorough review! |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/hooks/desktop-notify.js (1)
55-55:versionis computed but never used.
findPowerShell()returns{ path, version }, butversionis not referenced anywhere in the codebase. Consider removing the version probing if it's not planned for near-term use, or add a comment indicating future intent.♻️ Option A: Simplify if version is unneeded
for (const path of candidates) { try { - const result = spawnSync(path, ['-Command', '$PSVersionTable.PSVersion.Major'], + const result = spawnSync(path, ['-Command', '$true'], { stdio: ['ignore', 'pipe', 'ignore'], timeout: 3000 }); if (result.status === 0) { - const version = parseInt(result.stdout.toString().trim(), 10); - return { path, version }; + return { path }; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/hooks/desktop-notify.js` at line 55, findPowerShell() currently returns an object with { path, version } but the computed version value is never used; either remove the version probing and change the return to only supply path (and update any callers that destructure the result) or keep the probe but add a clear TODO/comment explaining future intent and mark the version as intentionally unused; update the findPowerShell function (and any code that handles its return) to reflect the chosen approach so there are no unused variables.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/hooks/desktop-notify.js`:
- Line 55: findPowerShell() currently returns an object with { path, version }
but the computed version value is never used; either remove the version probing
and change the return to only supply path (and update any callers that
destructure the result) or keep the probe but add a clear TODO/comment
explaining future intent and mark the version as intentionally unused; update
the findPowerShell function (and any code that handles its return) to reflect
the chosen approach so there are no unused variables.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 58dd876a-83ea-4662-b1ea-0286b33d1c3d
📒 Files selected for processing (1)
scripts/hooks/desktop-notify.js
The PowerShell path contains spaces and needs to be quoted when displayed as a copy-pasteable command.
BurntToast module is a well-known Microsoft module but per project policy avoiding unvetted external links in user-facing output.
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.
Avoids reading /proc/version twice (once in run(), once in findPowerShell()) by computing the result once when the module loads.
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.
|
Thanks for the thorough review! Here's a summary of all P2 issues addressed: 1. stderr capture (notifyWindows)
2. Shell safety (install tip)
3. External repo URL
4. Hardcoded C: drive / WSL mount prefix
5. isWSL() called twice
6. Sequential PowerShell spawns (3 → 1)
All P2 issues have been addressed. Thanks again for the detailed review! |
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'.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
scripts/hooks/desktop-notify.js (1)
137-145:⚠️ Potential issue | 🟠 MajorDon't collapse all WSL failures into the BurntToast install tip.
Lines 141-144 still tell users to install BurntToast when either PowerShell was not found at all or toast delivery failed for some other reason. That sends users to the wrong remediation path; only print the BurntToast tip when the underlying PowerShell failure actually indicates a missing module, and use a PowerShell-specific message for the
!pscase.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/hooks/desktop-notify.js` around lines 137 - 145, The current branch collapses all failures into the BurntToast tip; change the flow to call notifyWindows(ps, TITLE, summary) only when ps is truthy and inspect its result (e.g., const result = notifyWindows(ps, TITLE, summary)); have notifyWindows return a distinct value or error reason such as 'missingBurntToast' or true/false so you can: if (ps && result === true) do nothing, else if (ps && result === 'missingBurntToast') log the BurntToast install tip, else if (ps) log a PowerShell-specific failure message (toast delivery failed), and finally if (!ps) log the PowerShell-not-found tip; update notifyWindows and the call site (ps, notifyWindows, TITLE, summary, log) accordingly so each case maps to the correct remediation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@scripts/hooks/desktop-notify.js`:
- Around line 137-145: The current branch collapses all failures into the
BurntToast tip; change the flow to call notifyWindows(ps, TITLE, summary) only
when ps is truthy and inspect its result (e.g., const result = notifyWindows(ps,
TITLE, summary)); have notifyWindows return a distinct value or error reason
such as 'missingBurntToast' or true/false so you can: if (ps && result === true)
do nothing, else if (ps && result === 'missingBurntToast') log the BurntToast
install tip, else if (ps) log a PowerShell-specific failure message (toast
delivery failed), and finally if (!ps) log the PowerShell-not-found tip; update
notifyWindows and the call site (ps, notifyWindows, TITLE, summary, log)
accordingly so each case maps to the correct remediation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ef186afe-74b1-4752-8c91-f86c8665f930
📒 Files selected for processing (1)
scripts/hooks/desktop-notify.js
There was a problem hiding this comment.
2 issues found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/hooks/desktop-notify.js">
<violation number="1" location="scripts/hooks/desktop-notify.js:53">
P2: PowerShell detection timeout was tightened to 1s, which can cause false negatives on slower/cold WSL interop startup and skip notifications.</violation>
<violation number="2" location="scripts/hooks/desktop-notify.js:127">
P2: WSL notification failures are now always reported as “BurntToast not available,” and error details are dropped. Any PowerShell/notification error returns false and triggers the install tip, masking actionable diagnostics for non-module failures.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- 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
…rntToast (affaan-m#1019) * 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>
…rntToast (affaan-m#1019) * 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>
What Changed
Added WSL (Windows Subsystem for Linux) desktop notification support to the existing
desktop-notify.jshook.New functions:
isWSL(): detects WSL environmentfindPowerShell(): finds PowerShell 7 or Windows PowerShell on WSLisBurntToastAvailable(): checks if BurntToast module is installednotifyWindows(): sends Windows toast notification via BurntToastPlatforms:
If BurntToast is not installed, logs helpful tip for installation. Falls back silently on non-WSL/non-macOS platforms.
Why This Change
Users running Claude Code in WSL couldn't receive desktop notifications since the existing code only supported macOS. This change enables Windows native notifications for WSL users.
Testing Done
node tests/run-all.js- 1683 pass, 1 unrelated failure)Type of Change
feat:New featureSecurity & Quality Checklist
Documentation
Summary by cubic
Adds WSL desktop notifications in
desktop-notify.jsusing PowerShell andBurntToast, with improved detection and clearer error messages. Also updateshooks.jsonto mention macOS/WSL support and speeds up notifications by reducing PowerShell spawns.New Features
BurntToast; logs an install tip if the module is missing.hooks.jsonnow mentions macOS/WSL.Bug Fixes
notifyWindows; log actionable messages and only show theBurntToasttip when relevant.Written for commit 804d51d. Summary will update on new commits.
Summary by CodeRabbit