Repository navigation
fix: keep only the latest value per key in CLAUDE_ENV_FILE (SessionStart) #748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,11 +32,27 @@ function shellEscape(value) { | |
| return `'${String(value).replace(/'/g, `'\"'\"'`)}'`; | ||
| } | ||
|
|
||
| function appendEnvVar(name, value) { | ||
| if (!process.env.CLAUDE_ENV_FILE || value == null || value === "") { | ||
| function setEnv(name, value) { | ||
| const envFile = process.env.CLAUDE_ENV_FILE; | ||
| if (!envFile || value == null || value === "") { | ||
| return; | ||
| } | ||
| fs.appendFileSync(process.env.CLAUDE_ENV_FILE, `export ${name}=${shellEscape(value)}\n`, "utf8"); | ||
| const prefix = `export ${name}=`; | ||
| const line = `${prefix}${shellEscape(value)}`; | ||
|
|
||
| let content = ""; | ||
| try { | ||
| content = fs.readFileSync(envFile, "utf8"); | ||
| } catch (err) { | ||
| if (err.code !== "ENOENT") throw err; | ||
| } | ||
|
|
||
| const lines = content.split(/\r?\n/).filter((l) => l && !l.startsWith(prefix)); | ||
| lines.push(line); | ||
|
|
||
| const tmp = `${envFile}.${process.pid}.tmp`; | ||
| fs.writeFileSync(tmp, lines.join("\n") + "\n", "utf8"); | ||
| fs.renameSync(tmp, envFile); | ||
|
Comment on lines
+53
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Claude created the existing environment file with a restrictive mode such as Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| function cleanupSessionJobs(cwd, sessionId) { | ||
|
|
@@ -75,9 +91,9 @@ function cleanupSessionJobs(cwd, sessionId) { | |
| } | ||
|
|
||
| function handleSessionStart(input) { | ||
| appendEnvVar(SESSION_ID_ENV, input.session_id); | ||
| appendEnvVar(TRANSCRIPT_PATH_ENV, input.transcript_path); | ||
| appendEnvVar(PLUGIN_DATA_ENV, process.env[PLUGIN_DATA_ENV]); | ||
| setEnv(SESSION_ID_ENV, input.session_id); | ||
| setEnv(TRANSCRIPT_PATH_ENV, input.transcript_path); | ||
| setEnv(PLUGIN_DATA_ENV, process.env[PLUGIN_DATA_ENV]); | ||
| } | ||
|
|
||
| async function handleSessionEnd(input) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When another matching SessionStart hook writes to the shared
CLAUDE_ENV_FILEafter this read, the subsequent whole-file rename silently discards that hook's export. This can occur in installations with additional user or plugin SessionStart hooks, leaving later commands without their persisted environment variables; use an append-based update or otherwise serialize read-modify-write access.Useful? React with 👍 / 👎.