Notifications
OpenTUI asks the terminal emulator to show a desktop notification with an operating system command (OSC) sequence. It does not call host notification tools.
const ok = renderer.triggerNotification("Build finished", "OpenTUI")renderer.triggerNotification(message, title?) returns true when OpenTUI selects a protocol and queues its output. It does not confirm that the terminal or desktop displayed a notification.
The method returns false in these cases:
- The renderer is destroyed.
- OpenTUI has not selected a notification protocol.
- Notification detection or an override disabled the capability.
- Local encoding, allocation, or output generation fails.
Detection timing#
Check detection state through renderer capabilities:
if (renderer.capabilities?.notifications) {
renderer.triggerNotification("Tests passed", "CI")
}
renderer.on("capabilities", (capabilities) => {
console.log("notification capability", capabilities.notifications)
})createCliRenderer() starts terminal queries, but it does not wait for all replies before it resolves. The renderer updates capabilities and emits the capabilities event as replies arrive. The startup capability handler stops after 5 seconds.
A false value can mean that no protocol is supported. It can also mean that asynchronous detection has not selected one yet. Remote and multiplexer sessions often start in this state. Read Terminal capabilities for the complete detection lifecycle.
OpenTUI uses these sources, from strongest to weakest:
OPENTUI_NOTIFICATION_PROTOCOLoverrides.- OSC 99 and iTerm2 capability-query replies.
- XTVERSION terminal identity.
- Terminal environment heuristics.
An OSC 99 reply must include the OpenTUI query identifier, p=?, and title support. An iTerm2 capability reply selects OSC 9 only when its feature codes contain No.
Known terminal identities select these protocols:
| Protocol | Detected terminal families |
|---|---|
| OSC 99 | Kitty and foot |
| OSC 777 | Ghostty, WezTerm, Warp, hterm, Blink, Contour, VTE, GNOME Terminal, Tilix, Terminator, Xfce, rxvt, and Windows Terminal |
| OSC 9 | iTerm, Apple Terminal, Terminal.app, and ConEmu |
Environment hints can select the same protocols. TERM_FEATURES with No selects OSC 9. WT_SESSION selects OSC 777. Detection is terminal-mediated and does not call notify-send, AppleScript, PowerShell, or another platform notification command.
Protocol output#
| Protocol | Output behavior |
|---|---|
| OSC 99 | Sends base64 title and body payloads with one generated notification ID |
| OSC 777 | Sends notify, title, and body fields. Control bytes and semicolons become spaces |
| OSC 9 | Combines a nonempty title and body as title: message. Control bytes become spaces |
When no title is supplied, each protocol sends the message in its supported body form.
Terminal behavior#
Terminal and operating system settings decide how a notification appears. A terminal can ignore a valid sequence. Some terminals show a banner only while unfocused. Desktop settings can also store a notification without showing a banner.
Multiplexers#
tmux does not forward raw notification OSC sequences. When OpenTUI detects
renderer.capabilities?.multiplexer === "tmux", it wraps the selected protocol in tmux device control string (DCS)
passthrough. tmux must allow passthrough:
set -g allow-passthrough onUse allow-passthrough all if notifications need to work from panes that are not visible.
Zellij notification forwarding uses OSC 99. OpenTUI ignores inherited outer-terminal heuristics inside Zellij. It enables notifications only after a matching OSC 99 query reply or an explicit protocol override. Selected OSC 99 output remains raw instead of using tmux wrapping.
For a local GNU Screen session with STY set, OpenTUI wraps a selected protocol in Screen DCS passthrough. Screen does not itself select a notification protocol, so detection or an override must still enable one.
In an SSH session, the renderer sends the sequence to the client terminal. The server desktop is not the notification destination.
Overrides#
Use an override when detection cannot identify the final terminal path:
OPENTUI_NOTIFICATION_PROTOCOL=osc99
OPENTUI_NOTIFICATIONS=0OPENTUI_NOTIFICATION_PROTOCOL accepts these protocol values:
| Value | Result |
|---|---|
osc9, osc777, osc99 |
Force that protocol |
none, 0, false, off |
Disable notification protocols |
1, true, on |
Keep automatic selection |
The string comparisons for protocol names and words are case-insensitive. OPENTUI_NOTIFICATIONS=0, false, or off also disables notifications. Other values do not force support. An explicit disable remains authoritative when later query replies arrive.
See Environment variables for configuration timing. Protocol overrides assert support and can still produce no desktop notification when a terminal or multiplexer does not accept that protocol.
Example#
See the notification demo for detection state, protocol output, and interactive notification requests.
Next#
- Renderer documents the renderer and its capability event.
- Terminal capabilities explains query and remote-session state.
- Environment variables lists notification overrides.
- SSH defines remote renderer ownership and transport.
- Troubleshooting routes notification and multiplexer failures.