openai / openai/codex-plugin-cc
SessionEnd hook can hit 5s timeout on Windows due to shelling out to git
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
On Windows, the codex@openai-codex Claude plugin SessionEnd hook can exceed its configured 5s timeout and Claude reports:
SessionEnd hook [node "${CLAUDE_PLUGIN_ROOT}/scripts/session-lifecycle-hook.mjs" SessionEnd] failed: Hook cancelled
I reproduced this on plugin 1.0.4. In the no-broker teardown path, session-lifecycle-hook.mjs still calls:
handleSessionEnd -> cleanupSessionJobs -> resolveWorkspaceRoot -> ensureGitRepository
resolveWorkspaceRoot delegates to git rev-parse --show-toplevel through runCommand, which uses spawnSync(..., { shell: true }) on Windows. That emits Node DEP0190 and adds shell/git process overhead to every session close.
Local evidence
With realistic SessionEnd hook JSON (hook_event_name, session_id, and cwd) and CLAUDE_PLUGIN_DATA set to the real plugin data dir, the pre-patch hook showed the positive-control DEP0190 on every run:
{
"prePatchElapsedMs": [6205, 4796, 8192],
"prePatchDep0190": [true, true, true]
}
After replacing resolveWorkspaceRoot with a pure fs upward .git walk, the same hook harness completed quickly and emitted no DEP0190:
{
"postPatchElapsedMs": [103, 103, 107],
"postPatchDep0190": [false, false, false]
}
I also compared the full resolveStateDir(cwd) output before and after the patch across 12 cases:
- main checkout and nested subdir
- linked worktree and nested subdir
- junction-accessed worktree and nested subdir
CLAUDE_PLUGIN_DATAset and unset
All state-dir outputs were byte-identical.
Proposed patch
-
In
scripts/lib/workspace.mjs, replaceresolveWorkspaceRoot(cwd)with a purefsupward search for a.gitfile or directory. Returnfs.realpathSync.native()for the found root so both the state-dir hash and rawbasenameslug stay aligned withgit rev-parse --show-toplevel. -
In
scripts/lib/broker-lifecycle.mjs, add a local timeout tosendBrokerShutdown(endpoint). A live-but-unresponsive broker should not be able to hold theSessionEndhook past the configured timeout. A 1500ms socket timeout resolved an intentionally unresponsive named-pipe test in 1516ms.
Notes
- This does not require increasing the hook timeout. Increasing it hides the symptom but also makes Claude block longer on close.
- The broker timeout is not the reproduced no-broker cause; it closes a related live-broker teardown risk.
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 scripts/lib/workspace.mjs and scripts/lib/broker-lifecycle.mjs, then run the realistic SessionEnd hook harness described in the issue on Windows. Done means workspace resolution no longer shells out to git, an unresponsive broker is bounded by the local timeout, state-dir outputs remain identical, and the hook finishes without DEP0190.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- devtools, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100