I love my Apple silicon computer, but having to manually switch to Rosetta-enabled shells for my Intel-only projects was a bummer.
Fish offers a feature to define functions that get called when a variable has changed and Direnv offers a way to set variables when you enter a directory – let’s combine them to automatically switch to Rosetta!
Add the following function to your ~/.config/fish/config.fish
1:
function __switch-to-rosetta --on-variable SWITCH_TO_ROSETTA
if test -n "$SWITCH_TO_ROSETTA"
set --erase SWITCH_TO_ROSETTA
exec arch -x86_64 /usr/local/bin/fish -l
end
end
Then add the following to the top of the .envrc
in the project directory:
if [[ $(sysctl -n sysctl.proc_translated) = 0 ]]; then
export SWITCH_TO_ROSETTA=1
exit 0
fi
The “exit 0
” ensures that my .envrc
doesn’t run setup code like “eval $(pdm venv activate)
” on the wrong architecture.
You’re done! Whenever you enter this directory, and Fish is running on ARM, it will replace itself with an Intel version.
Note that since we use exec
to start the new shell, the ARM shell process is literally replaced by the Rosetta version. That means that you can’t get out of Rosetta mode again; exiting the shell ends the sessions and running “arch -arm64 /opt/homebrew/bin/fish
” does not put you back on ARM.
Bonus Tip: Add a Rosetta Indicator to Your Prompt!
If you’re using starship (which you should, regardless of your shell) you can add the following into your ~/.config/starship.toml
:
[env_var]
variable = 'STARSHIP_CPU'
format = 'on $env_value '
And the following into your ~/.config/fish/config.fish
:
if test (sysctl -n sysctl.proc_translated) = 1
set -x STARSHIP_CPU "🦕🦖"
end
Defining it using
funced
did not work for me. The name of the function doesn’t matter, it’s never called by hand. ↩︎