OpenAI Codex CLI
Get notified when OpenAI Codex CLI finishes a turn or needs approval. Codex hooks (Stop, PermissionRequest) and the notify setting, sending to Slack or SMS.
Codex CLI can run a command on agent events. There are two ways to set it up:
- Hooks (recommended) -
Stopwhen a turn finishes andPermissionRequestwhen Codex needs your approval. The event arrives as JSON on stdin. notify(older) - runs a program after each turn. It has no event for approval requests.
Hooks
1. Create the hook script
#!/usr/bin/env bash
# Forwards Codex Stop and PermissionRequest hook events to Alphorn.
jq -c '{
title: ("Codex - " + (.cwd | split("/") | last)),
message: (if .hook_event_name == "PermissionRequest"
then ("Approval needed: " + (.tool_input.description // .tool_input.command // .tool_name // "tool call"))
else (.last_assistant_message // "Turn complete") end),
priority: (if .hook_event_name == "PermissionRequest" then 4 else 2 end),
tags: ["ai-agent", "codex",
(if .hook_event_name == "PermissionRequest" then "permission" else "completed" end)]
}' | curl -fsS --max-time 5 -X POST https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT \
-H "Authorization: Bearer $ALPHORN_API_KEY" \
-H "Content-Type: application/json" \
-d @- > /dev/null
exit 0chmod +x ~/.codex/hooks/alphorn-notify.shThe script always exits 0: on a Stop hook, exit code 2 makes Codex continue the turn.
2. Register the hooks
{
"hooks": {
"Stop": [
{ "hooks": [{ "type": "command", "command": "~/.codex/hooks/alphorn-notify.sh", "timeout": 30 }] }
],
"PermissionRequest": [
{ "hooks": [{ "type": "command", "command": "~/.codex/hooks/alphorn-notify.sh", "timeout": 30 }] }
]
}
}Hooks can also live in a project's .codex/hooks.json; project hooks only load when the project is trusted. ALPHORN_API_KEY must be set in the environment Codex runs in. Codex only runs a hook after you have reviewed and trusted it: run /hooks in Codex and trust the new hook - and again after every change to it. Otherwise hooks silently never fire. If they still don't run, make sure hooks aren't disabled in config.toml ([features] hooks = false).
| Event | Useful fields |
|---|---|
| All | session_id, cwd, hook_event_name, model |
Stop | last_assistant_message |
PermissionRequest | tool_name, tool_input.command, tool_input.description |
Legacy notify setting
notify runs a program after each turn and passes the event as a JSON string in the last argument (not on stdin). Its field names use hyphens, for example last-assistant-message. Put it at the top level of ~/.codex/config.toml, before any [table] section:
notify = ["bash", "-c", "jq -n --argjson e \"$1\" '{title: (\"Codex - \" + ($e.cwd | split(\"/\") | last)), message: ($e[\"last-assistant-message\"] // \"Turn complete\"), priority: 2, tags: [\"ai-agent\", \"codex\", \"completed\"]}' | curl -fsS --max-time 5 -X POST https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT -H \"Authorization: Bearer $ALPHORN_API_KEY\" -H 'Content-Type: application/json' -d @-", "codex-notify"]The only event notify sends is agent-turn-complete. For approval requests, use the PermissionRequest hook above.
Notify when a Codex run exits
To get one notification when a whole codex run ends, including its exit code, wrap the command:
#!/bin/bash
WEBHOOK="https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT"
ALPHORN_API_KEY="${ALPHORN_API_KEY:-alp_...}" # or export it in the environment
PROJECT=$(basename "$PWD")
codex "$@"
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
BODY="{\"title\": \"Codex - $PROJECT\", \"message\": \"Task completed\", \"priority\": 2, \"tags\": [\"ai-agent\", \"codex\", \"completed\"]}"
else
BODY="{\"title\": \"Codex - $PROJECT\", \"message\": \"Exited with code $EXIT_CODE\", \"priority\": 4, \"tags\": [\"ai-agent\", \"codex\", \"error\"]}"
fi
curl -fsS --max-time 5 -X POST "$WEBHOOK" \
-H "Authorization: Bearer $ALPHORN_API_KEY" \
-H "Content-Type: application/json" \
-d "$BODY"
exit $EXIT_CODEUse it as a drop-in replacement:
alias codex="/path/to/codex-notify.sh"See AI Agent Notifications for routing conventions and an AGENTS.md snippet that lets Codex send notifications on its own.
Claude Code
Get notified when Claude Code finishes, waits for input, or needs permission. Claude Code hooks (Stop, Notification) that send to Slack, Telegram, or SMS.
Cursor
Get notified when a Cursor agent run completes, is aborted, or fails. A Cursor stop hook in hooks.json that sends to Slack, Telegram, SMS, or email.