AI CLI の入力待ちを音と Discord で通知する
Claude Code・Codex CLI が承認待ちや応答完了になったら、音を鳴らして Discord にもプッシュ通知を飛ばす設定。なぜ Slack ではなく Discord か。
長めのタスクを Claude Code や Codex CLI に投げて、横で別の作業をしていると、承認待ちで止まっているのに気付かず数十分経つことがある。音とスマホ通知で「待ってます」を拾えるようにする。
所要時間 10 分。Webhook URL 1 個と settings.json への追記だけ。
何をフックするか
Claude Code には hooks という仕組みがあり、セッションのイベントに任意のシェルコマンドを引っ掛けられる。今回使うのは:
Notification— Claude がユーザー入力(承認・追加プロンプト)を待つときStop— メインセッションが応答を終えたときSubagentStop— サブエージェントが終わったとき
Codex CLI は ~/.codex/config.toml の notify キーで、ターン完了時に任意コマンドを呼べる。
1. 音を鳴らす(最小構成)
Claude Code(macOS)
~/.claude/settings.json に追記:
{
"hooks": {
"Notification": [
{
"hooks": [
{ "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" }
]
}
]
}
}
🟢 安全 / 標準同梱の音を鳴らすだけ。
Claude Code(Linux)
# 必要なら
sudo apt install -y pulseaudio-utils
{
"hooks": {
"Notification": [
{
"hooks": [
{ "type": "command", "command": "paplay /usr/share/sounds/freedesktop/stereo/complete.oga" }
]
}
]
}
}
Claude Code(WSL2)
WSL の中から Windows のビープを鳴らす:
{
"hooks": {
"Notification": [
{
"hooks": [
{ "type": "command", "command": "powershell.exe -c \"[console]::beep(800,200)\"" }
]
}
]
}
}
Codex CLI
~/.codex/config.toml:
notify = ["bash", "-c", "afplay /System/Library/Sounds/Glass.aiff"]
Codex の notify はエージェントターン完了時に呼ばれる。形式(文字列 / 配列)はバージョンで異なる場合があるので、効かなければ 公式ドキュメント を確認。
2. Discord にプッシュ通知
Discord のスマホアプリは push 通知が強く、ロック画面でも音と振動で気付ける。
Webhook URL を取得
- Discord で適当なサーバを作る(自分 1 人だけのサーバで OK)
- 通知を受けたいチャンネル → 歯車アイコン → 連携サービス → ウェブフック → 新しいウェブフック
- 名前を決めて ウェブフック URL をコピー
URL は秘密扱い。流出すると誰でもそのチャンネルに書き込めるので、.zshrc 等に環境変数で持つのが安全:
# ~/.zshrc
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/.../..."
Claude Code に組み込む
音と Discord 通知を同時に発火:
{
"hooks": {
"Notification": [
{
"hooks": [
{ "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" },
{ "type": "command", "command": "curl -s -H 'Content-Type: application/json' -d '{\"content\":\"Claude Code が入力待ちです\"}' \"$DISCORD_WEBHOOK_URL\" > /dev/null" }
]
}
]
}
}
🟡 注意 / hook は新しいシェルで実行される。.zshrc の export が読まれないことがあるので、効かない場合は /etc/environment か ~/.profile 側に書くか、コマンド内で直接 URL を埋め込む(git に上げない)。
Codex CLI に組み込む
~/.codex/config.toml:
notify = ["bash", "-c", "afplay /System/Library/Sounds/Glass.aiff; curl -s -H 'Content-Type: application/json' -d '{\"content\":\"Codex CLI が応答完了\"}' \"$DISCORD_WEBHOOK_URL\" > /dev/null"]
長くなるならシェルスクリプトに切り出してパスを書くほうが管理しやすい:
notify = ["/Users/me/.local/bin/codex-notify.sh"]
なぜ Slack ではなく Discord か
個人で AI CLI 通知を仕込むだけなら、Discord のほうが圧倒的に簡単。
| 項目 | Discord | Slack |
|---|---|---|
| Webhook 作成 | サーバ設定から数クリック、無料 | アプリ登録 or 旧 Incoming Webhook、ワークスペース管理者承認が必要 |
| 個人利用 | 完全無料、無制限 | 無料プランは Workspace 単位で履歴/検索が制限 |
| モバイル push | 強力。ロック画面でも通知音・振動 | あるが法人向け設計で通知細分化が複雑 |
| 1 人サーバ | 普通の運用パターン | Workspace を 1 人で作る前提ではない |
| 会社のセキュリティ | 個人デバイスへの通知に最適 | 会社管理下に置くことを前提とする設計 |
要するに 「個人開発者の通知デバイス」として最適化されているのが Discord、「会社のチームコミュニケーション基盤」として最適化されているのが Slack。AI CLI の入力待ち通知は前者の用途。
Slack を選ぶのが妥当な場面:
- 既にチーム全員 Slack を常駐していて、エンジニア各人の AI 利用状況も共有チャンネルに流したい
- 会社のセキュリティポリシーで外部サービス通知が Slack に限定されている
それ以外の個人 / 小規模利用なら Discord で十分。
応用
タスク完了時にも通知
Claude Code の Stop イベントで、エージェントが応答を終えるたびに通知できる。長いタスクを投げて散歩に行くときに便利。
{
"hooks": {
"Stop": [
{
"hooks": [
{ "type": "command", "command": "curl -s -H 'Content-Type: application/json' -d '{\"content\":\"Claude のタスクが完了しました\"}' \"$DISCORD_WEBHOOK_URL\" > /dev/null" }
]
}
]
}
}
通知にプロジェクト名やセッション ID を載せる
hook の標準入力には JSON でセッション情報が渡る。シェルスクリプトで整形すれば、「どのプロジェクトの Claude が待っているか」まで通知に載せられる。
#!/bin/bash
# ~/.local/bin/claude-notify.sh
PROJ=$(basename "$PWD")
SID=$(jq -r '.session_id // "?"' 2>/dev/null)
curl -s -H "Content-Type: application/json" \
-d "{\"content\":\"Claude 待機中 · ${PROJ} · session ${SID:0:8}\"}" \
"$DISCORD_WEBHOOK_URL" > /dev/null
settings.json 側:
{ "type": "command", "command": "/Users/me/.local/bin/claude-notify.sh" }
詰まりやすい点
「音は鳴るが Discord に来ない」
→ Webhook URL の typo か、シェルのクオート崩れ。curl を単独で叩いて 204 が返るか確認。Discord 側で Bad Request 系が返るなら JSON の組み立てが壊れている。
「$DISCORD_WEBHOOK_URL が空」
→ hook のシェルは新規プロセスで、.zshrc の export が読まれないことがある。~/.profile か /etc/environment に書く、または URL を直接スクリプトに埋める運用に倒す。
「通知が来すぎてうるさい」
→ Notification(待ち)と Stop(完了)を両方仕込んでいると倍来る。本当に欲しいのはどちらか、業務時間内だけ鳴らす、など条件を絞る。
「WSL2 から音が鳴らない」
→ WSL のオーディオは設定が要る。powershell.exe -c "[console]::beep(...)" のように Windows 側に音を出させるのが手っ取り早い。
次のステップ
- Claude Code チートシート — hooks の他のフラグ・コマンド
- Codex CLI チートシート — config.toml の他の設定キー