Skip to content

Add CODEX_ENV_FILE hook persistence#24650

Closed
abhinav-oai wants to merge 5 commits into
mainfrom
abhinav/codex-env-file-simple
Closed

Add CODEX_ENV_FILE hook persistence#24650
abhinav-oai wants to merge 5 commits into
mainfrom
abhinav/codex-env-file-simple

Conversation

@abhinav-oai
Copy link
Copy Markdown
Collaborator

@abhinav-oai abhinav-oai commented May 26, 2026

Why

CC has CLAUDE_ENV_FILE as a shell script path that gets sourced before Bash commands so hook-written exports can persist across later commands - https://code.claude.com/docs/en/env-vars#variables

Codex needs the same so SessionStart hooks can make PATH, virtualenv, conda, and similar setup visible to shell tools without mutating persistent config or rewriting the user-visible command

What

  • Add a session-scoped CODEX_ENV_FILE, with CLAUDE_ENV_FILE as a compatibility alias for real SessionStart hooks.
  • Source that env file before local shell_command, exec_command, and /shell command execution while preserving the original command for approval, hooks, and display.
  • Keep hook env-file sourcing separate from shell snapshot wrapping, so snapshot policy restoration remains unchanged.
  • Use a fresh env file under tmp/env unless the process explicitly provides CODEX_ENV_FILE or CLAUDE_ENV_FILE, and create the parent directory lazily only when a hook or local shell command needs it.

@abhinav-oai abhinav-oai marked this pull request as ready for review May 27, 2026 00:05
@abhinav-oai abhinav-oai requested a review from a team as a code owner May 27, 2026 00:05
Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fab7852a0c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/core/src/tools/runtimes/shell.rs
Comment thread codex-rs/core/src/tasks/user_shell.rs
Comment thread codex-rs/core/src/hook_env.rs
@abhinav-oai
Copy link
Copy Markdown
Collaborator Author

@codex review again

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e37f412cc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +16 to +19
if let Some(path) = env_path(codex_hooks::CODEX_ENV_FILE_ENV_VAR)
.or_else(|| env_path(codex_hooks::CLAUDE_ENV_FILE_ENV_VAR))
{
return Self { path };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep inherited env-file paths out of sandbox grants

When the parent process has CODEX_ENV_FILE or CLAUDE_ENV_FILE set to a path outside Codex-managed storage, this accepts that arbitrary path as the session env file; later local shell_command/exec_command calls expose it in the command environment and add an exact read permission so the sandbox can source it. That means launching Codex with, for example, CODEX_ENV_FILE=$HOME/.ssh/id_rsa lets a sandboxed model command read a file the workspace sandbox would otherwise block, so inherited paths need to be constrained or tracked separately from the auto-granted managed temp file.

Useful? React with 👍 / 👎.

Comment on lines +220 to +223
handler.env.insert(
crate::CODEX_ENV_FILE_ENV_VAR.to_string(),
env_file_path.clone(),
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Serialize env-file writes across SessionStart hooks

When more than one matching SessionStart handler uses CODEX_ENV_FILE, every handler gets the same path here, but dispatcher::execute_handlers launches the selected handlers concurrently with FuturesUnordered. Hooks that append PATH or override the same variable therefore race, so the resulting env file order is nondeterministic and can reverse or corrupt setup for subsequent shell commands; this needs ordered execution or an ordered merge for env-file-producing hooks.

Useful? React with 👍 / 👎.

Comment on lines +130 to +131
if run_pending_session_start_hooks(&session, &turn_context).await {
return;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't consume SessionStart hooks from auxiliary /shell

This runs pending SessionStart hooks for both standalone /shell turns and /shell commands attached to an already active turn. If a user fires /shell while the newly spawned model turn has not yet reached its own run_pending_session_start_hooks call, the auxiliary task can pop the pending startup hook first; a hook that returns continue: false then only cancels the shell command while the main model turn proceeds without seeing the stop decision. Gate this path to StandaloneTurn so active-turn auxiliary commands cannot steal pending start hooks.

Useful? React with 👍 / 👎.

Comment on lines +22 to +26
Self {
path: codex_home
.join("tmp")
.join(HOOK_ENV_DIR)
.join(format!("{thread_id}-{}.sh", uuid::Uuid::new_v4())),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove Codex-managed env files when sessions end

The automatically chosen env file lives under codex_home/tmp/env, but the new HookEnvFile has no cleanup path (repo-wide references only prepare and source it). SessionStart hooks can write exports containing tokens or other transient setup into this shell script, so every session leaves a plaintext file in Codex home indefinitely; add session-end or stale-file cleanup for files created by Codex instead of relying on the tmp directory name.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant