Support named local environment overlays selectable per thread / turn / tool call

Open 💬 4 comments Opened Jun 10, 2026 by hlky

Summary

Codex currently exposes a single effective shell_environment_policy for a session. That works for projects with one stable local toolchain environment, but it breaks down for workflows that need to switch between multiple local build/runtime environments within the same thread.

A common Windows example is a project that needs:

  • one environment for ROCm / Python GPU tooling
  • a different environment for CPU / MSVC builds, typically initialized via vcvars*.bat or Developer PowerShell

Today the choices are all awkward:

  • put everything into one combined environment override and hope the toolchains coexist
  • relaunch Codex with a different profile
  • use experimental exec-server-backed environments, which are closer to “multiple execution backends” than “multiple local env overlays”

What seems missing is a first-class notion of named local environment overlays.

Problem

[shell_environment_policy] is a single policy object, not a set of named selectable policies.

That creates friction for projects that need to switch toolchains during the same session, for example:

  • building GPU code with a Python / ROCm venv
  • then building CPU-native code with MSVC environment variables from vcvars64.bat
  • then switching back without losing thread state or changing workflows

Profiles are not a good fit here because they are selected at launch and do not support fluid switching within one active thread.

The experimental environments / exec-server model also feels mismatched for this case:

  • it models execution backends, not local shell env presets
  • it introduces wrapper/launcher complexity
  • it is not an ergonomic replacement for “same machine, same repo, different local env overlays”

Proposal

Add named local environments as a first-class config concept, selectable at thread, turn, and tool-call scope.

Example config shape

[local_environments.rocm]
description = "ROCm Python/toolchain environment"

[local_environments.rocm.shell_environment_policy]
inherit = "all"
exclude = ["PATH"]
set = { 
  VIRTUAL_ENV = "H:\\dinoml_v2\\.venv\\rocm",
  Path = "H:\\dinoml_v2\\.venv\\rocm\\Scripts;..."
}

[local_environments.msvc]
description = "MSVC build environment"

[local_environments.msvc.vcvars]
script = "C:\\Program Files\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
arch = "amd64"

[local_environments.base]
description = "No extra overlay"

[environment_selection]
default = "rocm"
available = ["rocm", "msvc", "base"]

Selection semantics

Environment selection should follow this precedence:

  1. explicit tool-call environment
  2. turn-level override
  3. thread sticky environment
  4. config default
  5. existing current behavior

Tool-call shape

Shell-like tools could optionally accept an environment selector:

{
  "command": "cmake --build build-cpu",
  "environment_id": "msvc"
}
{
  "command": "python -c \"import torch; print(torch.version.hip)\"",
  "environment_id": "rocm"
}

Why this is different from exec-server environments

This proposal is not asking for more remote or stdio-backed execution targets.

It is specifically for:

  • one Codex session
  • one local machine
  • one repository / filesystem view
  • one model context
  • multiple local process environment overlays

That is a different problem from selecting multiple execution backends.

Windows-specific need

This seems especially important on Windows, where build environments are often procedural rather than declarative.

For MSVC, users should not have to manually encode the results of vcvars*.bat into set = { ... }. That is brittle and incomplete because vcvars modifies many environment variables, including:

  • PATH
  • INCLUDE
  • LIB
  • LIBPATH
  • Windows SDK and toolchain-specific vars

A first-class vcvars source would be much more robust than forcing users to approximate the result manually.

Suggested implementation model

Each named local environment would resolve to an effective environment map for spawned subprocesses.

This could support multiple sources:

  • direct shell_environment_policy
  • derived environment from a script/command
  • Windows-specific vcvars helper

Example ergonomic built-in for MSVC

[local_environments.msvc.vcvars]
script = "C:\\Program Files\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
host = "x64"
target = "x64"

Performance expectations

For script-derived environments, especially vcvars, Codex should ideally:

  • resolve the environment once
  • snapshot the resulting env map
  • cache it by script path + args + cwd + mtime
  • merge runtime-owned vars like CODEX_THREAD_ID afterward

That avoids rerunning vcvars on every command.

Model-visible context

If multiple local environments are available, <environment_context> could expose them compactly, for example:

<environment_context>
  <cwd>H:\dinoml_v2</cwd>
  <shell>powershell</shell>
  <local_environments>
    <environment id="rocm" current="true" />
    <environment id="msvc" />
    <environment id="base" />
  </local_environments>
</environment_context>

This gives the model enough context to choose the right environment without large token overhead.

Non-goals

This request is not asking for:

  • more remote environment support
  • replacement of existing exec-server environments
  • project-local machine-specific secrets or auth config
  • a second model session per environment

Acceptance criteria

A solution would feel complete if it supports:

  • defining multiple named local environments in config
  • selecting one as the default
  • overriding it per thread
  • overriding it per turn
  • optionally selecting it per shell/unified-exec tool call
  • compact visibility in <environment_context>
  • a first-class way to derive Windows/MSVC env from vcvars
  • caching of derived env snapshots so repeated switches are cheap

Why this would help

This would make Codex much easier to use in real mixed-toolchain projects without requiring users to:

  • relaunch with different profiles
  • maintain brittle combined env overrides
  • route local shell workflows through remote-style execution backends

It would also align better with how developers actually think about these setups: “use the ROCm env for this command, use the MSVC env for that one”, while staying inside the same conversation and repository context.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