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"
}
]
}
]
}
}
- A matcher is optional. Without one, the hook runs for every permission request. Supported tool names include
Bash,apply_patch(alsoEditandWrite), and MCP tool names. - Plain text on stdout is ignored for this event. A hook that returns no decision leaves the normal approval prompt in place, so this hook only notifies you.
- Trust: Codex skips new or changed hooks until you review and trust them. Open
/hooksin the CLI to do that. Project hooks in<repo>/.codex/load only when that project layer is trusted. - Hooks are on by default.
[features] hooks = falseturns them off.
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
- Every alert looks alike unless your script adds the project name.
- Terminal notifications depend on the terminal and on focus.
- A finished turn does not mean the work is correct.
- There is no list of sessions or history of what waited and for how long.
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.
- Mori appears on your display for approval requests and questions.
- Recorded tool calls, interruptions, and child agents appear in History.
- The hooks never approve permissions, change tools, or read transcripts. Prompts, commands, patches, and tool output are left out.
- Codex hooks do not give a continuous live status, so live timers and completion alerts are not available for Codex sessions in the preview.
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 accessSources
- Codex advanced configuration:
notify, its JSON payload, and[tui]notifications. - Codex configuration reference:
notifyis ignored in project-local config. - Codex hooks: hook locations, trust review,
PermissionRequest, andStopoutput rules.
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.