はじめに
Codex CLIへ少し時間のかかる作業を依頼したあと、別の画面で仕事をしていると、完了に気づくのが遅れることがあります。
そこで、Codexの処理が完了したときにmacOSの通知を表示し、通知をクリックすると該当するCodexタスクへ戻れるようにしました。
この記事では、Codexの notify フックと terminal-notifier を組み合わせた設定手順を、筆者の環境で動作確認した実装から再利用しやすい形に整理して説明します。
先に結論
次の3点を設定すると、Codexの完了通知から作業中のタスクへ戻れます。
- Homebrewで
terminal-notifierをインストールする - Codexから渡されるJSONを処理する通知スクリプトを用意する
- ユーザー用の
~/.codex/config.tomlにnotifyを設定する
処理の流れは次のとおりです。
OpenAIの通知設定に関する公式ドキュメントによると、外部プログラムを呼び出す notify が現在対応しているイベントは agent-turn-complete です。イベントの情報は、1つのJSON文字列として通知スクリプトの第1引数へ渡されます。
Codex標準の通知との違い
Codex CLIのTUIには、外部スクリプトを使わない tui.notifications もあります。対応するターミナルでは、OSC 9またはBELを使って通知できます。
単に処理完了へ気づきたいだけなら、まず標準通知を検討できます。今回 notify を使う理由は、JSONから thread-id を取得し、通知をクリックしたときの遷移先を組み立てる処理が必要だからです。
| 方法 | 向いている用途 |
|---|---|
tui.notifications |
外部スクリプトを用意せず、TUIのイベントを通知したい |
notify |
通知本文の加工、Webhook、ログ保存、クリック時のURL指定などを行いたい |
前提
- 対象読者: macOSでCodex CLIを使い、長めの処理の完了を通知で知りたい人
- 使用環境: macOS、Codex CLI、Codexデスクトップアプリ、Homebrew、Zsh
- 使用ツール:
terminal-notifier、jq - 仕様確認日: 2026年8月22日
- 扱わない範囲: WindowsやLinuxの通知設定、SlackなどへのWebhook通知
筆者は codex-cli 0.148.0-alpha.21、terminal-notifier 2.0.0 で確認しました。これは最低バージョンを示すものではありません。クリックしてタスクを開くには、macOSで codex: URLスキームを処理できるCodexデスクトップアプリも必要です。
terminal-notifier は、ターミナルからmacOSの通知センターへ通知を送るためのツールです。公式READMEに記載されている -open オプションには、Web URLだけでなく、アプリ独自のカスタムURLスキームも指定できます。
1. terminal-notifierをインストールする
Homebrewで terminal-notifier と、JSONを処理する jq をインストールします。
# 通知表示とJSON解析に使うツールをインストールする。
brew install terminal-notifier jq
インストールできたことを確認します。
# 2つのコマンドを実行できる状態か確認する。
command -v terminal-notifier
command -v jq
どちらも実行ファイルのパスが表示されれば準備完了です。すでに利用できる場合は、再インストールする必要はありません。インストール方法やmacOSの環境によって、表示されるパスは異なります。
/opt/homebrew/bin/terminal-notifier
/opt/homebrew/bin/jq
2. 通知スクリプトを配置する
この記事では、通知スクリプトを次の場所へ置く例を使います。
/Users/your-name/.local/bin/codex-macos-notify.sh
スクリプトの内容は次のとおりです。配列や print -r などZshの構文を使うため、コードブロックも zsh として明示しています。
#!/bin/zsh
# Codexは通知イベントのJSONを第1引数として渡す。
set -u
event=${1:-}
# 引数がない手動テストでは、標準入力からJSONを受け取れるようにする。
if [[ -z "$event" && ! -t 0 ]]; then
event=$(cat)
fi
[[ -z "$event" ]] && exit 0
# JSONを処理するjqの実行ファイルをPATHから取得する。
jq_bin=$(command -v jq 2>/dev/null || true)
[[ -z "$jq_bin" ]] && exit 0
# 現在サポートされている完了イベントだけを通知対象にする。
event_type=$(print -r -- "$event" | "$jq_bin" -r '.type // empty' 2>/dev/null)
[[ "$event_type" != "agent-turn-complete" ]] && exit 0
# 通知クリック用のタスクIDと、通知本文をJSONから取得する。
thread_id=$(print -r -- "$event" | "$jq_bin" -r '."thread-id" // empty' 2>/dev/null)
message=$(print -r -- "$event" | "$jq_bin" -r '."last-assistant-message" // "Codexのタスクが完了しました"' 2>/dev/null)
[[ -z "$message" || "$message" == "null" ]] && message="Codexのタスクが完了しました"
# 通知が長くなりすぎないように、改行を空白へ変えて180文字に制限する。
message=${message//$'\n'/ }
message=${message:0:180}
notifier=$(command -v terminal-notifier 2>/dev/null || true)
if [[ -n "$notifier" ]]; then
notifier_args=(
-title "Codex 完了"
-message "$message"
-sound Glass
)
# thread-idが取得できた場合だけ、通知クリック時の遷移先を設定する。
if [[ -n "$thread_id" ]]; then
notifier_args+=(
-group "codex-${thread_id}"
-open "codex://threads/${thread_id}"
)
fi
"$notifier" "${notifier_args[@]}"
else
# terminal-notifierがない場合は、クリック遷移なしの通知だけを表示する。
/usr/bin/osascript - "$message" <<'APPLESCRIPT'
on run argv
display notification (item 1 of argv) with title "Codex 完了" sound name "Glass"
end run
APPLESCRIPT
fi
このスクリプトで使っている主な値は次のとおりです。
| JSONの項目 | 用途 |
|---|---|
type |
agent-turn-complete かどうかを確認する |
thread-id |
完了したCodexタスクの識別とクリック後の遷移に使う |
last-assistant-message |
通知本文へ表示する |
OpenAIの公式ドキュメントには、ほかに turn-id、cwd、input-messages も一般的な項目として記載されています。今回は完了通知に必要な項目だけを利用しています。
3. 実行権限を付ける
配置したシェルスクリプトへ実行権限を付けます。
# 通知スクリプトへ実行権限を付ける。
chmod +x /Users/your-name/.local/bin/codex-macos-notify.sh
実行権限を確認します。
# 所有者の実行権限を表す「x」があることを確認する。
ls -l /Users/your-name/.local/bin/codex-macos-notify.sh
先頭付近に x があれば実行可能です。
-rwxr-xr-x ... codex-macos-notify.sh
4. Codexのnotifyを設定する
ユーザー用の ~/.codex/config.toml に、次の設定を追加します。
# Codexの処理完了時に実行する外部コマンドを指定する。
notify = ["/Users/your-name/.local/bin/codex-macos-notify.sh"]
/Users/your-name は、自分のホームディレクトリへ置き換えてください。設定値には、シェルスクリプトの絶対パスを指定しておくと、実行時のカレントディレクトリに左右されません。
notify はユーザー用の ~/.codex/config.toml に設定します。OpenAIの公式ドキュメントでは、プロジェクト内の .codex/config.toml に置いた notify は無視されると説明されています。
すでに notify が設定されている場合は、既存値をすぐに削除しないでください。notify は1つの外部コマンドを指定する設定なので、既存コマンドにも必要な役割がある場合は、1本の通知スクリプトから既存処理とmacOS通知の両方を呼び出す構成にします。
# 例: 既存の通知処理を先に実行し、その後でmacOS通知を続ける。
/path/to/existing-notify-command "$event" || true
# この下にterminal-notifierの処理を続ける。
既存コマンドへ渡す引数は、そのコマンドの現在の設定と仕様を確認して合わせます。確認せずに上書きすると、別の連携機能が動かなくなる可能性があります。
設定を反映するため、Codex CLIを再起動します。再起動後にタスクを1つ完了させ、macOS通知が表示されることを確認します。
5. スクリプトだけを手動確認する
Codexの完了を待たずに通知表示だけを確認したい場合は、次のJSONを第1引数として渡します。
# JSON全体を1つの引数として通知スクリプトへ渡す。
/Users/your-name/.local/bin/codex-macos-notify.sh \
'{"type":"agent-turn-complete","thread-id":"test-thread-id","last-assistant-message":"通知テストが完了しました"}'
この例の test-thread-id は実在しません。そのため、通知が表示されることは確認できますが、クリック後に実在するタスクを開く確認には使えません。クリック遷移は、Codexから発生した実際の完了通知で確認します。
通知をクリックするとタスクが開く仕組み
この実装では、通知イベントの thread-id から次のURLを組み立てています。
codex://threads/<thread-id>
terminal-notifier の -open は、公式READMEに記載されているとおり、カスタムURLスキームを受け取れます。筆者のmacOS環境ではCodexデスクトップアプリが codex: を処理するアプリとして登録されており、codex://threads/<thread-id> で該当タスクを開けることを確認しました。
ただし、OpenAI公式ドキュメントで説明されている範囲は、notify の呼び出し方法と通知イベントのJSON項目までです。codex://threads/<thread-id> は公開ドキュメントで保証された通知APIではなく、筆者環境で確認したデスクトップアプリ側のURLです。Codexアプリの更新後は、実際の完了通知でクリック遷移も確認してください。
通知されないときの確認項目
terminal-notifierが見つかるか
# terminal-notifierを実行できるパスが返るか確認する。
command -v terminal-notifier
何も表示されない場合は、インストール状態と PATH を確認します。
スクリプトを直接実行できるか
# 1行目でZsh構文を確認し、2行目で通知を手動実行する。
zsh -n /Users/your-name/.local/bin/codex-macos-notify.sh
/Users/your-name/.local/bin/codex-macos-notify.sh \
'{"type":"agent-turn-complete","last-assistant-message":"構文確認が完了しました"}'
1行目はZshの構文確認です。2行目は通知の手動確認です。
macOSで通知が許可されているか
macOSの「システム設定」から「通知」を開き、terminal-notifier の通知が許可されているか確認します。集中モードが有効な場合は、通知がすぐに見えないこともあります。
config.tomlの場所が正しいか
確認するファイルは、プロジェクト内ではなく次のユーザー設定です。
~/.codex/config.toml
すでに notify がある場合は、設定を重複させません。既存の値が何に使われているか確認し、必要なら1本のスクリプトから両方の処理を呼び出します。
通知へ機密情報を出さない
この例では last-assistant-message を通知本文へ表示します。Codexの最後の回答に顧客名、パス、ログ、設計情報などが含まれると、macOSのロック画面にも表示される可能性があります。
内容を表示する必要がなければ、次のように固定文へ変更する方が安全です。
# 完了内容を通知画面へ出さず、固定メッセージだけを表示する。
message="Codexのタスクが完了しました"
通知のプレビュー表示も、macOSの「システム設定」で利用環境に合わせて調整します。
今回の実装で分かったこと
Codexの通知フックは、単に音を鳴らすだけではありません。JSONに含まれる thread-id、作業ディレクトリ、入力内容、最後の回答などを使い、用途に応じた通知処理へつなげられます。
例えば、次のような応用が考えられます。
- 作業ディレクトリ名を通知タイトルへ表示する
- タスク単位で通知をグループ化する
- 機密情報を除去してから社内Webhookへ送る
- 完了時刻や
turn-idをローカルログへ残す
ただし、通知先を外部サービスへ広げる場合は、JSONに含まれる情報をそのまま送らず、送信項目と保存期間を先に決める必要があります。
参考・確認先
- Advanced Configuration - Notifications(OpenAI)
- Codex Configuration Reference(OpenAI)
- terminal-notifier(GitHub)
- terminal-notifier(Homebrew Formulae)
OpenAI公式ドキュメントで、notify が外部プログラムを呼び出すこと、現在の対応イベント、JSONを第1引数で渡すこと、一般的なJSON項目、プロジェクト設定では notify が無視されること、TUI標準通知との違いを確認しました。terminal-notifier の公式READMEでは、Homebrewによる導入方法と -open がカスタムURLスキームに対応することを確認しています。codex://threads/<thread-id> はOpenAI公開ドキュメントの記載ではなく、筆者環境のURLスキーム登録と実際の遷移で確認した内容として区別しました。
関連記事
- AIエージェントが迷わないリポジトリ設計 AGENTS.mdと作業メモの作り方(今後公開予定)
まとめ
- Codex CLIの
notifyで、処理完了時に外部スクリプトを実行できる - 通知イベントのJSONは、標準入力ではなくスクリプトの第1引数として渡される
- 筆者環境では、
thread-idとterminal-notifier -openを組み合わせると、通知から該当タスクへ戻れる - 単純な完了通知だけなら、Codex標準の
tui.notificationsも選択肢になる - 通知本文へ完了メッセージを出す場合は、ロック画面への表示も考慮する
おわりに
完了通知から元のタスクへ戻れるようにすると、Codexへ処理を任せている間も別の作業を進めやすくなります。
Wealthy Designでは、生成AIを使った開発支援や業務改善に取り組んでいます。会社の取り組みは、会社サイトにまとめています。

