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
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
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
[env_var] variable = 'STARSHIP_CPU' format = 'on $env_value '
And the following into your
if test (sysctl -n sysctl.proc_translated) = 1 set -x STARSHIP_CPU "🦕🦖" end
Defining it using
funceddid not work for me. The name of the function doesn’t matter, it’s never called by hand. ↩︎