Tools
Tui Notify
OpenClaw plugin for macOS desktop notifications when terminal TUI replies finish and Ghostty is unfocused.
Install
openclaw plugins install clawhub:openclaw-tui-notify
README
# openclaw-tui-notify
`openclaw-tui-notify` is an OpenClaw plugin for a simple workflow:
- you run `openclaw tui` inside `Ghostty`
- you switch to another app while a reply is still being generated
- when the final assistant reply finishes, you get a macOS notification
It intentionally does not notify for idle shells, tool-call intermediates, or background cron/run sessions.
## Status
This project is currently optimized for:
- macOS
- Ghostty as the terminal
- OpenClaw TUI sessions
- desktop notifications via `terminal-notifier`
## How It Works
The plugin uses two OpenClaw plugin hooks:
1. `before_dispatch`
2. `before_message_write`
It only continues when all of these are true:
- the session looks like a local interactive agent session
- the message is an `assistant` message
- `stopReason === "stop"`
- the reply is not empty
- the reply is not a tool/thinking/control artifact
- the session recently had a matching local `user` turn
After that, `notify-if-away.mjs` checks one thing:
- is the active app still `Ghostty`?
If yes, the notification is suppressed. If not, a macOS notification is sent.
## Why It Only Uses Layer 1
This project deliberately uses a narrow presence check:
- `Ghostty` frontmost or not
It does not currently try to detect:
- which Ghostty tab is focused
- which tmux window is focused
- which tmux pane originally ran the TUI session
That is intentional. In the current OpenClaw event model, this plugin runs inside `openclaw-gateway`, so it does not have a verified canonical tmux pane identity for the reply being written. The repo documents the future conditions required to add pane/window-level matching safely in [spec.md](./spec.md).
## Prerequisites
- OpenClaw with plugin support
- Ghostty
- macOS Accessibility permission for app-focus detection
- [`terminal-notifier`](https://github.com/julienXX/terminal-notifier)
Homebrew example:
```bash
brew install terminal-notifier
```
## Install
### Recommended: ClawHub
Available now. This is the most direct install path for OpenClaw users.
```bash
openclaw plugins install clawhub:openclaw-tui-notify
```
### Package Install: npm
Available now. OpenClaw will also try npm-safe plugin specs.
```bash
openclaw plugins install openclaw-tui-notify
```
### Development Install: git clone
Clone the repo anywhere you like, then install the plugin from the repository root:
```bash
openclaw plugins install --link --dangerously-force-unsafe-install /absolute/path/to/openclaw-tui-notify
```
Then restart OpenClaw Gateway.
## Configuration
Copy [config/config.env.example](./config/config.env.example) to `config.env` in the repo root:
```bash
cp config/config.env.example config.env
```
Supported settings:
- `OPENCLAW_TUI_NOTIFY_ENABLED=true|false`
- `OPENCLAW_TUI_NOTIFY_SOUND=Glass`
- `OPENCLAW_TUI_NOTIFY_DEBUG=true|false`
- `OPENCLAW_TUI_NOTIFY_STATE_DIR=/custom/path`
- `OPENCLAW_TUI_NOTIFY_TERMINAL_NOTIFIER_PATH=/path/to/terminal-notifier`
- `OPENCLAW_TUI_NOTIFY_NON_TUI_CHANNELS=feishu,telegram,...`
- `OPENCLAW_TUI_NOTIFY_SESSION_PREFIXES=agent:`
- `OPENCLAW_TUI_NOTIFY_EXCLUDE_SESSION_TOKENS=:cron:,:run:`
- `OPENCLAW_TUI_NOTIFY_FALLBACK_TITLE=OpenClaw`
Default log directory:
- macOS: `~/Library/Logs/openclaw-tui-notify`
- other systems: `~/.local/state/openclaw-tui-notify`
## Debugging
When `OPENCLAW_TUI_NOTIFY_DEBUG=true`, the project writes:
- `debug.log`
inside `OPENCLAW_TUI_NOTIFY_STATE_DIR`.
Each row includes a `source` field so you can still distinguish plugin-side filtering from notify-script decisions.
These logs use local timestamps with timezone offsets, for example:
```text
2026-04-13T00:22:41.912+08:00
```
## Manual Test
```bash
node notify-if-away.mjs "test-session" "This should appear when Ghostty is not frontmost"
```
## Limitations
- If you stay in Ghostty but switch to another tab or tmux window, the notification is still suppressed.
- OpenClaw currently labels TUI traffic as `webchat` in some environments, so channel metadata alone is not enough to distinguish browser sessions from terminal TUI sessions.
- macOS sleep / Focus modes / notification style can affect whether a banner is visibly shown even when the notification request was successfully sent.
## Notes On Session And Channel Matching
- Notification titles are derived from the trailing segment of `sessionKey`, not hardcoded to a fixed session name.
- The fallback title is configurable through `OPENCLAW_TUI_NOTIFY_FALLBACK_TITLE`.
- Session targeting is configurable through `OPENCLAW_TUI_NOTIFY_SESSION_PREFIXES` and `OPENCLAW_TUI_NOTIFY_EXCLUDE_SESSION_TOKENS`.
- Explicit non-TUI channels are configurable through `OPENCLAW_TUI_NOTIFY_NON_TUI_CHANNELS`.
## Repository Layout
- [index.ts](./index.ts): OpenClaw plugin entry
- [notify-if-away.mjs](./notify-if-away.mjs): away check + notification sender
- [package.json](./package.json): publishable package metadata
- [openclaw.plugin.json](./openclaw.plugin.json): OpenClaw plugin metadata
- [config/config.env.example](./config/config.env.example): local config template
- [spec.md](./spec.md): design notes, constraints, and future directions
## License
MIT
tools
Comments
Sign in to leave a comment