#알림

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에 활성화된 훅이 하나 이상 있을 때만 실행합니다. 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
  },
  "effects": {
    "record": true,
    "markUnread": true,
    "reorderWorkspace": true,
    "desktop": true,
    "sound": true,
    "command": true,
    "paneFlash": true
  }
}

훅은 전역 ~/.config/cmux/cmux.json과 현재 workspace까지의 부모 디렉터리에 있는 프로젝트 .cmux/cmux.json 파일에서 상속됩니다. 프로젝트 훅은 실행 전에 다른 프로젝트 cmux.json 명령과 동일한 신뢰 프롬프트를 사용합니다. Feed 승인 배너도 이 훅을 통과합니다. desktop을 비활성화하면 네이티브 배너는 숨기고 Feed 항목은 cmux에 유지합니다. 상속된 훅을 무시하려면 프로젝트 설정에서 notifications.hooksModereplace로 설정하세요. 훅이 실패하거나 시간 초과되거나 잘못된 JSON을 반환하면 cmux는 기본 알림 동작을 사용하고 훅 실패 알림을 표시합니다.

#알림 보내기

#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 99OSC 777
제목 + 본문
부제목아니오
알림 ID아니오
복잡도높음낮음
간단한 알림에는 OSC 777을 사용하세요. 부제목이나 알림 ID가 필요한 경우 OSC 99를 사용하세요. 가장 쉬운 통합을 위해 CLI(cmux notify)를 사용하세요.

#Claude Code hooks

cmux는 hooks를 통해 Claude Code와 통합하여 작업이 완료되면 알려줍니다.

#1. 훅 스크립트 생성

~/.claude/hooks/cmux-notify.sh
#!/bin/bash
# Skip if not in cmux
[ -S /tmp/cmux.sock ] || exit 0

EVENT=$(cat)
EVENT_TYPE=$(echo "$EVENT" | jq -r '.hook_event_name // "unknown"')
TOOL=$(echo "$EVENT" | jq -r '.tool_name // ""')

case "$EVENT_TYPE" in
    "Stop")
        cmux notify --title "Claude Code" --body "Session complete"
        ;;
    "PostToolUse")
        [ "$TOOL" = "Task" ] && cmux notify --title "Claude Code" --body "Agent finished"
        ;;
esac
chmod +x ~/.claude/hooks/cmux-notify.sh

#2. Claude Code 설정

~/.claude/settings.json
{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/cmux-notify.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Task",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/cmux-notify.sh"
          }
        ]
      }
    ]
  }
}

hooks를 적용하려면 Claude Code를 재시작하세요.

#GitHub Copilot CLI

Copilot CLI는 프롬프트 제출, 에이전트 중지, 오류 등 라이프사이클 이벤트에서 셸 명령을 실행하는 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
      }
    ]
  }
}

저장소 수준 hooks의 경우, 같은 구조로 .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\\'