I mostly use Claude Code, but lately I’ve been using Codex CLI and Codex.app (hereafter “Codex”) more often too. My environment is macOS.
However, after I started using mise in [2026-03-29-1] , I ran into trouble because Codex wouldn’t use the mise-managed Ruby, Node.js, and so on.
Here’s the state I was in:
$ where ruby
/usr/bin/ruby
$ ruby --version
ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25]
The Solution
I solved it by adding the following to ~/.zshenv:
# When Codex CLI and Codex.app run commands, .zshrc's mise activate zsh doesn't take effect,
# so add mise shims to PATH.
if [ -n "$CODEX_SANDBOX" ]; then
PATH=${XDG_DATA_HOME}/mise/shims:$PATH
fi
Here’s the state inside Codex after the change:
$ where ruby
/Users/masutaka/.local/share/mise/shims/ruby
/usr/bin/ruby
$ ruby --version
ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [arm64-darwin25]
Codex’s Command Execution Environment Is a Sandbox
I’d vaguely suspected this for a while, but it seems Codex’s command execution environment runs inside a sandbox.
You can spot the clues from within Codex:
$ env | grep CODEX
CODEX_CI=1
CODEX_SANDBOX=seatbelt
CODEX_THREAD_ID=019e7806-6025-7c13-a3c6-a70d41c13905
“seatbelt” refers to Apple Seatbelt, which appears to be macOS’s sandboxing mechanism.
🔗 macOSで手軽にSandbox環境を構築できるApple Seatbeltの実践ガイド
しかしながら、Apple Seatbeltは公式にドキュメントを公開されておらず、非推奨とされています。一方で実際には多くのアプリケーションやツールで使用されています。
(English translation) However, Apple Seatbelt has no officially published documentation and is considered deprecated. Yet in practice, it’s used by many applications and tools.
I see…
According to this article, Claude Code also adopts Apple Seatbelt, and I confirmed that it can be enabled with /sandbox (see the official documentation
).
Coming from a background of being used to Claude Code, Codex’s sandbox is hard to wrap my head around, but the following article covers it in detail. Much appreciated.
🔗 [Codex] sandbox実行の仕組みと設定方法を完全に理解する
Codex also seems to restrict network access by default. Come to think of it, I remembered that I’d previously set the following in ~/.codex/config.toml:
[sandbox_workspace_write]
network_access = true
The Road to the Solution
At first I tried to solve it with a setting like this in ~/.codex/config.toml, but it didn’t work:
[shell_environment_policy.set]
PATH = "/Users/masutaka/.local/share/mise/shims/ruby:(the existing PATH settings hardcoded here)"
As I dug deeper, it occurred to me: “Doesn’t ~/.zshenv get loaded every time, even inside the sandbox? If Codex-related environment variables are defined, I should be able to handle it in ~/.zshenv.” That led me to the solution.
The reason eval "$(mise activate zsh)" in ~/.zshrc doesn’t take effect is that ~/.zshrc is only loaded for interactive shells. Codex appears to run commands in non-interactive shells, so the settings in ~/.zshenv, which is loaded every time zsh starts, are what take effect.
I also came up with the idea of moving eval "$(mise activate zsh)" itself into ~/.zshenv, and it did actually work. However, I think this isn’t a good approach. The activate PATH method
is a mechanism that updates environment variables every time the prompt is displayed, so using it in a non-interactive shell with no prompt falls outside its intended purpose.
mise also recommends shims for non-interactive environments (scripts, IDEs, CI), so I followed that here. It’s the same approach of adding shims to PATH that I adopted for Emacs in [2026-03-29-1]
.
I wanted to avoid hardcoding PATH into ~/.codex/config.toml since that would mean duplicate management with ~/.zshenv, so I’m glad it settled into a clean form.
Conclusion
I summarized how to make Codex CLI and Codex.app use mise-managed Ruby and Node.js.
I think mise is gradually gaining adoption, but I couldn’t find an answer by Googling and wondered how everyone else handles this, so I wrote this short article. I hope it helps someone.