fix(hooks): classify Claude desktop-app sessions as the desktop voice channel - #2105
Open
pai-scaffolde wants to merge 1 commit into
Open
pai-scaffolde wants to merge 1 commit into
pai-scaffolde wants to merge 1 commit into
Conversation
… channel getNotificationChannel() infers "has a speaker" from terminal identity (TERM, TERM_PROGRAM, KITTY_WINDOW_ID, SSH_TTY). The Claude desktop app is an interactive session with a speaker that sets none of those; it sets CLAUDE_CODE_ENTRYPOINT=claude-desktop. Every session started from the app was therefore classified 'headless' and every voice-firing hook skipped /notify with reason remote_channel:headless. Count the desktop-app entrypoint as terminal identity. An explicit LIFEOS_NOTIFICATION_CHANNEL still wins, so the spawners that stamp children 'headless' are unaffected. Adds a bun test covering both directions; the desktop case fails on the shipped file. Public issue danielmiessler#1975. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reproduced on a fresh LifeOS 7.40.4 install (macOS, Claude Code in the Claude desktop app); the fix was applied to that install and run there before filing. Addresses the detector half left open on #1975 ("paste the CLAUDE* env from a desktop session and I'll wire it") — this PR is that answer.
Observed
Every session started from the Claude desktop app (Code tab) produced no voice;
MEMORY/VOICE/voice-events.jsonlfilled withevent_type: "skipped",reason: "remote_channel:headless"for every notification.Environment of a desktop-app session (measured in a tool-spawned child process; hook processes inherit the same env):
CLAUDECODE=1,CLAUDE_CODE_CHILD_SESSION=1,CLAUDE_CODE_ENTRYPOINT=claude-desktop;TERM,TERM_PROGRAM,KITTY_WINDOW_ID,SSH_TTYall unset.Root cause
hooks/lib/notification-channel.tsgetNotificationChannel()infers "has a speaker" from terminal identity (TERM,TERM_PROGRAM,KITTY_WINDOW_ID,SSH_TTY). The desktop app is an interactive session with a speaker that sets none of them, so it fell into the launchd/cronheadlessbranch.Fix
Count
CLAUDE_CODE_ENTRYPOINT === 'claude-desktop'as terminal identity. Rule 1 (explicitLIFEOS_NOTIFICATION_CHANNELwins) is untouched and evaluated first, so the spawners that stamp childrenheadless(Inference, CarrierProbe, PULSE lib, github-work; remote channels imessage/telegram/siri) are unaffected.CLAUDE_CODE_CHILD_SESSIONis not used: it is set in the desktop main session too and is not a channel signal.How tested
bun test hooks/lib/notification-channel.test.ts— 4 pass; on the shipped file the first case fails (entrypoint set, no terminal vars →headless, expecteddesktop). Cases: desktop marker alone →desktop; marker + explicitheadless/imessage→ the explicit value; nothing set orCLAUDE_CODE_ENTRYPOINT=cli→headless;TERMalone →desktop(unchanged).Repro on a clean tree: from a desktop-app session,
env -u TERM -u TERM_PROGRAM bun -e 'import {getNotificationChannel} from "./hooks/lib/notification-channel"; console.log(getNotificationChannel())'in~/.claude→headlessbefore,desktopafter; the next Stop hook plays. Voice is back on the live desktop-app install with this change.Note on convention: this adds a
bun:testfile next to the lib (the repo has no runner today); happy to fold it into a probe table if that is preferred.🤖 Generated with Claude Code