Codex CLI compatibility. OpenAI's Codex CLI now joins Claude Code and Cursor IDE as a first-class editor target. Single AI-first prompt installs everything; the calling AI agent handles every follow-up step that requires a config edit. No human-in-the-loop steps.
π For Codex users: paste this single prompt into Codex (or any AI agent that can run shell commands):
"Clone https://github.com/ChanMeng666/claude-code-audio-hooks into ~/audio-hooks, then run
python ~/audio-hooks/bin/audio-hooks install --codex. Read the JSON output: iffeature_flag_stateissection_missingorflag_missing_or_false, follow thenext_stepsinstruction (use your Edit tool to add[features]\ncodex_hooks = trueto~/.codex/config.toml). Then restart Codex."
What's new
audio-hooks install --codex / uninstall --codex
- Writes
$CODEX_HOME/hooks.json(default~/.codex/hooks.json) registering the 6 events Codex supports per developers.openai.com/codex/hooks:SessionStart,PreToolUse,PostToolUse,PermissionRequest,UserPromptSubmit,Stop. The other 18 audio-hooks canonical events have no Codex equivalent and the runner no-ops them with askipped_no_codex_equivalentdebug NDJSON event. - Tags every entry with
_managed_by: "audio-hooks"so re-installs are idempotent and uninstall preserves user-authored hooks. Never touches~/.codex/config.tomlon uninstall β thecodex_hooksflag may benefit other Codex hook plugins. - Codex does NOT auto-bridge Claude Code plugins (unlike Cursor). Confirmed by independent investigation of openai/codex. Consequence: no
DUPLICATE_BRIDGEproblem to solve.
AI-first feature-flag handling
Codex hooks require [features]\ncodex_hooks = true in ~/.codex/config.toml. The install:
| State | Action |
|---|---|
| File doesn't exist | Authors a fresh config.toml with the flag enabled (feature_flag_state: "freshly_written") |
| Flag already true | Skips silently (feature_flag_state: "already_enabled") |
| Flag missing or false | Emits a machine-readable next_steps JSON instruction so the calling AI agent can add the flag with its Edit tool |
We never round-trip user-authored TOML β formatting and comments would be destroyed. The AI agent handles targeted edits with its Edit tool while the install handles the safe cases.
--invoker codex CLI flag
Codex sets no env var we could detect by (unlike Cursor's CURSOR_VERSION). The install template bakes --invoker codex into every command:
{ "command": "python \"/abs/path/to/hook_runner.py\" stop --invoker codex" }New hooks/invoker.py module extracted from hook_runner.py so user_preferences.py can ask "which IDE invoked us?" without a circular import. detect_invoker() checks argv first, then env vars, then falls back to unknown. The cache is primed before argv stripping so downstream callers see the right answer.
editor_targets.codex block in audio-hooks status / manifest
Reports state (active / active-but-flag-disabled / active-but-flag-unknown / inactive), hooks_file, config_path, feature_flag_enabled, data_dir. Surfaces a CODEX_FEATURE_FLAG_MISSING warning when the install is in place but the flag isn't enabled β actionable for the calling AI agent.
codex: {...} sub-object in webhook payloads
When invoker == "codex", the raw payload includes a codex sub-object with turn_id, tool_use_id, permission_mode, tool_response, stop_hook_active (parallel to cursor: {...}). Schema stays at audio-hooks.webhook.v1 β additive, no breaking changes.
Codex-gated step in _resolve_data_dir()
New priority 3 (between env-var overrides and the plugin-cache layout): when detect_invoker() == "codex" AND $CODEX_HOME/audio-hooks-data/user_preferences.json exists, return that path. Sits ahead of the Claude Code shared dir so a developer machine that happens to have both Claude Code and Codex installed still lands at the right dir under Codex sessions.
Tests + CI
33 new bridge-contract tests in tests/test_codex_hooks.py across 8 TestCase classes:
- Invoker detection from argv (4 cases including the
--invoker=codexform and invalid-value fallback) strip_invoker_argscorrectness_resolve_data_dirCodex fallback (positive + negative gating)- Template validity (all 6 events, every command carries
--invoker codex, every canonical handler is known) - Unsupported-events no-op (all 18)
- NDJSON
invokerfield, webhook codex sub-object - Install end-to-end (writes hooks.json, substitutes paths, seeds user_preferences, writes install_marker, idempotent, preserves foreign entries)
- Feature-flag handling (4 states)
- Uninstall (removes managed, preserves foreign, preserves data dir by default,
--purge, never touches config.toml) editor_targets.codexend-to-end
135/135 tests pass on Windows.
Out of scope for 5.2.0
- Project-scope install (
<repo>/.codex/hooks.json). User-scope only is the v1 design. Users wanting per-repo audio config can hand-edit<repo>/.codex/hooks.jsonthemselves. - Codex plugin packaging (
~/.codex/plugins/audio-hooks/). Codex has its own plugin system but we haven't packaged audio-hooks for it; the hooks.json install is sufficient for v1. - Auto-editing existing
~/.codex/config.toml. Too risky for user-authored TOML β TOML round-trip with comment preservation is hard and getting it wrong destroys user formatting. Thenext_stepsAI-readable instruction is the right contract for v1.
Files changed
24 files: 19 modified + 5 new. +2505 / -81. New files: codex-hooks/hooks.json, hooks/invoker.py, tests/test_codex_hooks.py, plus plugin-layout copies. See CHANGELOG.md for the full entry.