Desktop PATH builder appends version-manager shim dirs after the shell PATH — mise/asdf/pyenv/rbenv tools lose to system binaries
Summary
The desktop app adds shim directories for mise, asdf, pyenv and rbenv to PATH. It adds them after the whole extracted shell PATH, so they land after /usr/bin.
For mise this inverts tool resolution. mise inserts its tool bin directories immediately before the shims entry. It assumes shims sit early. When the shims entry sits last, every mise-managed tool drops below /usr/bin, and the system binary wins.
Result: a project pinned to Ruby 4.0.1 runs /usr/bin/ruby 2.6.10 inside the Bash tool. The same command works in the user's terminal.
Environment
- Claude Desktop 1.32352.1, Claude Code 2.1.229
- macOS 26.5.2 (arm64)
- mise 2026.7.12
.zshrcusesmise activate zsh, which is shims-free
Mechanism
From /Applications/Claude.app/Contents/Resources/app.asar. The glob list includes four shim directories:
`${e}/.volta/bin`
`${e}/.local/share/mise/shims`
`${e}/.asdf/shims`
`${e}/.pyenv/shims`
`${e}/.rbenv/shims`
...
`/usr/bin`
The merge keeps the first occurrence of each entry:
async function _Xe(e) {
let t = []; // getExtractedShellPath()
...
let r = process.env.PATH?.split(...) ?? [];
return Array.from(new Set([...t, ...e, ...r]));
}
t is the extracted shell PATH. e is the globbed list above. Because t comes first, any directory already in the shell PATH keeps its shell position.
/usr/bin is in the shell PATH, so it stays early. The mise shims directory is not in the shell PATH — mise activate zsh never adds it. It only arrives through e, so it lands after the entire shell PATH.
Measured in the Bash tool:
16: /usr/bin
29: ~/.local/share/mise/shims
The glob list puts the shims entry before /usr/bin. The merge order reverses that.
Steps to reproduce
- Install mise. Activate it with
mise activate zshin.zshrc. Do not use--shims. - Run
mise reshimso the shims directory exists. - In a project, pin Ruby with
.ruby-versionand setidiomatic_version_file_enable_tools = ["ruby"]in.mise.toml. - Open the project in Claude Code in the desktop app.
- Run a mise task that calls
rubyorbundle.
Expected: the task uses the pinned Ruby.
Actual: the task uses /usr/bin/ruby 2.6.10 and fails. With a Gemfile.lock the error is:
Could not find 'bundler' (4.0.3) required by your Gemfile.lock. (Gem::GemNotFoundException)
from /System/Library/Frameworks/Ruby.framework/Versions/2.6/.../rubygems.rb:302:in `activate_bin_path'
from /usr/bin/bundle:23:in `<main>'
Evidence
One variable, same shell, same project:
| PATH | Result |
| --- | --- |
| shims entry first | PASS |
| shims entry absent | PASS |
| shims entry last (current behavior) | FAIL |
Same task in a clean login shell, which has no shims entry: PASS.
Note for anyone debugging this
Deleting the shims directory does not help. mise anchors on the literal path string, whether or not the directory exists. Deleting it removes the shims and keeps the anchor.
A nonexistent path that is not mise's shims location is ignored, and the task passes. That difference makes it easy to "verify" a fix that does not work.
Impact
Not Ruby-specific. It affects every mise-managed tool, and the same append order applies to the asdf, pyenv and rbenv shim directories.
The failure is silent and confusing. The agent sees a working tool at the wrong version, and the user cannot reproduce it in their terminal.
Suggested fix
Put the globbed directories before the extracted shell PATH:
Array.from(new Set([...e, ...t, ...r]))
This matches the order in the glob list, where the shim directories already sit before /usr/bin. A narrower fix is to place only the shim directories first, since version managers expect their shims early.
Related
Same PATH-builder code path, all closed:
- #54135 — nvm glob ordering, lexicographic sort picked the wrong Node
- #42248 — desktop ignores PATH from all sources
- #46954 — hooks run without
/opt/homebrew/bin
#54135 documents the extraction method used above.