openai / openai/codex-plugin-cc
session-lifecycle-hook: SessionStart appends env exports without dedup - env file grows unboundedly on resume/compact, breaking Bash on Windows (8191-char limit)
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
scripts/session-lifecycle-hook.mjs appends its three export lines to CLAUDE_ENV_FILE on every SessionStart event without checking whether they are already present. Claude Code re-fires SessionStart on every session resume and compaction, so in a long-running session the env file grows without bound.
Because Claude Code prepends the entire env file to every Bash tool invocation, the accumulated duplicates eventually push the composed bash -c string past the Windows 8191-character command-line limit. The command gets truncated mid-token, and every Bash call longer than a few hundred bytes fails with:
/usr/bin/bash: -c: line 70: unexpected EOF while looking for matching `''
The failures look random (long gh pr create commands, heredocs, etc. fail; short commands succeed), which makes this very hard to diagnose from the outside.
Observed impact (real session, plugin v1.0.6, Windows 11)
~/.claude/session-env/<session-id>/sessionstart-hook-1.shcontained the same 3 export lines duplicated 23× (~7.4 KB) after a long session with many compactions/resumes.- Measured via
echo ${#BASH_EXECUTION_STRING}: a 103-character command produced an 8042-characterbash -cstring (lines 1–69 of it were the duplicated exports). - Remaining budget for the actual command was ~250 characters; anything longer was truncated at the 8191-char boundary → shell syntax error.
- Bisected empirically: an all-ASCII
true "AAA…"probe passed at ~360 total bytes and failed at ~400, consistent with the 8191 limit given the ~7.9 KB prefix.
Root cause
appendEnvVar() in scripts/session-lifecycle-hook.mjs:
function appendEnvVar(name, value) {
if (!process.env.CLAUDE_ENV_FILE || value == null || value === "") {
return;
}
fs.appendFileSync(process.env.CLAUDE_ENV_FILE, `export ${name}=${shellEscape(value)}\n`, "utf8");
}
handleSessionStart() calls this for CODEX_COMPANION_SESSION_ID, CODEX_COMPANION_TRANSCRIPT_PATH, and CLAUDE_PLUGIN_DATA on each SessionStart — including source: "resume" / "compact" re-fires — with no dedup.
Suggested fix (verified locally)
Make the append idempotent:
function appendEnvVar(name, value) {
if (!process.env.CLAUDE_ENV_FILE || value == null || value === "") {
return;
}
const line = `export ${name}=${shellEscape(value)}\n`;
try {
if (fs.readFileSync(process.env.CLAUDE_ENV_FILE, "utf8").includes(line)) {
return;
}
} catch {
// file may not exist yet; fall through to append
}
fs.appendFileSync(process.env.CLAUDE_ENV_FILE, line, "utf8");
}
Verified by invoking the hook three times with the same SessionStart payload against a scratch CLAUDE_ENV_FILE: the file stays at exactly 3 lines (unpatched: 9).
An alternative would be to rewrite the file wholesale on each SessionStart (the three values are session-scoped constants), which also self-heals files already bloated by previous plugin versions.
Environment
- Plugin: codex@openai-codex 1.0.6 (marketplace refreshed; 1.0.6 is current latest)
- Claude Code on Windows 11 (Git Bash as the Bash tool shell — the 8191-char limit is what turns the unbounded growth into hard failures, but the growth itself is platform-independent)
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 in scripts/session-lifecycle-hook.mjs, reading appendEnvVar and its calls from handleSessionStart. Invoke the hook three times with the same SessionStart payload against a scratch CLAUDE_ENV_FILE, then verify that repeated session-start events do not add duplicate export lines and the file remains at three lines.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100