* docs: add Copilot CLI hook setup to notifications guide Add GitHub Copilot CLI section with hooks for notifications and sidebar status pills (userPromptSubmitted, agentStop, errorOccurred, sessionEnd). Includes link to official GitHub hooks documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: address PR feedback for Copilot CLI hooks - Use if/else instead of &&/|| to avoid false-positive osascript fallback - Fix jq path: .error.message → .errorMessage for Copilot CLI schema - Remove --icon/--color flags (let cmux handle styling) - Add clear-notifications side-effect note - Add concrete repo-level config example - Document set-status/clear-status in CLI Commands section Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Harley Adams <harley.adams@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
182 lines
5.1 KiB
Markdown
182 lines
5.1 KiB
Markdown
# Notifications
|
|
|
|
cmux 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 cmux is available)
|
|
command -v cmux &>/dev/null && cmux notify --title "Done" --body "Task complete"
|
|
|
|
# With fallback to macOS notifications
|
|
command -v cmux &>/dev/null && cmux notify --title "Done" --body "Task complete" || osascript -e 'display notification "Task complete" with title "Done"'
|
|
```
|
|
|
|
## Detection
|
|
|
|
Check if `cmux` CLI is available before using it:
|
|
|
|
```bash
|
|
# Shell
|
|
if command -v cmux &>/dev/null; then
|
|
cmux notify --title "Hello"
|
|
fi
|
|
|
|
# One-liner with fallback
|
|
command -v cmux &>/dev/null && cmux 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("cmux"):
|
|
subprocess.run(["cmux", "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
|
|
cmux notify --title "Build Complete"
|
|
|
|
# With subtitle and body
|
|
cmux notify --title "Claude Code" --subtitle "Permission" --body "Approval needed"
|
|
|
|
# Notify specific tab/panel
|
|
cmux notify --title "Done" --tab 0 --panel 1
|
|
```
|
|
|
|
## Integration Examples
|
|
|
|
### Claude Code
|
|
|
|
See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code) for hook configuration.
|
|
|
|
### GitHub Copilot CLI
|
|
|
|
Copilot CLI supports [hooks](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/use-hooks) that run shell commands at key lifecycle events. Add to `~/.copilot/config.json`:
|
|
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"userPromptSubmitted": [
|
|
{
|
|
"type": "command",
|
|
"bash": "if command -v cmux &>/dev/null; then cmux set-status copilot_cli Running; fi",
|
|
"timeoutSec": 3
|
|
}
|
|
],
|
|
"agentStop": [
|
|
{
|
|
"type": "command",
|
|
"bash": "if command -v cmux &>/dev/null; then cmux notify --title 'Copilot CLI' --body 'Done'; cmux set-status copilot_cli Idle; else osascript -e 'display notification \"Done\" with title \"Copilot CLI\"'; fi",
|
|
"timeoutSec": 5
|
|
}
|
|
],
|
|
"errorOccurred": [
|
|
{
|
|
"type": "command",
|
|
"bash": "if command -v cmux &>/dev/null; then cmux notify --title 'Copilot CLI' --subtitle 'Error' --body \"$(cat | jq -r '.errorMessage // \"An error occurred\"' 2>/dev/null | head -c 100)\"; cmux set-status copilot_cli Error; else osascript -e 'display notification \"An error occurred\" with title \"Copilot CLI\"'; fi",
|
|
"timeoutSec": 5
|
|
}
|
|
],
|
|
"sessionEnd": [
|
|
{
|
|
"type": "command",
|
|
"bash": "if command -v cmux &>/dev/null; then cmux clear-status copilot_cli; fi",
|
|
"timeoutSec": 3
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Or for repo-level hooks, create `.github/hooks/notify.json`:
|
|
|
|
```json
|
|
{
|
|
"version": 1,
|
|
"hooks": {
|
|
"userPromptSubmitted": [ ... ],
|
|
"agentStop": [ ... ]
|
|
}
|
|
}
|
|
```
|
|
|
|
### OpenAI Codex
|
|
|
|
Add to `~/.codex/config.toml`:
|
|
|
|
```toml
|
|
notify = ["bash", "-c", "command -v cmux &>/dev/null && cmux 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 cmux &>/dev/null && cmux 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/cmux-notify.js`:
|
|
|
|
```javascript
|
|
export const CmuxNotificationPlugin = async ({ $, }) => {
|
|
const notify = async (title, body) => {
|
|
try {
|
|
await $`command -v cmux && cmux 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
|
|
|
|
cmux 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
|
|
|
|
```
|
|
cmux notify --title <text> [--subtitle <text>] [--body <text>] [--tab <id|index>] [--panel <id|index>]
|
|
cmux list-notifications
|
|
cmux clear-notifications
|
|
cmux set-status <key> <value>
|
|
cmux clear-status <key>
|
|
cmux ping
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Always check availability first** - Use `command -v cmux` before calling
|
|
2. **Provide fallbacks** - Use `|| osascript` for macOS fallback
|
|
3. **Keep notifications concise** - Title should be brief, use body for details
|