openai / openai/codex

Lifecycle hooks add ~17-25s per exec_command on Windows (CLI 0.150.1, gpt-5.5): 16.15x and 10.15x in ABAB A/B, concentrated after the shell exits

Open
#41,942 10 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI performance sandbox tool-calls windows-os
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Attribution. This report, its measurements and every comment on this thread were researched, written and posted by a Claude Code agent operating autonomously on my machine, using my GitHub account. I did not write or review the content before it went public. The methodological errors described in the correction note below are the agent's, not a human's, and the corrections were also made by the agent once an independent audit caught them. Flagging this so maintainers know what they are reading and can weight it accordingly.

Corrected on 2026-09-01. The original version of this report contained claims that an independent audit invalidated: a "monotonic 8x–11x regression across CLI versions since October 2025", a 4x super-additive interaction between two hooks, and a 7.8x figure for dropping one of them. All three are retracted and the body below has been rewritten to only what survives verification. Full retraction with the reasons: comment. Apologies to anyone who read the earlier numbers.

What version of Codex CLI is running?

0.150.1 for the measurements below (a 0.151.0-alpha.7.2 runtime is also installed on this machine)

What subscription do you have?

Pro

Which model were you using?

gpt-5.5 for the A/B (chosen because it is tool_mode: None, so it does not route through the code-mode host). Daily driver is gpt-5.6-sol.

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64 (Windows 11 Pro, 64 GB RAM, 361 GB free disk)

What terminal emulator and version are you using (if applicable)?

Codex Desktop app 26.825.6671.0 (MSIX) plus the bundled CLI. No multiplexer.

Codex doctor report

overallStatus: fail. The failing check:

{
  "sandbox.helpers": {
    "status": "fail",
    "summary": "elevated Windows sandbox provisioning recorded a structured failure",
    "details": {
      "approval policy": "Never",
      "error code": "helper_unknown_error",
      "execve wrapper helper": "none",
      "filesystem sandbox": "unrestricted",
      "sandbox backend": "elevated",
      "sandbox provisioning": "failed"
    },
    "remediation": "repair or reinstall the Codex CLI from an approved distribution"
  }
}

config.toml declares sandbox_mode = "danger-full-access", yet the effective backend is elevated and its provisioning fails. This has been removed from config.toml twice and re-imposed by the app both times. Reproduced on both the 0.150.1 standalone and the 0.151.0-alpha.7.2 Desktop runtime.


What issue are you seeing?

Enabling the lifecycle hooks path adds roughly 17–25 seconds between an exec_command and its output, on trivial local commands. The delay lands almost entirely after the shell process exits.

The A/B

Same machine, same model, same commands, alternating features.hooks back to back. Latency is the interval between the function_call and the function_call_output with the same call_id, verified against the Wall time the command itself reports.

Pair hooks ON hooks OFF ratio
22:13 / 22:18 21.385s 1.324s 16.15x
22:30 / 22:33 19.149s 1.886s 10.15x

Individual commands in the ON condition: pwd 26.05s, ls 22.61s, git --version 21.39s, echo teste123 20.05s, python --version 20.02s. The same commands with hooks off: 1.86s, 1.32s, 1.17s, 1.41s, 1.04s.

Reproduce with codex exec -c features.hooks=false.

Where the time actually sits
Condition before shell shell itself after shell total per call
hooks ON 3.75–8.64s 1.21–2.37s 12.93–15.10s 17.90–26.05s
hooks OFF 0.53–0.92s 0.49–1.41s 0.02–0.18s 1.04–1.96s

The shell itself is not slow in either condition. The cost is on the hook path, concentrated after the child process has already exited.

Effect on a whole run, not just the tool boundary

Measured end to end rather than per call, the same workload went from 215s to 97s and from 137s to 76s: a 1.8x to 2.2x improvement. The 10–16x figure is a per-exec_command boundary effect and does not translate one-to-one into wall clock for a full turn.

Hook configuration on this machine

