# 通知

cmuxはデスクトップ通知をサポートしており、AIエージェントやスクリプトが注意を必要とするときに通知できます。

## ライフサイクル

1.  受信：通知がパネルに表示され、デスクトップアラートが発火（抑制されていない場合）
2.  未読：ワークスペースタブにバッジを表示
3.  既読：そのワークスペースを表示するとクリア
4.  クリア済み：パネルから削除

### 抑制

デスクトップアラートは以下の場合に抑制されます：

-   cmuxウィンドウにフォーカスがある
-   通知を送信した特定のワークスペースがアクティブ
-   通知パネルが開いている

### 通知パネル

`⌘⇧I`を押して通知パネルを開きます。通知をクリックするとそのワークスペースにジャンプします。`⌘⇧U`を押すと、最新の未読通知があるワークスペースに直接ジャンプします。

## カスタムコマンド

通知がスケジュールされるたびにシェルコマンドを実行できます。設定 > アプリ > 通知コマンドで設定してください。コマンドは/bin/sh -cで実行され、以下の環境変数が使用可能です：

| 変数 | 説明 |
| --- | --- |
| `CMUX_NOTIFICATION_TITLE` | 通知タイトル（ワークスペース名またはアプリ名） |
| `CMUX_NOTIFICATION_SUBTITLE` | 通知サブタイトル |
| `CMUX_NOTIFICATION_BODY` | 通知本文 |

Examples

```
# Text-to-speech
say "$CMUX_NOTIFICATION_TITLE"

# Custom sound file
afplay /path/to/sound.aiff

# Log to file
echo "$CMUX_NOTIFICATION_TITLE: $CMUX_NOTIFICATION_BODY" >> ~/notifications.log
```

コマンドはシステムサウンドピッカーとは独立して実行されます。カスタムコマンドのみを使用する場合はピッカーを「なし」に設定し、システムサウンドとカスタムアクションの両方を使用する場合は両方を有効にしてください。

## 通知フック

`cmux.json` で通知フックを定義すると、すべての通知ポリシーを stdin の JSON として受け取れます。各フックは stdout に JSON を返します。フックは既定ではオフです。cmux は `notifications.hooks` に有効なフックが 1 つ以上ある場合にのみ実行します。cmux は返された通知テキストと効果を適用するため、バナーのフィルタ、サイドバー履歴の保持またはスキップ、サウンドの実行、後続フックの停止を制御できます。

cmux.json

```
{
  "notifications": {
    "hooks": [
      {
        "id": "quiet-docs",
        "command": "sed 's/"desktop":true/"desktop":false/'",
        "timeoutSeconds": 20
      }
    ]
  }
}
```

フックの入力と出力

```
{
  "version": 1,
  "notification": {
    "workspaceId": "3B3F0D83-...",
    "surfaceId": "7E9C1A02-...",
    "title": "Codex",
    "subtitle": "Waiting",
    "body": "Agent needs input"
  },
  "context": {
    "cwd": "/path/to/project",
    "configPath": "/path/to/project/.cmux/cmux.json",
    "hookId": "quiet-docs",
    "appFocused": false,
    "focusedPanel": false
  },
  "agent": {
    "kind": "claude",
    "category": "turn-complete",
    "pending": false,
    "isSubagent": true
  },
  "effects": {
    "record": true,
    "markUnread": true,
    "reorderWorkspace": true,
    "desktop": true,
    "sound": true,
    "command": true,
    "paneFlash": true
  }
}
```

フックはグローバル `~/.config/cmux/cmux.json` と、現在のワークスペースまでの親ディレクトリにあるプロジェクト `.cmux/cmux.json` から継承されます。プロジェクトフックは、他のプロジェクト `cmux.json` コマンドと同じ信頼プロンプトを実行前に使用します。Feed の承認バナーもこれらのフックを通ります。`desktop` を無効にすると、Feed 項目は cmux に残したままネイティブバナーを抑制します。継承したフックを無視するには、プロジェクト設定で `notifications.hooksMode` を `replace` に設定します。フックが失敗、タイムアウト、または無効な JSON を返した場合、cmux は既定の通知動作を使用し、フック失敗アラートを表示します。

### エージェントイベントコンテキスト

エージェントの完了シグナルに由来する通知には、読み取り専用の `agent` オブジェクトが付きます。`kind` は安定した小文字のエージェントスラッグ（claude、codex、grok など）、`category` は turn-complete、needs-permission、idle-reminder のいずれか、`pending` はバックグラウンド作業が残ったままターンが終了した場合に true、`isSubagent` はネストされたサブエージェントセッションの場合に true です。エージェント以外の通知ではこのオブジェクトは省略されます。同じ値は CMUX\_NOTIFICATION\_AGENT\_KIND、CMUX\_NOTIFICATION\_AGENT\_CATEGORY、CMUX\_NOTIFICATION\_AGENT\_PENDING、CMUX\_NOTIFICATION\_AGENT\_IS\_SUBAGENT としてフックプロセスの環境変数にもエクスポートされます。たとえば次のフックは、他の動作はそのままに、サブエージェント完了時のバナー・サウンド・ペインフラッシュだけを抑制します:

サブエージェント完了通知の抑制

```
{
  "notifications": {
    "hooks": [
      {
        "id": "mute-subagent-completions",
        "command": "if [ \"${CMUX_NOTIFICATION_AGENT_IS_SUBAGENT-0}\" = \"1\" ] && [ \"$CMUX_NOTIFICATION_AGENT_CATEGORY\" = \"turn-complete\" ]; then printf '{\"effects\":{\"desktop\":false,\"sound\":false,\"paneFlash\":false}}'; fi"
      }
    ]
  }
}
```

