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)

Open Beginner friendly
#528 6 comments 4 reactions 0 assignees View on GitHub

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.sh contained 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-character bash -c string (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

  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

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.