Fixing Ruby environment for non-interactive shells

If you ever encountered Gem::GemNotFoundException when git hooks try to run Rubocop, Reek, or other tools from within a GUI git client, it's because the correct shell profile didn't get sourced in a non-interactive shell, so mise/asdf/rbenv/another Ruby version manager never activated and the system Ruby kicks in.

Quick fix: add Ruby env init to ~/.zshenv (or officially recommended ~/.zprofile). Here is mise example:

if [[ -x "/opt/homebrew/bin/mise" ]]; then
  eval "$(/opt/homebrew/bin/mise activate zsh --shims)"
fi

Unlike ~/.zshrc, ~/.zshenv loads for non-interactive context. And the --shims flag is specifically designed for cases like that. It just prepends the shims directory to PATH without hooking into the shell, so it's safe for non-interactive contexts.

Alternative solution for Lefthook-managed git callback:

# lefthook-local.yml
rc: eval "$(/opt/homebrew/bin/mise activate bash --shims)"

How to test:

# Before (system default Ruby)
$ zsh -lc "which ruby"
/usr/bin/ruby

# After (proper override)
$ zsh -lc "which ruby"
/Users/alex/.local/share/mise/installs/ruby/<version>/bin/ruby

For findability:

Could not find 'bundler' ... required by your .../Gemfile.lock. Gem::GemNotFoundException


Somewhat related: