Notify when Codex finishes: notify = ["python3", "notify.py"] in config.toml

Codex Published: Updated:

Set notify = ["python3", "/path/notify.py"] in config.toml and Codex runs it after every turn with one JSON argument. Covers the JSON fields and tui.notifications filtering.

Verified on Oct 14, 2026 These tools change quickly. Please also check the latest official documentation. How articles are researched and verified
Contents
  1. notify: launching an external program
    1. macOS example
    2. Linux example
    3. Sending to Slack
  2. tui.notifications: controlling terminal notifications
  3. Summary

Hand Codex a longer task, switch to something else, and you can easily miss the moment it finishes. Codex CLI offers two mechanisms: notify, which launches an external program when a turn completes, and tui.notifications, which controls the terminal's own notifications.

In short: write an argv array such as notify = ["python3", "/path/to/notify.py"], and Codex runs that program with a single JSON argument at the end of every turn. From there you can post a desktop notification, hit a Slack webhook, or anything else.

KEY POINT

What you will learn

  • How to write notify and which JSON fields the program receives
  • Filtering terminal notifications by type, condition, and method with tui.notifications
  • Desktop notification scripts for macOS and Linux

notify: launching an external program

In ~/.codex/config.toml, list the command as an array. Unset means disabled.

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

The program receives one JSON string as its argument and should exit 0 on success. The main fields:

FieldContents
typeevent type; currently agent-turn-complete
thread-idthe session (thread) identifier
turn-idthe turn identifier
cwdthe working directory
input-messagesthe user messages for that turn
last-assistant-messagethe assistant's final output text

用語解説

Turn: one round from you sending an instruction to Codex finishing its response, including any command runs and approvals in between. notify fires at the end of that unit.

macOS example

Using terminal-notifier (installable with 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: turn complete"
body = (payload.get("last-assistant-message") or "")[:120]
subprocess.run(["terminal-notifier", "-title", title, "-message", body, "-group", payload.get("thread-id", "")])

Linux example

With notify-send you can skip the script entirely; the sample configuration shows this form.

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

The JSON string then becomes the notification body as is. Insert a script like the one above if you want it tidier.

Sending to Slack

For a Slack Incoming Webhook, have the script trim last-assistant-message and POST it. Read the webhook URL from an environment variable rather than writing it into config.toml.

last-assistant-message contains your work

Passing last-assistant-message straight into a notification sends file names and code fragments to an external service. For Slack and similar, truncate to a few dozen characters or send only a "done" marker.

tui.notifications: controlling terminal notifications

The terminal's own notifications are configured under [tui].

[tui]
# true / false, or a list of types
notifications = ["agent-turn-complete", "approval-requested"]
# unfocused (default) | always
notification_condition = "unfocused"
# auto (default) | osc9 | bel
notification_method = "auto"
KeyValuesMeaning
notificationstrue / false / liston by default; restrict to agent-turn-complete and approval-requested
notification_conditionunfocused / alwaysdefault fires only when the terminal is not focused
notification_methodauto / osc9 / belauto prefers OSC 9 when the terminal supports it, else BEL (\x07)

notify and tui.notifications are independent. For external notifications only, set notifications = false.

If what you want is a ding when Codex needs a response from you, this is the setting to use, not notify: the only event notify currently supports is agent-turn-complete, so it never fires on a pending approval. This configuration rings the terminal bell (\x07) for both turn completion and approval requests, even while the terminal is focused:

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

The documentation gives approval-requested as an example of a type tui.notifications can filter on. A complete list of accepted type names appears neither in the configuration reference nor on the notifications page.

The overall structure of the config file is covered in the hub article Configuring Codex with config.toml, and when approvals are requested in Codex approval modes and sandbox settings.

Summary

  • notify is an argv array, run with one JSON argument on every agent-turn-complete
  • The JSON carries type, thread-id, turn-id, cwd, input-messages, and last-assistant-message
  • terminal-notifier on macOS or a bare notify-send on Linux is enough to start
  • Truncate the body before sending it to external services and keep webhook URLs in environment variables
  • Terminal notifications are separate: [tui] notifications, notification_condition, notification_method

FAQ

Which events does notify receive?
Currently agent-turn-complete. The program gets one JSON argument with type, thread-id, turn-id, cwd, input-messages, and last-assistant-message.
Can I silence terminal notifications but keep notify?
Yes. Set notifications = false under [tui]; notify is configured independently.
Does notify work with the IDE extension?
According to the notifications page, you configure notify on the Codex host the extension connects to.
Can Codex ding when a prompt response is needed, not just when the turn completes?
Not through notify, which currently supports only agent-turn-complete. Keep approval-requested in the tui.notifications list, set notification_method = "bel" for the terminal bell, and notification_condition = "always" to hear it even when the terminal is focused.

Primary sources

This article was drafted by AI from official documentation and reviewed by the site operator before publishing. Found a mistake? Let us know via the contact page.