Summary
When the plugin runs under Claude Code (CLAUDECODE=1), scripts/warp-notify.sh writes the OSC 777 escape sequence to /dev/tty, but Claude Code spawns hook subprocesses without a controlling TTY, so the write fails silently and no notification ever reaches Warp.
- Plugin version:
2.0.0
- Warp version:
v0.2026.05.13.09.15.stable_01 (also reproduced on v0.2026.05.06.15.42.stable_04)
- Claude Code:
2.1.142 on macOS (Darwin 25.3.0)
Repro
- Install the plugin in Claude Code, restart /
/reload-plugins.
- Confirm
WARP_CLI_AGENT_PROTOCOL_VERSION=1 and WARP_CLIENT_VERSION are set (they are).
- Confirm Warp's "Receive desktop notifications" + agent toggles are on.
- Run anything in Claude Code that triggers
Stop, PermissionRequest, or idle Notification hooks.
- Expected: native Warp/macOS notification. Actual: nothing fires.
Root cause
Adding debug logging to warp-notify.sh shows every hook firing with:
/dev/tty: Device not configured
/dev/tty exists but NOT writable
tty: not a tty
printf to /dev/tty FAILED
The hook subprocess Claude Code spawns has no controlling terminal, so > /dev/tty errors. The 2>/dev/null || true swallows the error, so the failure is invisible.
Workaround / suggested fix
Walk up the process tree to find the nearest ancestor with a real tty (the parent claude process keeps its tty, e.g. ttys003), and write the OSC sequence to that device directly. Patch that works locally:
find_parent_tty() {
local pid=$PPID
local tty
while [ -n "$pid" ] && [ "$pid" != "1" ] && [ "$pid" != "0" ]; do
tty=$(ps -o tty= -p "$pid" 2>/dev/null | tr -d ' ')
if [ -n "$tty" ] && [ "$tty" != "??" ] && [ "$tty" != "-" ]; then
echo "/dev/$tty"
return 0
fi
pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
done
return 1
}
TARGET_TTY=$(find_parent_tty)
if [ -n "$TARGET_TTY" ] && [ -w "$TARGET_TTY" ]; then
printf '\033]777;notify;%s;%s\007' "$TITLE" "$BODY" > "$TARGET_TTY" 2>/dev/null || true
else
printf '\033]777;notify;%s;%s\007' "$TITLE" "$BODY" > /dev/tty 2>/dev/null || true
fi
With this in place, Stop / PermissionRequest / idle notifications all fire correctly.
Minor
The resulting notifications show a generic folder icon rather than the Warp icon — not sure if that's a separate macOS notification-attribution issue or related to the OSC 777 path.
Summary
When the plugin runs under Claude Code (
CLAUDECODE=1),scripts/warp-notify.shwrites the OSC 777 escape sequence to/dev/tty, but Claude Code spawns hook subprocesses without a controlling TTY, so the write fails silently and no notification ever reaches Warp.2.0.0v0.2026.05.13.09.15.stable_01(also reproduced onv0.2026.05.06.15.42.stable_04)2.1.142on macOS (Darwin 25.3.0)Repro
/reload-plugins.WARP_CLI_AGENT_PROTOCOL_VERSION=1andWARP_CLIENT_VERSIONare set (they are).Stop,PermissionRequest, or idleNotificationhooks.Root cause
Adding debug logging to
warp-notify.shshows every hook firing with:The hook subprocess Claude Code spawns has no controlling terminal, so
> /dev/ttyerrors. The2>/dev/null || trueswallows the error, so the failure is invisible.Workaround / suggested fix
Walk up the process tree to find the nearest ancestor with a real tty (the parent
claudeprocess keeps its tty, e.g.ttys003), and write the OSC sequence to that device directly. Patch that works locally:With this in place, Stop / PermissionRequest / idle notifications all fire correctly.
Minor
The resulting notifications show a generic folder icon rather than the Warp icon — not sure if that's a separate macOS notification-attribution issue or related to the OSC 777 path.