Get native Windows 10/11 toast notifications when Claude Code needs your input or finishes a task.
- Windows 10/11 with WSL2
powershell.exeaccessible from WSL (default in most setups)jqinstalled in WSL (sudo apt install jq)
powershell.exe -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser"
powershell.exe -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Install-Module -Name BurntToast -Force -Scope CurrentUser"mkdir -p ~/bin
cat > ~/bin/toast << 'SCRIPT'
#!/bin/bash
# WSL -> Windows toast notification using BurntToast
# Usage:
# toast "Title" "Message" # simple mode
# echo '{"cwd":...}' | toast --hook "Title" # hook mode (reads JSON from stdin)
HOOK_MODE=false
if [[ "$1" == "--hook" ]]; then
HOOK_MODE=true
shift
fi
TITLE="${1:-Claude Code}"
MESSAGE="${2:-}"
if $HOOK_MODE; then
# Read JSON from stdin (Claude Code hook context)
INPUT=$(cat)
CWD=$(echo "$INPUT" | jq -r '.cwd // empty')
HOOK_MSG=$(echo "$INPUT" | jq -r '.message // empty')
NTYPE=$(echo "$INPUT" | jq -r '.notification_type // empty')
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')
EVENT=$(echo "$INPUT" | jq -r '.hook_event_name // empty')
# Shorten cwd: replace $HOME with ~
if [[ -n "$CWD" ]]; then
CWD="${CWD/#$HOME/\~}"
fi
# Build message from hook context
PARTS=()
if [[ -n "$HOOK_MSG" ]]; then
PARTS+=("$HOOK_MSG")
elif [[ "$EVENT" == "Stop" ]]; then
PARTS+=("Task complete")
fi
if [[ -n "$TOOL" ]]; then
PARTS+=("Tool: $TOOL")
fi
if [[ -n "$CWD" ]]; then
PARTS+=("[$CWD]")
fi
MESSAGE=$(IFS=$'\n'; echo "${PARTS[*]}")
fi
# Escape single quotes for PowerShell
TITLE="${TITLE//\'/\'\'}"
MESSAGE="${MESSAGE//\'/\'\'}"
powershell.exe -NoProfile -Command "
Import-Module BurntToast -ErrorAction SilentlyContinue
New-BurntToastNotification -Text '$TITLE', '$MESSAGE' -Sound 'Default'
" >/dev/null 2>&1 &
SCRIPT
chmod +x ~/bin/toastecho '' >> ~/.bashrc
echo '# WSL toast notifications for Claude Code' >> ~/.bashrc
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrctoast "Hello" "It works!"You should see a Windows toast notification with a sound.
Add the hooks section to ~/.claude/settings.json (create the file if it doesn't exist):
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "/home/YOUR_USERNAME/bin/toast --hook \"Claude Code\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "/home/YOUR_USERNAME/bin/toast --hook \"Claude Code\""
}
]
}
]
}
}Replace YOUR_USERNAME with your WSL username (whoami).
Hooks are loaded at startup, so restart Claude Code for the changes to take effect.
- Notification (Claude needs input): Shows the specific message (e.g. "Claude needs your permission to use Bash") plus the working directory.
- Stop (Claude finished): Shows "Task complete" plus the working directory.
Claude Code hooks pass JSON context to commands via stdin. The --hook flag tells the toast script to parse this JSON and extract useful fields:
| Field | Used for |
|---|---|
message |
The notification text from Claude (e.g. permission requests) |
cwd |
Current working directory, shown as [~/path] |
tool_name |
Which tool triggered the hook (if applicable) |
hook_event_name |
Whether this is a Notification or Stop event |
| Problem | Fix |
|---|---|
| No notification appears | Run powershell.exe -Command "Get-Module -ListAvailable BurntToast" - if empty, reinstall the module |
powershell.exe not found |
Check with which powershell.exe - should be at /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe |
| Hooks not firing | Make sure you restarted Claude Code after editing settings.json |
jq not found |
sudo apt install jq |