What version of the Codex App are you using (From “About Codex” dialog)?
26.422.71525
What subscription do you have?
API Key
What platform is your computer?
Darwin 25.4.0 arm64 arm
What issue are you seeing?
Codex Desktop shell commands can fail to find tools that are installed via Homebrew, for example gh, even though the same Codex config works when Codex is launched from a terminal.
My config uses shell_environment_policy.inherit = "all" and keeps PATH in include_only. For a CLI/terminal-launched Codex process, tool execution inherits the terminal PATH, which includes /opt/homebrew/bin. In the Desktop app, the app-server process is launched from the macOS GUI environment, so the inherited PATH does not include /opt/homebrew/bin.
Shell snapshots are supposed to bridge that gap by sourcing .zshrc and restoring the resulting shell environment before running the final non-interactive command. In this case, the app-server log shows the shell snapshot was created successfully, but the snapshot omitted the actual PATH export. A later gh --version tool call was logged as /bin/zsh -lc "gh --version" and failed with:
zsh:1: command not found: gh
The likely source is the zsh snapshot export/declare filter. zsh emits tied path parameters as:
export -T PATH path=( /opt/homebrew/bin /usr/bin /bin ... )
but the current filter only preserves simple export/declare -x/typeset -x lines whose parsed name looks like NAME=.... It parses the zsh line as something like -T PATH path, rejects it as an invalid variable name, and drops it. The snapshot succeeds, but does not restore PATH.
What steps can reproduce the bug?
- On macOS with zsh, install
gh or another CLI tool under /opt/homebrew/bin.
- Configure PATH from
~/.zshrc, not from a global launchd environment.
- Use a Codex config that inherits PATH into tool execution, for example:
[shell_environment_policy]
inherit = "all"
ignore_default_excludes = true
include_only = ["HOME", "LOGNAME", "PATH", "SHELL", "USER", "TMPDIR", "TEMP", "TMP"]
- Launch Codex Desktop from the macOS app/Finder/Dock, not from a terminal.
- In a thread, run a command such as
gh --version or command -v gh.
Observed in one Desktop-backed rollout:
command=["/bin/zsh","-lc","gh --version"]
stderr="zsh:1: command not found: gh"
exit_code=127
- Check app-server logs in
~/.codex/logs_2.sqlite: the shell snapshot had succeeded before the command ran, so this was not a snapshot timeout.
- Inspect a generated zsh snapshot under
~/.codex/shell_snapshots/*.sh: there is no top-level export PATH=..., declare -x PATH=..., or typeset -x PATH=...; PATH only appears incidentally inside captured function bodies.
What is the expected behavior?
Codex Desktop should behave the same as a terminal-launched Codex process under the same shell config. If .zshrc adds /opt/homebrew/bin to PATH and the zsh shell snapshot succeeds, subsequent shell commands should be able to resolve tools from that PATH.
The zsh snapshot should preserve tied exported path parameters such as export -T PATH path=(...), or otherwise normalize them into a sourceable scalar export PATH=... line before the final non-login/non-interactive shell command is executed.
Additional information
This appears Desktop-specific because the broken snapshot is masked when Codex is launched from a terminal whose parent environment already contains the desired PATH.
Relevant source locations from current openai/codex:
codex-rs/core/src/shell_snapshot.rs: zsh_snapshot_script() captures exports via export -p | awk ....
codex-rs/core/src/tools/runtimes/mod.rs: maybe_wrap_shell_lc_with_snapshot() sources the snapshot, then executes the original command with exec <shell> -c <script>.
- Current tests only assert that the snapshot text contains
PATH; this can pass when PATH appears inside captured function bodies even if the snapshot does not restore the PATH variable.
In the investigated Desktop session, app-server logs showed:
Shell snapshot successfully created: ~/.codex/shell_snapshots/<thread-id>.tmp-...
No Snapshot command timed out, Failed to create shell snapshot, validation failure, or finalize failure was logged for that thread.
Also, I investigated this issue with Codex, and using the Computer Use MCP, got it to fill out all of the fields. I did review all of the text, I'm not going to subject y'all to my slop.
What version of the Codex App are you using (From “About Codex” dialog)?
26.422.71525
What subscription do you have?
API Key
What platform is your computer?
Darwin 25.4.0 arm64 arm
What issue are you seeing?
Codex Desktop shell commands can fail to find tools that are installed via Homebrew, for example
gh, even though the same Codex config works when Codex is launched from a terminal.My config uses
shell_environment_policy.inherit = "all"and keepsPATHininclude_only. For a CLI/terminal-launched Codex process, tool execution inherits the terminal PATH, which includes/opt/homebrew/bin. In the Desktop app, the app-server process is launched from the macOS GUI environment, so the inherited PATH does not include/opt/homebrew/bin.Shell snapshots are supposed to bridge that gap by sourcing
.zshrcand restoring the resulting shell environment before running the final non-interactive command. In this case, the app-server log shows the shell snapshot was created successfully, but the snapshot omitted the actualPATHexport. A latergh --versiontool call was logged as/bin/zsh -lc "gh --version"and failed with:The likely source is the zsh snapshot export/declare filter. zsh emits tied path parameters as:
export -T PATH path=( /opt/homebrew/bin /usr/bin /bin ... )but the current filter only preserves simple
export/declare -x/typeset -xlines whose parsed name looks likeNAME=.... It parses the zsh line as something like-T PATH path, rejects it as an invalid variable name, and drops it. The snapshot succeeds, but does not restorePATH.What steps can reproduce the bug?
ghor another CLI tool under/opt/homebrew/bin.~/.zshrc, not from a global launchd environment.gh --versionorcommand -v gh.Observed in one Desktop-backed rollout:
~/.codex/logs_2.sqlite: the shell snapshot had succeeded before the command ran, so this was not a snapshot timeout.~/.codex/shell_snapshots/*.sh: there is no top-levelexport PATH=...,declare -x PATH=..., ortypeset -x PATH=...;PATHonly appears incidentally inside captured function bodies.What is the expected behavior?
Codex Desktop should behave the same as a terminal-launched Codex process under the same shell config. If
.zshrcadds/opt/homebrew/binto PATH and the zsh shell snapshot succeeds, subsequent shell commands should be able to resolve tools from that PATH.The zsh snapshot should preserve tied exported path parameters such as
export -T PATH path=(...), or otherwise normalize them into a sourceable scalarexport PATH=...line before the final non-login/non-interactive shell command is executed.Additional information
This appears Desktop-specific because the broken snapshot is masked when Codex is launched from a terminal whose parent environment already contains the desired PATH.
Relevant source locations from current
openai/codex:codex-rs/core/src/shell_snapshot.rs:zsh_snapshot_script()captures exports viaexport -p | awk ....codex-rs/core/src/tools/runtimes/mod.rs:maybe_wrap_shell_lc_with_snapshot()sources the snapshot, then executes the original command withexec <shell> -c <script>.PATH; this can pass whenPATHappears inside captured function bodies even if the snapshot does not restore the PATH variable.In the investigated Desktop session, app-server logs showed:
No
Snapshot command timed out,Failed to create shell snapshot, validation failure, or finalize failure was logged for that thread.Also, I investigated this issue with Codex, and using the Computer Use MCP, got it to fill out all of the fields. I did review all of the text, I'm not going to subject y'all to my slop.