Context: Studying claude-code-source-code-full (backup branch)
Claude Code Notification System
Claude Code uses terminal-specific OSC sequences to notify users when it needs attention (e.g., permission prompts, elicitation dialogs). Each terminal gets its own protocol:
| Terminal | OSC Code | Mechanism |
|---|---|---|
| iTerm2 | OSC 9 | iTerm2 proprietary sequence |
| Kitty | OSC 99 | Multi-part: title, body, activate |
| Ghostty | OSC 777 | notify;title;message |
| Apple Terminal | BEL (\x07) | Raw bell (only if bell enabled in profile) |
All sequences are wrapped via wrapForMultiplexer() for tmux/screen DCS passthrough, except BEL which stays raw so tmux can trigger its bell-action.
Configuration
Setting: preferredNotifChannel (set via /config or claude config set)
Valid values (from src/utils/configConstants.ts):
auto(default): detects terminal viaTERM_PROGRAMand picks matching protocoliterm2,iterm2_with_bell,kitty,ghostty,terminal_bell: force a specific channelnotifications_disabled: suppresses all notifications
Idle Threshold
Notifications only fire after the user has been idle. Controlled by useNotifyAfterTimeout (src/hooks/useNotifyAfterTimeout.ts):
- Hardcoded at 6 seconds (
DEFAULT_INTERACTION_THRESHOLD_MS = 6000) - A
setIntervalchecks every 6s whether the user has typed anything recently - If idle > 6s, notification fires; if actively typing, suppressed
- Interaction timestamp updated in
App.tsx’sprocessKeysInBatch - Not configurable. No setting, CLI flag, or env var to change the threshold.
Environment Variables
| Variable | Effect |
|---|---|
TERM_PROGRAM | Terminal detection for auto channel routing |
TMUX | Enables tmux DCS passthrough wrapping |
STY | Enables GNU screen passthrough wrapping |
SSH_CONNECTION | Gates native clipboard (pbcopy); affects OSC pipeline |
LC_TERMINAL | Special-cases iTerm2 over SSH (disables tmux -w to avoid crashes) |
NODE_ENV=test | Suppresses notifications entirely |
USER_TYPE=ant | Gates OSC 21337 tab-status emission (Anthropic-internal) |
Key Source Files
src/ink/termio/osc.ts: OSC sequence generation, multiplexer wrappingsrc/ink/useTerminalNotification.ts: React hook exposing notify methods per terminalsrc/services/notifier.ts: Notification dispatch (channel routing, analytics)src/hooks/useNotifyAfterTimeout.ts: Idle detection and threshold logicsrc/utils/configConstants.ts: Valid channel enumsrc/utils/env.ts: Terminal detection viaTERM_PROGRAM
Hook Integration
The settings hook system has a Notification event. When a notification fires, executeNotificationHooks (src/services/notifier.ts:25) runs any user-configured notification hooks before dispatching the terminal notification. This lets users run custom shell commands on notification.