macOS app: default exec_command resolves /bin/zsh as relative bin/zsh when login shell is fish
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using (From “About Codex” dialog)?
- ChatGPT desktop app: 26.810.52044 (build 6662)
- Bundled Codex CLI:
codex-cli 0.148.0-alpha.9 - Standalone Codex CLI:
codex-cli 0.147.0
What subscription do you have?
Logged in using ChatGPT. The exact subscription tier is not exposed in the local agent environment.
What platform is your computer?
Darwin 25.5.0 arm64 arm
macOS 26.5.2 (build 25F84)
Apple Silicon
Login shell:
SHELL=/opt/homebrew/bin/fish
fish, version 4.8.1
What issue are you seeing?
The first local shell tool call commonly omits the optional shell parameter. In this environment that call fails before the requested command starts:
sandbox-exec: execvp() of 'bin/zsh' failed: No such file or directory
The important detail is that the failing executable is the relative path bin/zsh, not the valid absolute path /bin/zsh.
Retrying the same command with either of these explicit settings succeeds:
shell: "/bin/zsh"
login: false
shell: "/opt/homebrew/bin/fish"
login: false
This makes the problem appear to happen only on the initial/default shell call: after the failure, the agent can recover by explicitly selecting an absolute shell path.
What steps can reproduce the bug?
-
On macOS, configure the login shell as Homebrew fish:
/opt/homebrew/bin/fish. -
Start a local Codex/ChatGPT desktop thread.
-
Have the agent invoke
exec_commandfor a trivial command such aspwd, omitting the optionalshellfield. -
Observe:
sandbox-exec: execvp() of 'bin/zsh' failed: No such file or directory -
Retry the same command with
shell: "/bin/zsh"andlogin: false. -
Observe that the command succeeds.
The behavior was reproduced with simple commands and is independent of the workspace command itself.
What is the expected behavior?
When the shell parameter is omitted, the app should resolve the default/fallback shell to a valid absolute executable path and preserve the leading slash when launching it.
For an unsupported login shell such as fish, the existing macOS fallback to zsh should launch /bin/zsh, not bin/zsh.
Additional information
The public shell detection code currently declares the macOS zsh fallback as the absolute path /bin/zsh and falls back to zsh when the user's shell type is unsupported:
- https://github.com/openai/codex/blob/main/codex-rs/shell-command/src/shell_detect.rs#L166
- https://github.com/openai/codex/blob/main/codex-rs/shell-command/src/shell_detect.rs#L275-L286
This suggests the leading slash may be lost after shell detection, possibly at an app/unified-exec process boundary.
Related issues, but with materially different reproduction:
- #37594 and #20770: explicit shell paths also fail and all exec calls are blocked.
- #3916: the user's default shell is not respected, but it does not report the relative
bin/zshlaunch failure.
Current workaround: instruct the agent to always pass an absolute shell path and login: false.
No session transcript or app logs are attached because they may contain private workspace data.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the omitted-shell call on macOS with a Homebrew fish login shell, then inspect codex-rs/shell-command/src/shell_detect.rs at the cited lines. Trace how the detected /bin/zsh fallback crosses the app/unified-exec boundary. Done means the default call launches the absolute /bin/zsh path and the reported relative bin/zsh failure no longer occurs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fish, macos, rust, zsh
- Domain
- cli, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100