Coding tools · 03
Codex app
Configure a Stop hook for Local and Worktree tasks running on this Mac. The script reads only session, turn, and working-directory fields; it does not pass prompts or response text to bluebell.
Check where the task runs
Only for tasks running on this Mac
| Codex environment | Can it invoke the local bluebellctl? |
|---|---|
| Local | Yes. The task runs directly in the current project directory. |
| Worktree | Yes. The task runs in an isolated worktree on this Mac. |
| Cloud | Not with this guide. The remote environment cannot access the CLI inside your Mac app. |
Current official lifecycle
Stop runs when the main thread stops
The Codex Stop hook runs when a response turn in the main thread stops and receives JSON on stdin. Current fields include session_id, turn_id, cwd and the latest response text. This guide uses only the first three fields.
Step 1
Create a Stop adapter script
#!/usr/bin/env python3
import json, os, subprocess, sys
CLI = "/Applications/bluebellMac.app/Contents/Helpers/bluebellctl"
try:
payload = json.load(sys.stdin)
except Exception:
sys.exit(0)
if payload.get("hook_event_name") != "Stop":
sys.exit(0)
session_id = str(payload.get("session_id") or "")
turn_id = str(payload.get("turn_id") or "")
cwd = str(payload.get("cwd") or "")
if not session_id or not turn_id:
sys.exit(0)
try:
subprocess.run([
CLI, "emit",
"--source", "Codex app",
"--workspace-name", os.path.basename(cwd) or "Codex",
"--session-id", session_id,
"--turn-id", turn_id,
"--dedupe-key", f"codex-app:{session_id}:{turn_id}",
"--local",
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=3, check=False)
except (OSError, subprocess.SubprocessError):
pass Replace CLI with the actual CLI path copied from the bluebell Mac home screen. session_id + turn_id form a stable deduplication ID. Retrying the same hook does not create a second logical notification.
Step 2
Add the hook to your Codex configuration
To apply it to all local projects, merge the following into ~/.codex/hooks.json; to apply it to just one project, use <repo>/.codex/hooks.json. Project-level configuration also requires that project to be trusted.
{
"description": "Send Codex Stop events to bluebell",
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"/absolute/path/codex-app-bluebell.py\"",
"timeout": 5
}
]
}
]
}
} Replace the script’s absolute path. If the file already contains hooks, merge only the new Stop entry. Do not overwrite the whole file or define both hooks.json and config.toml hooks.
Step 3
Review the hook, then complete a local task
- After saving, create a Local or Worktree task. Review and trust the command hook when Codex prompts you.
- Complete a short turn and confirm that bluebell Mac shows exactly one local “Codex app” event in recent notifications.
- Continue with another turn in the same task. Confirm that the new
turn_idproduces a new event. - If Codex reports an untrusted hook, use
/hooksin Codex CLI to inspect its source and trust status. - After verification, remove
--localfrom the script. Then check Mac remote delivery, the delivery queue, and a real Watch.
Sources
OpenAI official references
- Codex Hooks Configuration locations, trust, Stop input fields, and concurrent execution
- Codex environments Where Local, Worktree, and Cloud tasks run