Setting Up My M1 MacBook Pro for Development

Posted on Feb 12, 2022

Update July 2022: Since I don’t need Development Containers for my new project, I ceased the opportunity and tried out NeoVIM and love it so far. Updated the article accordingly.

Update 15th February 2022: Unfortunately, I could not get our VSCode Development Containers running with Colima. The reason is permission issues when bind mounting volumes from MacOS. I assume this will get fixed soonish. For now, Docker Desktop solves my problems.

I recently switched to an M1 MacBook Pro. I documented most steps I did for the initial setup. I hope this saves my future self and my colleagues some time setting up their machine. This is my first Mac, so please let me know if I’m doing something stupid or suboptimal. Also, let me know if you have more suggestions, especially regarding Mac settings.

Homebrew

You can think of Homebrew as the apt package manager for Mac, but you can install almost all important GUI Apps, fonts, etc. (casks). This will also install xcode cli tools (git, compiler toolchains, …)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Update package list
brew update
# Upgrade installed formulae
brew upgrade

Brew will install two versions for M1 and for x86-64. For your M1, which brew should point to the /opt/... path.

Installing Basic Apps

Installing some essential apps I use regularly (not CLI tools, hence the --cask). I use Alacritty as my main terminal emulator but have iterm2 as backup on my system.

brew install --cask alacritty
brew install --cask iterm2            
brew install --cask firefox
brew install --cask google-chrome
brew install --cask visual-studio-code

Terminal and Oh My Zsh

Settings for the Aalacritty Terminal

You can find my settings here

Gruvbox Theme for Iterm2

Close your terminal and open Iterm2, which is a much better terminal than the default terminal that comes with Mac! First, let’s make the terminal pretty to enjoy the rest of the setup steps: I downloaded the gruvbox color profile In your iterm2 preferences, go to Profiles > Colors > Color Profiles and import the downloaded files.

Oh My ZSH

Next let’s install Oh My Zsh to easily handly plugins, themes, etc

sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" 
omz reload

In ~/.zshrc, add Plugins, I use: plugins=(git z zsh-syntax-highlighting zsh-autosuggestions docker) The last two don’t come with Oh My Zsh, so you have to install them to your custom plugin directory:

git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlighting
omz reload

The omz reload command reloads Oh My Zsh so that you have everything configured without re-starting the terminal.

As a theme and font, I use powerlevel10k. It’s fast, customizable, and easy to install with ohmyzsh. In iterm2, installing powerlevel10k will automatically prompt you to install the required nerd font with all the excellent symbols, do it! Then, of course, you can change the font later. This is the command to download p10k:

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

Now you can go to your .zshrc, set ZSH_THEME=“powerlevel10k/powerlevel10k” and omz reload again. Iterm2 will prompt you to set up Powerlevel10k. After going through the steps, you can further configure the look and feel or re-configure with p10k configure. Don’t forget to allow it to save the changes to your .zshrc

Now let’s get to more development-related topics.

GNU CLI Tools

MacOS has its own flavor of some command-line tools. I want mine to behave the same as Linux, so I brew install the GNU Tools.

brew install coreutils ed findutils gawk gnu-sed gnu-tar grep make wget git gpg

By default, these tools are invoked with a “g” prefix, e.g., ggrep instead of grep. Avoid this by prepending them to your path by putting this into your .zshrc.

# Add Standard GNU Tools to path
# see: https://gist.github.com/skyzyx/3438280b18e4f7c490db8a2a2ca0b9da
if type brew &>/dev/null; then
  HOMEBREW_PREFIX=$(brew --prefix)
  NEWPATH=${PATH}
  # gnubin; gnuman
  for d in ${HOMEBREW_PREFIX}/opt/*/libexec/gnubin; do NEWPATH=$d:$NEWPATH; done
  for d in ${HOMEBREW_PREFIX}/opt/*/libexec/gnuman; do export MANPATH=$d:$MANPATH; done
 export PATH=$(echo ${NEWPATH} | tr ':' '\n' | cat -n | sort -uk2 | sort -n | cut -f2- | xargs | tr ' ' ':')
fi

Now, invoking grep invokes the GNU tools like on a Linux system.

For more info, you can see this discussion where I found the command, or check out / adapt the linuxify script. I chose the above approach because it gives me a bit more control.

Git Config

git config --global init.defaultBranch main
git config --global user.name "your name"
git config --global user.email "your mail"

Docker

Docker is super essential for me because my team uses development containers. Hence, almost all of my development is happening in a container. For now, I’ll try my luck with Colima, a lightweight VM for containers. Colima can be used as a drop-in replacement for Docker Desktop. However, my company is also buying Docker Desktop Licenses to switch if I have problems.

brew install Colima
brew install docker
brew install docker-credential-helper
# Install Docker Compose v2
mkdir -p ~/.docker/cli-plugins/
curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-darwin-aarch64 -o ~/.docker/cli-plugins/docker-compose
chmod +x ~/.docker/cli-plugins/docker-compose
# Start Colima VM (can be supplied with cpu, memory, and disk flags)
colima start
# Check that installation worked
docker compose Version
docker run hello-world

To make VSCode remote containers work with colima, see here: https://github.com/abiosoft/colima/issues/141

See these articles for more info:

Python / Miniconda / Mambaforge

My strong recommendation is to install mambaforge. Mambafore is just a version of Miniconda that works with conda-forge as a default (among other advantages avoids ToS issues with Anaconda. It also has Mamba as a super-fast drop-in replacement for Conda installed in the base environment. With the conda info command, you can check that the M1 Version was installed

brew install --cask mambaforge
conda init "$(basename "${SHELL}")"
omz reload
conda info
# platform : osx-arm64

I mostly use these local environments for quick tests, PoCs, and side-projects. All of my development for work is set up in a Docker container in which I develop with the VSCode devcontainer feature. This way, we share precisely the same environment among the development team and speed up onboarding tremendously.

Other

Remap CapsLock to Esc

I am a heavy Vim user, so I like to globally remap CapsLock to the Esc keys (who uses CapsLock for anything anyway?). To do this, go to Mac System Preferences > Keyboard > Modifier Keys > Remap CapsLock to Esc

Allow key repeating in VSCode

Holding some keys like u or o doesn’t execute them repeatedly by default but brings up a selection for accented letters. This is bad for navigation with hjkl in Vim. Executing this in the terminal solves the problem:

defaults write -g ApplePressAndHoldEnabled -bool false

If you want to change this only for VSCode you can do:

defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false

This site provides more info

More specific Installs

These apps are more specific to my personal use; choose whichever you need. Hugo is the static site generator used to generate this Blog. Elm is a fully functional language for the frontend that I learn for fun.

brew install hugo elm awscli stow
brew install --cask spotify signal 1password