Codex の完了通知は notify = ["python3", "通知.py"]:デスクトップ通知と Slack への送り方

Codex 公開: 更新:

config.toml に notify = ["python3", "/path/notify.py"] と書くと、ターン完了ごとに JSON を 1 引数で受け取るプログラムが動きます。tui.notifications での絞り込みと macOS・Linux の例も載せます。

検証日 2026年10月14日 仕様変更が早い分野です。最新の公式ドキュメントも併せてご確認ください。 記事の作り方と検証手順
目次
  1. notify:外部プログラムを起動する
    1. macOS の例
    2. Linux の例
    3. Slack に送る
  2. tui.notifications:ターミナル通知を制御する
  3. まとめ

Codex に長めのタスクを任せて別の作業をしていると、終わったことに気づかず放置してしまいます。Codex CLI には、ターン完了時に 外部プログラムを起動する notify と、ターミナル自体の通知を制御する tui.notifications の 2 つの仕組みがあります。

結論として、notify = ["python3", "/path/to/notify.py"] のように argv 配列を書くと、ターン完了ごとに JSON を 1 引数として受け取るプログラムが起動します。デスクトップ通知でも Slack の Webhook でも、そのプログラムで好きな処理ができます。

KEY POINT

この記事で分かること

  • notify の書き方と、プログラムに渡される JSON のフィールド
  • tui.notifications で通知の種類・条件・方式を絞る方法
  • macOS / Linux でデスクトップ通知を出すスクリプト例

notify:外部プログラムを起動する

~/.codex/config.toml に、起動するコマンドを配列で書きます。未設定なら無効です。

notify = ["python3", "/Users/you/.codex/notify.py"]

プログラムは JSON 文字列 1 つを引数として 受け取り、成功時は終了コード 0 を返します。渡される主なフィールドは次のとおりです。

フィールド内容
typeイベント種別。現時点では agent-turn-complete
thread-idセッション(スレッド)の識別子
turn-idターンの識別子
cwd作業ディレクトリ
input-messagesそのターンでユーザーが送ったメッセージ
last-assistant-messageアシスタントの最後の出力テキスト

用語解説

ターン: あなたが 1 回指示を送ってから、Codex が応答を返し終えるまでの単位です。途中でコマンド実行や承認が挟まっても 1 ターンです。notify はこの単位の終わりで発火します。

macOS の例

terminal-notifier を使った例です(Homebrew でインストールできます)。

#!/usr/bin/env python3
import json, subprocess, sys

payload = json.loads(sys.argv[1])
if payload.get("type") != "agent-turn-complete":
    sys.exit(0)
title = "Codex: ターン完了"
body = (payload.get("last-assistant-message") or "")[:120]
subprocess.run(["terminal-notifier", "-title", title, "-message", body, "-group", payload.get("thread-id", "")])

Linux の例

notify-send を使う最小構成なら、スクリプトなしで直接指定もできます。サンプル設定にもこの形が示されています。

notify = ["notify-send", "Codex"]

この場合、JSON 文字列がそのまま通知本文として渡されます。本文を整えたい場合は上のようなスクリプトを挟んでください。

Slack に送る

Slack の Incoming Webhook に POST するなら、スクリプトの中で last-assistant-message を要約して送ります。Webhook URL は環境変数から読むようにし、config.toml に直接書かないでください。

last-assistant-message には作業内容が含まれる

通知本文に last-assistant-message をそのまま載せると、ファイル名やコードの断片が外部サービスに送られます。Slack などに送る場合は、先頭の数十文字に切り詰めるか、「完了」の一言だけにするのが安全です。

tui.notifications:ターミナル通知を制御する

ターミナル自体が出す通知は [tui] セクションで制御します。

[tui]
# true / false、または種類のリスト
notifications = ["agent-turn-complete", "approval-requested"]
# unfocused(既定)| always
notification_condition = "unfocused"
# auto(既定)| osc9 | bel
notification_method = "auto"
キー値意味
notificationstrue / false / 種類のリスト既定は有効。agent-turn-complete と approval-requested で絞れる
notification_conditionunfocused / always既定はターミナルが非アクティブのときだけ
notification_methodauto / osc9 / belauto は端末が対応していれば OSC 9、そうでなければ BEL(\x07)

notify と tui.notifications は独立しています。外部通知だけにしたいなら notifications = false にします。

逆に「承認を求められたときに音を鳴らしたい」場合は、notify ではなくこちらを使います。notify が対応しているイベントは現時点で agent-turn-complete だけなので、承認待ちでは起動しません。次の設定なら、ターン完了と承認待ちの両方で、ターミナルが前面にあっても BEL(\x07)が鳴ります。

[tui]
notifications = ["agent-turn-complete", "approval-requested"]
notification_condition = "always"
notification_method = "bel"

公式ドキュメントは approval-requested を tui.notifications で絞り込める種類の例として挙げています。指定できる種類の完全な一覧は、設定リファレンスにも通知のページにも載っていませんでした。

Codex の設定ファイル全体の構造は親記事の config.toml でモデル・推論の深さ・プロファイルを切り替える を参照してください。承認が必要になる条件は approval mode と sandbox 設定の違い で扱っています。

まとめ

  • notify は argv 配列。ターン完了(agent-turn-complete)のたびに JSON 1 引数でプログラムを起動する
  • JSON には type、thread-id、turn-id、cwd、input-messages、last-assistant-message が入る
  • macOS は terminal-notifier、Linux は notify-send を直接指定するだけでも動く
  • 外部サービスに送るときは本文を切り詰め、Webhook URL は環境変数に置く
  • ターミナル通知は [tui] の notifications / notification_condition / notification_method で別に制御する

よくある質問

notify にはどんなイベントが渡されますか?
現時点で対応しているのは agent-turn-complete(ターン完了)です。type、thread-id、turn-id、cwd、input-messages、last-assistant-message を含む JSON が 1 つの引数として渡されます。
ターミナルの通知だけ止めて notify は使えますか?
はい。[tui] の notifications = false でターミナル通知を止め、notify は別に設定できます。
IDE 拡張でも notify は使えますか?
公式の通知ページによると、接続先の Codex ホスト側で notify を設定します。
ターン完了だけでなく、承認を求められたとき(prompt response needed)にも音を鳴らしたいです。
notify では鳴りません。notify が対応しているのは現時点で agent-turn-complete だけです。承認待ちで鳴らすには tui.notifications の種類に approval-requested を残し、音を確実に鳴らすなら notification_method = "bel"、席を外していなくても鳴らすなら notification_condition = "always" にします。

参考にした一次情報

この記事は公式ドキュメントを基に AI が下書きを作成し、運営者が内容を確認して公開しています。誤りを見つけた場合は お問い合わせからお知らせください。