Summary
codex-native sub-agents can never start when the user has Codex hooks configured. The per-session CODEX_HOME breaks Codex's hook-trust records, so Codex opens an interactive "Hooks need review" prompt on every launch. In a headless sub-agent there is nobody to answer it, the app-server never emits thread/started, and the run dies on the 15s timeout.
This also affects the bundled polly orchestrator: its codex sub-agent is declared as codex-native, so cross-vendor review — polly's core guarantee — silently never runs on any machine where Codex hooks are configured.
Impact
Observed while running polly on a real task. Polly dispatched a codex reviewer twice; both attempts produced a one-item conversation and this error:
inner executor error: Codex native thread never started: Codex app-server never
started a thread (startup timed out: TimeoutError). See the runner log near
'native-codex routing' for the resolved provider/model.
Polly correctly reported that it could not obtain cross-vendor review and refused to merge — but the underlying cause is not visible from the error text, which points at provider/model routing rather than at the hook prompt.
Root cause
Codex keys hook-trust records by the absolute path of the file that declares the hook:
[hooks.state."/home/<user>/.codex/hooks.json:pre_tool_use:0:0"]
trusted_hash = "sha256:…"
codex-native provisions a private per-session CODEX_HOME
(~/.omnigent/codex-native/<session-id>/codex-home/) and copies config.toml
and hooks.json into it (_populate_codex_home_config, _CODEX_HOME_COPY_FILES).
The copied hooks.state keys still reference the original paths, while the
hooks are now loaded from the new path. Every key therefore misses, and
Codex classifies all hooks as new or changed.
Verified on a live install — trust keys inside one session's private home:
4 entries → /home/<user>/.codex/config.toml (global, not used here)
9 entries → /home/<user>/.codex/hooks.json (global, not used here)
3 entries → /home/<user>/.omnigent/codex-native/<other-session-id>/codex-home/hooks.json
The third group is trust granted interactively during an earlier session: it
carries that session's id, so the next session — with a fresh id — misses again.
Trust granted through the TUI is written into the ephemeral home and discarded
with it, so the prompt reappears on every single launch and can never be
satisfied for headless runs.
Reproduction
- Configure any Codex hook, e.g.
~/.codex/hooks.json with a SessionStart entry.
- Run
omnigent codex once and choose Trust all and continue. Codex starts normally.
- Run
omnigent codex again → "Hooks need review — N hooks are new or changed" appears again.
- Ask
polly to dispatch a codex sub-agent → Codex native thread never started … startup timed out.
Step 3 is the minimal reproduction; step 4 is the user-visible failure.
Proposed fix
When materialising the private CODEX_HOME, rewrite hooks.state keys so the
path component points at the copied files instead of the originals:
[hooks.state."<global home>/hooks.json:pre_tool_use:0:0"]
→ [hooks.state."<private home>/hooks.json:pre_tool_use:0:0"]
The hash component stays untouched, so trust is neither widened nor weakened —
it is only carried across the copy that Omnigent itself performs. Users who
already trust their hooks globally keep working; users who do not are still
prompted, as today.
Two smaller points, if useful:
- The timeout message could name the real blocker.
_CODEX_THREAD_START_TIMEOUT_SECONDS = 15.0
in codex_native.py is hit whenever the TUI is waiting on any interactive
prompt; pointing only at provider/model routing sends the reader in the wrong
direction. (I first misdiagnosed this as MCP startup cost — with 21 MCP servers
configured — and only found the real cause by attaching to the terminal.)
- Codex warns
loading hooks from both …/hooks.json and …/config.toml; prefer a single representation for this layer when both are present. Since Omnigent
copies both, users with hooks in config.toml see this warning on every
native-Codex session.
Environment
- Omnigent 0.6.0, self-hosted server, Linux (Ubuntu 24.04)
- Codex CLI 0.145.0, logged in via subscription
- 21 MCP servers configured (not the cause — plain
codex exec starts in ~7.8s)
- Hooks: 5 events declared in
~/.codex/hooks.json, 3 more in ~/.codex/config.toml
Happy to test a patch against this setup — the failure reproduces every time.
Summary
codex-nativesub-agents can never start when the user has Codex hooks configured. The per-sessionCODEX_HOMEbreaks Codex's hook-trust records, so Codex opens an interactive "Hooks need review" prompt on every launch. In a headless sub-agent there is nobody to answer it, the app-server never emitsthread/started, and the run dies on the 15s timeout.This also affects the bundled
pollyorchestrator: itscodexsub-agent is declared ascodex-native, so cross-vendor review — polly's core guarantee — silently never runs on any machine where Codex hooks are configured.Impact
Observed while running
pollyon a real task. Polly dispatched acodexreviewer twice; both attempts produced a one-item conversation and this error:Polly correctly reported that it could not obtain cross-vendor review and refused to merge — but the underlying cause is not visible from the error text, which points at provider/model routing rather than at the hook prompt.
Root cause
Codex keys hook-trust records by the absolute path of the file that declares the hook:
codex-nativeprovisions a private per-sessionCODEX_HOME(
~/.omnigent/codex-native/<session-id>/codex-home/) and copiesconfig.tomland
hooks.jsoninto it (_populate_codex_home_config,_CODEX_HOME_COPY_FILES).The copied
hooks.statekeys still reference the original paths, while thehooks are now loaded from the new path. Every key therefore misses, and
Codex classifies all hooks as new or changed.
Verified on a live install — trust keys inside one session's private home:
The third group is trust granted interactively during an earlier session: it
carries that session's id, so the next session — with a fresh id — misses again.
Trust granted through the TUI is written into the ephemeral home and discarded
with it, so the prompt reappears on every single launch and can never be
satisfied for headless runs.
Reproduction
~/.codex/hooks.jsonwith aSessionStartentry.omnigent codexonce and choose Trust all and continue. Codex starts normally.omnigent codexagain → "Hooks need review — N hooks are new or changed" appears again.pollyto dispatch acodexsub-agent →Codex native thread never started … startup timed out.Step 3 is the minimal reproduction; step 4 is the user-visible failure.
Proposed fix
When materialising the private
CODEX_HOME, rewritehooks.statekeys so thepath component points at the copied files instead of the originals:
The hash component stays untouched, so trust is neither widened nor weakened —
it is only carried across the copy that Omnigent itself performs. Users who
already trust their hooks globally keep working; users who do not are still
prompted, as today.
Two smaller points, if useful:
_CODEX_THREAD_START_TIMEOUT_SECONDS = 15.0in
codex_native.pyis hit whenever the TUI is waiting on any interactiveprompt; pointing only at provider/model routing sends the reader in the wrong
direction. (I first misdiagnosed this as MCP startup cost — with 21 MCP servers
configured — and only found the real cause by attaching to the terminal.)
loading hooks from both …/hooks.json and …/config.toml; prefer a single representation for this layerwhen both are present. Since Omnigentcopies both, users with hooks in
config.tomlsee this warning on everynative-Codex session.
Environment
codex execstarts in ~7.8s)~/.codex/hooks.json, 3 more in~/.codex/config.tomlHappy to test a patch against this setup — the failure reproduces every time.