openai / openai/codex-plugin-cc
SessionStart hook is killed by its own 5s timeout, silently dropping CODEX_COMPANION_SESSION_ID
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
SessionStart carries the same timeout: 5 as SessionEnd (hooks.json). #474 asks to raise SessionEnd "while leaving the SessionStart timeout unchanged". I have measurements from a Windows machine saying SessionStart needs it too — it has been killed at that ceiling at least 6 times in 9 days.
What the kill costs
The SessionStart branch does exactly one thing:
function handleSessionStart(input) {
appendEnvVar(SESSION_ID_ENV, input.session_id); // CODEX_COMPANION_SESSION_ID
appendEnvVar(TRANSCRIPT_PATH_ENV, input.transcript_path);
appendEnvVar(PLUGIN_DATA_ENV, process.env[PLUGIN_DATA_ENV]);
}
scripts/session-lifecycle-hook.mjs
Killed, those three are never written, and anything downstream resolving the session id or transcript path from the environment starts without them. A cancelled hook is silent at normal verbosity, so there is no signal that it happened.
Measurements
Aggregated the hook_* attachment entries across the 50 most recently modified session transcripts (9 days, 25 project directories), keyed by command:
codex session-lifecycle-hook.mjs SessionStart recorded=6 avg=5390ms max=5889ms timedOut=6
superpowers run-hook.cmd session-start recorded=59 avg=2209ms max=6839ms timedOut=0
vercel session-start-profiler.mjs recorded=56 avg=1990ms max=6410ms timedOut=0
vercel inject-claude-md.mjs recorded=56 avg=1385ms max=6431ms timedOut=0
caveman caveman-activate.js recorded=58 avg=1154ms max=2778ms timedOut=0
The max column is the argument. Three of the four sibling SessionStart hooks have peaked above 5 seconds on this machine, in these same sessions. They survive it because they run on the default 60s budget. Under timeout: 5 each of those peaks would have been a kill.
Caveat on the counts: Claude Code does not persist a hook run that succeeds with empty output, so successful runs of this hook are invisible in transcripts. The 6 above are the recorded runs, and all 6 are timeouts — I cannot derive a failure rate from this, only that it has happened at least 6 times.
What it is not
Startup cost, ruled out on the same machine:
bare `node -e "0"` 204ms / 232ms / 200ms
import broker-lifecycle + state + app-server 241ms / 266ms
The hook itself, run directly with stdin closed and CLAUDE_ENV_FILE unset so it performs no writes:
run1: 278ms exit=0
run2: 284ms exit=0
run3: 296ms exit=0
~300ms standalone against a 5000ms budget — the code path is not the problem.
I also considered the readHookInput() → fs.readFileSync(0, "utf8") blocking-stdin cause from #191. I do not think that is what this is. stop-review-gate-hook.mjs still uses the identical pattern, and on this same Windows machine the Stop hook completes fine (recorded=13, avg=1707ms, max=6384ms, timedOut=0). Whatever #191 was, stdin is closing here.
What is left is contention: five SessionStart hooks spawn at the same moment, and the sibling numbers show that moment routinely producing 6+ second outliers. timeout: 5 is simply the tightest budget in the noisiest part of the session, guarding the cheapest work.
Ask
- Give
SessionStartthe same treatment #474 asks forSessionEnd— the default 60s, or 30s to match that request. ThreeappendFileSynccalls do not need a deadline shorter than the observed spawn variance of their own event. - Make the loss visible. Downstream code that reads
CODEX_COMPANION_SESSION_IDcould report the variable as missing rather than proceeding as though there were no session. - (Optional, unrelated to the 5s)
SessionStartneeds none ofbroker-lifecycle.mjs,app-server.mjs,state.mjs, orprocess.mjs, all imported eagerly at module top level for theSessionEndpath. Moving them behind a dynamicimport()insidehandleSessionEndwould keep every module-level side effect out of the start path. Measured above, the graph only costs ~250ms, so this is hygiene, not the fix.
Environment
| OS | Windows 11 Enterprise LTSC 2024 (10.0.26100) |
| Claude Code | 2.1.240 |
| Plugin | codex 1.0.6 (marketplace openai-codex) |
| Node | v26.4.0 |
Related: #474 (same value, SessionEnd), #191 (stdin cause I ruled out here).
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with plugins/codex/hooks/hooks.json to inspect the SessionStart timeout, then read scripts/session-lifecycle-hook.mjs and its SessionStart branch. Reproduce or review the reported timeout behavior on Windows and check the existing hook measurements. Done means SessionStart is no longer killed by the current 5s ceiling and missing session environment data is made visible as requested.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 64/100