From 3046531bdd26c23fdea4057288e7046c0c6d61ef Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:20:55 -0800 Subject: [PATCH] Add notifications documentation for AI agent integrations Document how to use cmuxterm CLI for notifications with Claude Code, Codex, and OpenCode. Includes one-liner examples with automatic detection and fallback to macOS notifications. --- docs/notifications.md | 156 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 docs/notifications.md diff --git a/docs/notifications.md b/docs/notifications.md new file mode 100644 index 00000000..151eb4df --- /dev/null +++ b/docs/notifications.md @@ -0,0 +1,156 @@ +# Notifications + +cmuxterm provides a notification panel for AI agents like Claude Code, Codex, and OpenCode. Notifications appear in a dedicated panel and trigger macOS system notifications. + +## Quick Start + +```bash +# Send a notification (if cmuxterm is available) +command -v cmuxterm &>/dev/null && cmuxterm notify --title "Done" --body "Task complete" + +# With fallback to macOS notifications +command -v cmuxterm &>/dev/null && cmuxterm notify --title "Done" --body "Task complete" || osascript -e 'display notification "Task complete" with title "Done"' +``` + +## Detection + +Check if `cmuxterm` CLI is available before using it: + +```bash +# Shell +if command -v cmuxterm &>/dev/null; then + cmuxterm notify --title "Hello" +fi + +# One-liner with fallback +command -v cmuxterm &>/dev/null && cmuxterm notify --title "Hello" || osascript -e 'display notification "" with title "Hello"' +``` + +```python +# Python +import shutil +import subprocess + +def notify(title: str, body: str = ""): + if shutil.which("cmuxterm"): + subprocess.run(["cmuxterm", "notify", "--title", title, "--body", body]) + else: + # Fallback to macOS + subprocess.run(["osascript", "-e", f'display notification "{body}" with title "{title}"']) +``` + +## CLI Usage + +```bash +# Simple notification +cmuxterm notify --title "Build Complete" + +# With subtitle and body +cmuxterm notify --title "Claude Code" --subtitle "Permission" --body "Approval needed" + +# Notify specific tab/panel +cmuxterm notify --title "Done" --tab 0 --panel 1 +``` + +## Integration Examples + +### Claude Code Hooks + +Add to `~/.claude/settings.json`: + +```json +{ + "hooks": { + "Notification": [ + { + "matcher": "idle_prompt", + "hooks": [ + { + "type": "command", + "command": "command -v cmuxterm &>/dev/null && cmuxterm notify --title 'Claude Code' --body 'Waiting for input' || osascript -e 'display notification \"Waiting for input\" with title \"Claude Code\"'" + } + ] + }, + { + "matcher": "permission_prompt", + "hooks": [ + { + "type": "command", + "command": "command -v cmuxterm &>/dev/null && cmuxterm notify --title 'Claude Code' --subtitle 'Permission' --body 'Approval needed' || osascript -e 'display notification \"Approval needed\" with title \"Claude Code\"'" + } + ] + } + ] + } +} +``` + +### OpenAI Codex + +Add to `~/.codex/config.toml`: + +```toml +notify = ["bash", "-c", "command -v cmuxterm &>/dev/null && cmuxterm notify --title Codex --body \"$(echo $1 | jq -r '.\"last-assistant-message\" // \"Turn complete\"' 2>/dev/null | head -c 100)\" || osascript -e 'display notification \"Turn complete\" with title \"Codex\"'", "--"] +``` + +Or create a simple script `~/.local/bin/codex-notify.sh`: + +```bash +#!/bin/bash +MSG=$(echo "$1" | jq -r '."last-assistant-message" // "Turn complete"' 2>/dev/null | head -c 100) +command -v cmuxterm &>/dev/null && cmuxterm notify --title "Codex" --body "$MSG" || osascript -e "display notification \"$MSG\" with title \"Codex\"" +``` + +Then use: +```toml +notify = ["bash", "~/.local/bin/codex-notify.sh"] +``` + +### OpenCode Plugin + +Create `.opencode/plugins/cmuxterm-notify.js`: + +```javascript +export const CmuxNotificationPlugin = async ({ $, }) => { + const notify = async (title, body) => { + try { + await $`command -v cmuxterm && cmuxterm notify --title ${title} --body ${body}`; + } catch { + await $`osascript -e ${"display notification \"" + body + "\" with title \"" + title + "\""}`; + } + }; + + return { + event: async ({ event }) => { + if (event.type === "session.idle") { + await notify("OpenCode", "Session idle"); + } + }, + }; +}; +``` + +## Environment Variables + +cmuxterm sets these in child shells: + +| Variable | Description | +|----------|-------------| +| `CMUX_SOCKET_PATH` | Path to control socket | +| `CMUX_TAB_ID` | UUID of the current tab | +| `CMUX_PANEL_ID` | UUID of the current panel | + +## CLI Commands + +``` +cmuxterm notify --title [--subtitle ] [--body ] [--tab ] [--panel ] +cmuxterm list-notifications +cmuxterm clear-notifications +cmuxterm ping +``` + +## Best Practices + +1. **Always check availability first** - Use `command -v cmuxterm` before calling +2. **Provide fallbacks** - Use `|| osascript` for macOS fallback +3. **Keep notifications concise** - Title should be brief, use body for details