<!-- Source: https://moriblink.com/codex-notifications -->
<!-- Title: Codex CLI notifications on Mac: turn-complete and approval alerts -->

[Home](https://moriblink.com/) / [Guides](https://moriblink.com/guides) / Codex notifications

# Codex CLI notifications on Mac

Get an alert when Codex finishes a turn or needs your approval. Use the built-in TUI setting, the `notify` program, or a `PermissionRequest` hook.

Updated 26 October 2026

## 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:

```toml
[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:

```toml
# ~/.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:

```python
#!/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)
```

```toml
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`:

```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` (also `Edit` and `Write`), 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 `/hooks` in 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 = false` turns them off.

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

- 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 access](https://moriblink.com/#download)

## Sources

- [Codex advanced configuration](https://learn.chatgpt.com/docs/config-file/config-advanced): `notify`, its JSON payload, and `[tui]` notifications.
- [Codex configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference): `notify` is ignored in project-local config.
- [Codex hooks](https://learn.chatgpt.com/docs/hooks): hook locations, trust review, `PermissionRequest`, and `Stop` output 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.

Contact: [support@moriblink.com](mailto:support@moriblink.com)
