Quick answer

Codex has built-in terminal notifications. Add this to ~/.codex/config.toml to get an alert when a turn completes and when Codex asks for approval:

[tui]
notifications = ["agent-turn-complete", "approval-requested"]
notification_method = "auto"         # auto | osc9 | bel
notification_condition = "unfocused" # unfocused | always

In auto mode, Codex prefers OSC 9 terminal notifications and falls back to the terminal bell (BEL). Whether OSC 9 becomes a macOS notification depends on your terminal. With unfocused, you get alerts only when the terminal is not in focus.

Use notify for a real macOS notification

The notify setting runs an external program when Codex emits a supported event. Today the only event is agent-turn-complete. Codex passes the event to the program as one JSON argument. This one-line version ignores the JSON and shows a notification:

# ~/.codex/config.toml (top level, before any [table])
notify = ["sh", "-c", "osascript -e 'display notification \"Codex finished a turn\" with title \"Codex\"'", "codex-notify"]

With sh -c, the argument after the script (codex-notify) becomes the script name, and Codex’s JSON becomes $1, which this command does not use. Put notify in ~/.codex/config.toml. Codex ignores it in a project-local .codex/config.toml.

Show the project name

The JSON includes type, thread-id, turn-id, cwd, input-messages, and last-assistant-message. This script uses cwd so you can tell sessions apart:

#!/usr/bin/env python3
# ~/.codex/notify.py
import json, os, subprocess, sys

event = json.loads(sys.argv[1])
if event.get("type") == "agent-turn-complete":
    project = os.path.basename(event.get("cwd") or "") or "Codex"
    script = 'display notification "Turn complete" with title ' + json.dumps("Codex · " + project, ensure_ascii=False)
    subprocess.run(["osascript", "-e", script], check=False)
notify = ["python3", "/Users/you/.codex/notify.py"]

Replace /Users/you with your home folder. The same Script Editor permission applies: run osascript -e 'display notification "test"' once, then allow notifications for Script Editor in System Settings → Notifications.

Get an alert for approvals with a hook

notify does not run for approvals. For those, use the PermissionRequest hook. It runs when Codex is about to ask for approval, and it does not run for commands that do not need approval. Save this as ~/.codex/hooks.json:

{
  "hooks": {
    "PermissionRequest": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Codex needs approval\" with title \"Codex\" sound name \"Glass\"' >/dev/null 2>&1"
          }
        ]
      }
    ]
  }
}
Do not use the Stop hook for a plain notification. Codex expects JSON on stdout from Stop when it exits with code 0, and plain text is invalid for that event. notify is the simpler choice for finished turns.

Limits of a notification-only setup

How MoriBlink handles Codex

MoriBlink’s Codex connection is a preview, tested with documented hook fixtures. When you approve a project in Settings → Projects → Codex, MoriBlink adds only its own command-hook groups to <project>/.codex/hooks.json. Restart Codex and review the hooks with /hooks. Codex’s trust rules still decide whether they run.

See every agent in one place

MoriBlink follows OpenCode, Claude Code, and Codex sessions on your Mac, alerts you when one needs you, and shows where a slow run spent its time.

Get early access

Sources

Checked against the official documentation on 26 October 2026. Codex changes often. Check /hooks after an update.

Questions

Does the Codex notify setting run for approval requests?

No. Today notify runs only for the agent-turn-complete event. For approvals, use the built-in [tui] notifications setting with approval-requested, or a PermissionRequest hook.

Why does my Codex hook not run?

Codex skips new or changed hooks until you review and trust them in /hooks. Project hooks also need a trusted project .codex/ layer. Check that hooks are not turned off with [features] hooks = false.

Where does the Codex notify setting go?

In ~/.codex/config.toml, at the top level. Codex ignores notify in a project-local .codex/config.toml.