Desktop app zsh snapshot export filter omits PATH, breaking Homebrew tools
What version of the Codex App are you using (From “About Codex” dialog)?
26.602.71036
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
ghor 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 --versionorcommand -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-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 .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 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>.- Current tests only assert that the snapshot text contains
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:
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.
7 Comments
Potential fix outline:
export -T PATH path=(...).zsh_snapshot_script()to either preserve zsh tied exports in a sourceable form or normalize them toexport PATH=...before filtering.---
Human realization- macOS's default shell is
zsh, so this is probably impacting a lot of users.Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
same issues here!
Fix is in #16974
I found a tangentially related but distinct macOS PATH failure in current Codex Desktop and documented it in:
In that case, the Desktop main process tries to capture the shell environment with
zsh -ilc, but aborts after a hard 5-second timeout. It then retains the GUI launch PATH (/usr/bin:/bin:/usr/sbin:/sbin), so the latergh --versionprobe cannot find/opt/homebrew/bin/ghand the Summary panel rendersGitHub CLI unavailable.That differs from this issue because shell snapshot creation never reaches the successful-but-PATH-omitted state. The environment import fails first. #27740 includes app version, packaged
app.asarfunction paths and hashes, log evidence, and reproduction timings.Same issue here too, this is very annoying as it makes the agent do extra work every time it needs my tools, even when I give it "full access"
Confirming this on ChatGPT desktop for macOS 26.707.41301 (build 5103) with bundled
codex-cli 0.144.0-alpha.4, specifically in the dedicated Pull requests screen.The screen reported
GitHub CLI (gh) is not installedeven though Homebrewgh 2.96.0was installed at/opt/homebrew/bin/ghand authenticated successfully.Observed after a full app restart:
The app-server PATH excludes both
/opt/homebrew/binand/usr/local/bin.launchctl setenv PATH ...followed by a full app restart did not change the PATH inherited by this build.I inspected the packaged app behavior and the Pull Requests availability check invokes
gh --versiondirectly through the local app-server execution host. Because that execution does not use a login shell or restored shell snapshot, it returnsENOENTand the UI labelsghas uninstalled.A targeted workaround confirmed the diagnosis: adding a symlink for
/opt/homebrew/bin/ghinside Codex's existing runtimedependencies/bin/fallbackdirectory immediately made the same app-server PATH resolvegh, passgh --versionandgh auth status, and allowed the Pull Requests detector to work.The same direct-command environment also hid
node,npm,npx,cargo,brew,cmake, and Docker, so this can affect more than GitHub integration.This may be a distinct path from the zsh snapshot parsing described in the original report: the Pull Requests screen appears to run its availability probe directly against the app-server environment. It would help if the desktop app imported the login-shell PATH, included standard Homebrew paths on macOS, or exposed a configurable developer-tools PATH.
An in-product Codex bug report was also recorded without logs. Feedback thread ID:
019f506f-0d44-7fd2-9c38-879285e38947.