フックを設定していない場合、通知動作は cmux の組み込み既定とまったく同じです。フックの設定こそが、配信の判断をスクリプトに委ねる明示的なオプトインです。なお、cmux の組み込みサブエージェント抑制（`automation.suppressSubagentNotifications`、既定でオン）は、サブエージェントの完了イベントをフックに届く前に破棄します。フック側でサブエージェントイベントを受け取って独自に判断したい場合は、この設定をオフにしてください。

## 通知の送信

### CLI

```
cmux notify --title "Task Complete" --body "Your build finished"
cmux notify --title "Claude Code" --subtitle "Waiting" --body "Agent needs input"
```

### OSC 777（シンプル）

RXVTプロトコルはタイトルと本文の固定フォーマットを使用します：

```
printf '\e]777;notify;My Title;Message body here\a'
```

Shell function

```
notify_osc777() {
    local title="$1"
    local body="$2"
    printf '\e]777;notify;%s;%s\a' "$title" "$body"
}

notify_osc777 "Build Complete" "All tests passed"
```

### OSC 99（リッチ）

Kittyプロトコルはサブタイトルと通知IDをサポートします：

```
# Format: ESC ] 99 ; <params> ; <payload> ESC \

# Simple notification
printf '\e]99;i=1;e=1;d=0:Hello World\e\\'

# With title, subtitle, and body
printf '\e]99;i=1;e=1;d=0;p=title:Build Complete\e\\'
printf '\e]99;i=1;e=1;d=0;p=subtitle:Project X\e\\'
printf '\e]99;i=1;e=1;d=1;p=body:All tests passed\e\\'
```

| 機能 | OSC 99 | OSC 777 |
| --- | --- | --- |
| タイトル + 本文 | あり | あり |
| サブタイトル | あり | なし |
| 通知ID | あり | なし |
| 複雑さ | 高い | 低い |

シンプルな通知にはOSC 777を使用してください。サブタイトルや通知IDが必要な場合はOSC 99を使用してください。最も簡単な連携にはCLI（cmux notify）を使用してください。

## Claude Codeフック

cmuxは[Claude Code](https://docs.anthropic.com/en/docs/claude-code)とフックで連携し、タスク完了時に通知します。

### 1\. フックスクリプトの作成

~/.claude/hooks/cmux-notify.sh

```
#!/bin/bash
# Outside cmux there is no socket to talk to, so do nothing.
[ -S /tmp/cmux.sock ] || exit 0

payload=$(cat)
field() { printf '%s' "$payload" | jq -r "$1 // empty"; }

event=$(field .hook_event_name)
if [ "$event" = "Stop" ]; then
    cmux notify --title "Claude Code" --body "Session complete"
elif [ "$event" = "SubagentStop" ]; then
    cmux notify --title "Claude Code" --body "Agent finished"
fi
```

```
chmod +x ~/.claude/hooks/cmux-notify.sh
```

### 2\. Claude Codeの設定

~/.claude/settings.json

```
{
  "hooks": {
    "SubagentStop": [
      {
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/cmux-notify.sh" }]
      }
    ],
    "Stop": [
      {
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/cmux-notify.sh" }]
      }
    ]
  }
}
```

フックを適用するにはClaude Codeを再起動してください。

## GitHub Copilot CLI

Copilot CLIは、プロンプト送信、エージェント停止、エラーなどのライフサイクルイベントでシェルコマンドを実行する[フック](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/use-hooks)をサポートしています。

~/.copilot/config.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; fi",
        "timeoutSec": 5
      }
    ],
    "errorOccurred": [
      {
        "type": "command",
        "bash": "if command -v cmux &>/dev/null; then cmux notify --title 'Copilot CLI' --subtitle 'Error' --body 'An error occurred'; cmux set-status copilot_cli Error; fi",
        "timeoutSec": 5
      }
    ],
    "sessionEnd": [
      {
        "type": "command",
        "bash": "if command -v cmux &>/dev/null; then cmux clear-status copilot_cli; fi",
        "timeoutSec": 3
      }
    ]
  }
}
```

リポジトリレベルのフックには、同じ構造で.github/hooks/notify.jsonファイルを作成してください：

.github/hooks/notify.json

```
{
  "version": 1,
  "hooks": {
    "userPromptSubmitted": [ ... ],
    "agentStop": [ ... ]
  }
}
```

## 連携の例

### 長時間コマンド後の通知

~/.zshrc

```
# Add to your shell config
notify-after() {
  "$@"
  local exit_code=$?
  if [ $exit_code -eq 0 ]; then
    cmux notify --title "✓ Command Complete" --body "$1"
  else
    cmux notify --title "✗ Command Failed" --body "$1 (exit $exit_code)"
  fi
  return $exit_code
}

# Usage: notify-after npm run build
```

### Python

python

```
import sys

def notify(title: str, body: str):
    """Send OSC 777 notification."""
    sys.stdout.write(f'\x1b]777;notify;{title};{body}\x07')
    sys.stdout.flush()

notify("Script Complete", "Processing finished")
```

### Node.js

node

```
function notify(title, body) {
  process.stdout.write(`\x1b]777;notify;${title};${body}\x07`);
}

notify('Build Done', 'webpack finished');
```

### tmuxパススルー

cmux内でtmuxを使用する場合、パススルーを有効にしてください：

.tmux.conf

```
set -g allow-passthrough on
```

```
printf '\ePtmux;\e\e]777;notify;Title;Body\a\e\\'
```

Canonical: https://cmux.com/ja/docs/notifications

Documentation index: https://cmux.com/llms.txt
