Skip to content

warp-notify.sh fails silently when /dev/tty is unavailable in Claude Code sandbox #55

@thebrownproject

Description

@thebrownproject

Summary

warp-notify.sh writes OSC 777 escape sequences to /dev/tty, but Claude Code runs hook scripts in a sandboxed subshell where /dev/tty is not attached ("Device not configured"). The || true on line 21 swallows the error, so all notifications silently fail.

Environment

  • macOS (Darwin 25.3.0)
  • Warp v0.2026.05.18.05.32.stable_02
  • Claude Code 2.1.142
  • Plugin warp@claude-code-warp v2.0.0
  • WARP_CLI_AGENT_PROTOCOL_VERSION=1
  • TERM_PROGRAM=WarpTerminal

Steps to reproduce

  1. Launch Claude Code in a Warp terminal tab
  2. Trigger any notification (idle prompt, permission request, stop)
  3. No in-app notification chip appears

Root cause

Inside Claude Code's hook execution environment:

$ tty
not a tty

$ printf '' > /dev/tty
/dev/tty: Device not configured

The parent claude process does have a TTY (e.g. ttys018), but the subshell spawned for hook scripts does not inherit it.

Workaround

Replace the /dev/tty write in warp-notify.sh with a function that walks up the process tree to find the ancestor's TTY device:

resolve_tty() {
    if printf '' 2>/dev/null > /dev/tty 2>/dev/null; then
        echo /dev/tty
        return
    fi
    local pid=$$
    while [ "$pid" -gt 1 ] 2>/dev/null; do
        local ancestor_tty
        ancestor_tty=$(ps -o tty= -p "$pid" 2>/dev/null | tr -d ' ')
        if [ -n "$ancestor_tty" ] && [ "$ancestor_tty" != "??" ]; then
            local dev="/dev/$ancestor_tty"
            if [ -w "$dev" ]; then
                echo "$dev"
                return
            fi
        fi
        pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
    done
    return 1
}

TTY_DEV=$(resolve_tty) || exit 0
printf '\033]777;notify;%s;%s\007' "$TITLE" "$BODY" > "$TTY_DEV" 2>/dev/null || true

This resolves the issue and notifications work correctly after the patch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions