- Python 100%
| .codex-plugin | ||
| hooks | ||
| scripts | ||
| skills/agent-notify | ||
| tests | ||
| README.md | ||
Agent Notify
Agent Notify is a local Codex plugin that bridges Codex app-server sessions to
ntfy. It publishes session updates to a send topic and turns explicitly
addressed replies from a poll topic into Codex turn/start, turn/steer, or
approval responses.
ntfy Behavior
ntfy supports updating one visible client notification by publishing new
messages with the same X-Sequence-ID. The ntfy server cache/history remains
append-only, so Agent Notify guarantees one visible notification per session on
clients that honor X-Sequence-ID, not one stored server record.
Required Environment
export AGENT_NOTIFY_NTFY_BASE_URL="https://ntfy.xiny.li"
export AGENT_NOTIFY_NTFY_SEND_TOPIC="<send>"
export AGENT_NOTIFY_NTFY_POLL_TOPIC="<poll>"
export AGENT_NOTIFY_NTFY_TOKEN="<token>"
Basic auth is also supported with AGENT_NOTIFY_NTFY_USER and
AGENT_NOTIFY_NTFY_PASSWORD.
Production runs refuse to start without ntfy auth. Use
--allow-anonymous-test only for throwaway test topics.
Optional:
export AGENT_NOTIFY_BRIDGE_LABEL="workstation-a"
export AGENT_NOTIFY_PLUGIN_ROOT="/absolute/path/to/agent-notify"
The Codex app-server Unix socket is created at
$XDG_RUNTIME_DIR/agent-notify/codex-app-server.sock. The bridge requires
$XDG_RUNTIME_DIR to be owned by the current user and inaccessible to
group/other users. The runtime socket directory is forced to 0700, and the
app-server socket is forced to 0600 after startup.
AGENT_NOTIFY_BRIDGE_ID is an advanced override. By default, the bridge
generates and persists a random 128-bit ID in its state directory. If a duplicate
bridge ID is observed on a shared poll topic, auto-generated IDs rotate before
sessions start; manual overrides fail closed.
Run
Start the bridge and shared Codex app-server:
python3 scripts/agent_notify_bridge.py serve
Create Codex threads with local Codex CLI/TUI clients connected to the shared socket:
codex --remote "unix://$XDG_RUNTIME_DIR/agent-notify/codex-app-server.sock" --cd /path/to/project-a
codex --remote "unix://$XDG_RUNTIME_DIR/agent-notify/codex-app-server.sock" --cd /path/to/project-b
When the bridge observes a Codex thread, it registers a local session and publishes an ntfy notification with the reply target:
Reply target: @<bridge-id>/<session-id>
Reply Syntax
Replies must always be explicitly addressed:
@<bridge-id>/<session-id> continue with the next step
@<bridge-id>/<session-id> approve <request-id>
@<bridge-id>/<session-id> approve-session <request-id>
@<bridge-id>/<session-id> deny <request-id>
@<bridge-id>/<session-id> cancel <request-id>
Unaddressed plain text is ignored. Messages addressed to a different bridge are ignored so many app-servers can share the same ntfy topics.
Hooks
hooks/hooks.json forwards Codex lifecycle events to the local bridge socket.
Set AGENT_NOTIFY_PLUGIN_ROOT to this plugin directory before relying on the
bundled hook commands.
If AGENT_NOTIFY_PLUGIN_ROOT is unset, bundled hooks no-op instead of failing.
The hook client is best-effort. If the bridge is not running, it logs to stderr and exits successfully so it does not block Codex.