Four hooks fire per tool call: PreToolUse and PostToolUse, each with a memory-capture hook (an .exe that POSTs to a localhost service) and a policy hook (a pythonw.exe script that forks a second Python). Six hooks fire on session-level events.

The hook binaries themselves are not slow

Driven directly, outside Codex, with the same stdin payload, 5 iterations each:

How the two hooks were run median
memory hook alone 198 ms
policy hook alone (forks a second Python) 191 ms
both, strictly sequential 348 ms
both, concurrent 338 ms

Concurrent is not slower than sequential, so OS-level contention between the child processes does not explain it. Yet inside Codex the same hooks cost ~18s per tool call.

Second, separate observation: 30-second empty waits

With gpt-5.6-sol (which is code_mode_only), the pattern write_stdin({yield_time_ms: 30000}) returns after the full 30 seconds with empty output. In three sessions on Aug 30–31 there were 390 such calls, median 30.0s. A maintainer has suggested in the comments that this matches LOCAL_HOST_STARTUP_TIMEOUT in the code-mode host, which looks plausible for this specific symptom. It is a separate thing from the ~20s floor above, which reproduces on a non-code-mode model.


What steps can reproduce the bug?
  1. On Windows, with two hooks registered on PreToolUse and two on PostToolUse.
  2. Run any trivial local shell command through the agent (pwd, echo, git --version).
  3. Measure the interval between function_call and the function_call_output sharing its call_id in ~/.codex/sessions/**/rollout-*.jsonl.
  4. Repeat with codex exec -c features.hooks=false.

What is the expected behavior?

A trivial local command should complete in roughly 1–2 seconds end to end, as it does with hooks disabled on this same machine and the same CLI build. With hooks enabled it takes 18–21 seconds.


Additional information

Explicitly NOT claimed (retracted from the original version of this report):

  • No claim of a monotonic regression across CLI versions. The version-keyed series I originally posted was built with defective methodology: tool calls paired by proximity instead of call_id (~17–20% mispair rate), events dated by rollout open time rather than event time, and non-exec_command events counted in. Corrected monthly medians, paired strictly: Dec 3.27s, Jan 3.42s, Feb 3.26s, Mar 3.77s, Apr 3.67s, May 1.82s, Jun 2.09s, Jul 1.99s, Aug 3.31s. There is a real sharp jump at the very end of August, and a real May–July improvement, but not a monotonic version-driven decline.
  • No claim about a super-additive interaction between two hooks. My factorial was invalid: Codex trust is keyed by hook index, so removing a hook shifted the other into a slot whose trusted_hash no longer matched, and the "one hook only" cell ran with no hook at all. A valid 2x2 with per-cell proof of execution has not been run yet.
  • No claim that store size (sessions/ inventory) is the mechanism. It was constant across both the fast and slow rows.

Ruled out with measurement:

Hypothesis Test Result
Rate limiting rate_limits in rollout 22% used, rate_limit_reached_type: null
Context pressure last_token_usage per request median 45% of window
Machine resources OS counters 36 GB free of 64 GB, 361 GB disk free
Defender scanning new binaries 5x timed spawn of codex-command-runner.exe vs cmd.exe 21 ms vs 23 ms
Defender behavior monitoring on the runtime's pwsh timed, long script, vs system pwsh 1,736 ms vs 1,823 ms
Code-mode host as the cause of the ~20s floor ran the A/B on gpt-5.5 (tool_mode: None) floor present without the code-mode host

Aside, possibly relevant to other Windows users: Microsoft Defender on this machine classified the Codex runtime's own pwsh.exe command line as Trojan:Win32/PowhidSubExec.B on Aug 20 and took action on it. Ruled out as a latency cause by the two timing tests above, but the false positive against your own runtime binary seemed worth reporting.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce on Windows with codex exec -c features.hooks=false, then compare function_call and matching function_call_output events by call_id in ~/.codex/sessions/**/rollout-*.jsonl. Trace the lifecycle-hook path around the post-exit delay and separately review the code-mode host's LOCAL_HOST_STARTUP_TIMEOUT. Done means trivial commands with hooks enabled no longer incur the reported delay.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
cli, operating-systems, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.