Setting Up a macOS Development Environment on Apple Silicon
Apple Silicon — the M1, M2, M3, and M4 family of chips — has fundamentally changed how developers work on macOS. With its ARM-based architecture, unified memory, and impressive performance-per-watt, it offers a compelling platform for everything from web development to native iOS apps and machine learning. However, because Apple Silicon uses the ARM64 instruction set rather than the x86_64 architecture that dominated Macs for over a decade, setting up a development environment requires some specific considerations. This tutorial walks you through everything you need to build a robust, future-proof dev setup on Apple Silicon.
What Is Apple Silicon?
Apple Silicon is Apple's line of custom system-on-a-chip (SoC) processors based on the ARM architecture. Unlike Intel-based Macs, which used the x86_64 instruction set, Apple Silicon Macs run natively on ARM64. This shift brings significant benefits: faster compilation, longer battery life, and the ability to run iOS and iPadOS apps natively on macOS. For developers, it also means that some tools, libraries, and Docker images need to be ARM-compatible or run through Apple's translation layer, Rosetta 2.
Why It Matters for Developers
The architecture transition matters because software built for x86_64 does not run natively on ARM64. While Rosetta 2 transparently translates many Intel binaries, it comes with performance overhead and does not support kernel extensions or certain virtualization scenarios. A properly configured Apple Silicon dev environment ensures you get native performance, avoid subtle bugs caused by architecture mismatches, and can leverage platform-specific tooling like Metal for GPU compute and Core ML for on-device machine learning.
Prerequisites and Initial Setup
Before installing development tools, make sure your system is ready. You will need a Mac with an Apple Silicon chip, macOS 13 (Ventura) or later (macOS 14 Sonoma or 15 Sequoia recommended), and administrative access to install software.
Install Command Line Tools
The Xcode Command Line Tools provide git, make, clang, and other essentials. Install them by running:
xcode-select --install
Follow the prompt to complete installation. Verify with:
clang --version
git --version
Decide on Rosetta 2
Some legacy tools still require x86_64. Install Rosetta 2 only if you need it:
softwareupdate --install-rosetta --agree-to-license
You can run a specific terminal or binary under Rosetta by right-clicking the app in Finder, selecting "Get Info," and checking "Open using Rosetta." For most modern development, however, prefer native ARM64 binaries.
Installing Homebrew
Homebrew is the de facto package manager for macOS. On Apple Silicon, Homebrew installs into /opt/homebrew rather than /usr/local, which is the Intel location. This separation allows both versions to coexist if needed.
Install Homebrew Natively
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
After installation, add Homebrew to your shell configuration. For zsh (the default shell on modern macOS):
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
Verify the installation and architecture:
brew --version
arch
The arch command should report arm64. If you ever need to check whether a specific binary is native ARM or x86, use:
file $(which node)
Look for arm64 in the output to confirm native Apple Silicon support.
Setting Up Your Shell
macOS ships with zsh as the default shell. Enhance it with a modern prompt and useful plugins for a better developer experience.
Install Oh My Zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Useful Plugins and Theme
Edit your ~/.zshrc to enable plugins like git, docker, and syntax highlighting:
plugins=(
git
docker
macos
z
zsh-autosuggestions
zsh-syntax-highlighting
)
ZSH_THEME="agnoster"
Install the autosuggestions and syntax-highlighting plugins:
brew install zsh-autosuggestions zsh-syntax-highlighting
echo "source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh" >> ~/.zshrc
echo "source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ~/.zshrc
source ~/.zshrc
Language Runtimes and Version Managers
For most languages, prefer version managers that compile or download native ARM64 binaries. Avoid installing runtimes via Rosetta unless absolutely necessary.
Node.js with nvm or fnm
For Node.js, fnm is a fast, Rust-based version manager that works well on Apple Silicon:
brew install fnm
echo 'eval "$(fnm env --use-on-cd)"' >> ~/.zshrc
source ~/.zshrc
fnm install --lts
fnm use lts-latest
node --version
Python with pyenv
Python 3.9+ ships with official ARM64 macOS builds. Use pyenv to manage multiple versions:
brew install pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
source ~/.zshrc
pyenv install 3.12.3
pyenv global 3.12.3
python --version
Ruby with rbenv
brew install rbenv ruby-build
echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc
source ~/.zshrc
rbenv install 3.3.1
rbenv global 3.3.1
ruby --version
Go and Rust
Both Go and Rust have excellent native ARM64 support:
brew install go
go version
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
rustc --version
Java with SDKMAN
For Java, use SDKMAN to install native ARM64 JDKs from vendors like Azul Zulu, Eclipse Temurin, or Amazon Corretto:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk list java | grep "17.*arm"
sdk install java 17.0.10-tem
java -version
Docker and Container Development
Docker on Apple Silicon uses a lightweight virtual machine to run containers. Most popular images now ship multi-arch manifests, but some legacy images are x86-only and will run through emulation, which is slower.
Install Docker Desktop
brew install --cask docker
Launch Docker from Applications and complete the onboarding. Verify with:
docker --version
docker run --rm hello-world
docker run --rm --platform linux/arm64 alpine uname -m
The last command should return aarch64, confirming native ARM64 container execution.
Handling x86-Only Images
If you must use an x86 image, Docker will emulate it via QEMU. You can force a platform:
docker run --rm --platform linux/amd64 alpine uname -m
This returns x86_64 but runs significantly slower. Whenever possible, choose multi-arch images or build your own.
Build Multi-Arch Images with buildx
docker buildx create --use --name multiarch
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .
Database and Data Tools
Most databases run natively on Apple Silicon. Install common ones via Homebrew:
brew install postgresql@16
brew services start postgresql@16
psql postgres
brew install redis
brew services start redis
brew install mysql
brew services start mysql
For MongoDB, use the official tap:
brew tap mongodb/brew
brew install mongodb-community
brew services start mongodb-community
Editor and IDE Configuration
Visual Studio Code
VS Code ships a universal binary that runs natively on Apple Silicon:
brew install --cask visual-studio-code
Recommended extensions for a general dev workflow include:
- ESLint and Prettier for JavaScript/TypeScript
- Python and Pylance for Python development
- GitLens for Git integration
- Docker for container management
- Remote - SSH for remote development
JetBrains IDEs
JetBrains IDEs (IntelliJ IDEA, PyCharm, WebStorm, etc.) all ship native Apple Silicon builds. Install via Homebrew Cask:
brew install --cask intellij-idea
brew install --cask pycharm-ce
brew install --cask webstorm
Xcode for Apple Platform Development
For iOS, macOS, watchOS, or visionOS development, install Xcode from the App Store or via xcodes for version management:
brew install xcodes
xcodes install --latest
xcode-select --switch /Applications/Xcode.app/Contents/Developer
Terminal Multiplexers and Productivity Tools
For managing multiple terminal sessions, tmux and zellij both run natively:
brew install tmux
brew install zellij
Other useful native tools:
brew install ripgrep fzf bat eza tldr gh jq htop
Integrate fzf with your shell:
echo 'source <(fzf --zsh)' >> ~/.zshrc
source ~/.zshrc
Machine Learning and GPU Compute
Apple Silicon includes a Neural Engine and a unified GPU accessible via the Metal framework. For ML workloads, use Apple's native tooling.
Install MLX
MLX is Apple's array framework for machine learning on Apple Silicon:
pip install mlx
PyTorch with MPS
PyTorch supports the Metal Performance Shaders (MPS) backend for GPU acceleration:
pip install torch torchvision
python -c "import torch; print(torch.backends.mps.is_available())"
If the command prints True, you can move tensors to the MPS device:
import torch
device = torch.device("mps")
x = torch.randn(1000, 1000, device=device)
y = x @ x
print(y.sum().item())
Best Practices
- Prefer native ARM64 binaries. Always check that tools and libraries you install are built for Apple Silicon. Use
file $(which <binary>)to verify. - Avoid mixing Homebrew installations. If you ever installed the Intel Homebrew in
/usr/local, remove it or keep paths separate to prevent conflicts. - Pin versions in projects. Use
.nvmrc,.python-version,.ruby-version, or.tool-versions(withasdf) so teammates get consistent environments. - Use multi-arch Docker images. When building containers, target both
linux/amd64andlinux/arm64so your images work in production on x86 servers and locally on Apple Silicon. - Keep Rosetta usage minimal. Reserve Rosetta 2 for tools that genuinely lack ARM builds. Native execution is faster and avoids subtle compatibility issues.
- Automate setup with a Brewfile. Track your installed packages in a
Brewfileso you can reproduce your environment on a new machine. - Use dotfiles repos. Store your shell configs, editor settings, and scripts in a Git repository for portability.
- Monitor resource usage. Use
htopor Activity Monitor to spot Rosetta-translated processes consuming excessive CPU.
Create a Brewfile
brew bundle dump --file=~/Brewfile --force
Restore on a new machine:
brew bundle --file=~/Brewfile
Verifying Your Environment
Run this quick sanity check to confirm everything is native:
echo "Architecture: $(arch)"
echo "Homebrew: $(brew --prefix)"
echo "Node: $(file $(which node) | awk -F: '{print $2}')"
echo "Python: $(file $(which python) | awk -F: '{print $2}')"
echo "Docker: $(docker version --format '{{.Server.Os}}/{{.Server.Arch}}')"
Expected output should show arm64 for the architecture, /opt/homebrew for Homebrew, and arm64 or aarch64 for the runtimes.
Conclusion
Setting up a development environment on Apple Silicon is straightforward once you understand the architectural differences and follow native-first practices. By installing ARM64 versions of your tools, leveraging Homebrew's /opt/homebrew prefix, using multi-arch Docker images, and taking advantage of platform-specific features like the MPS backend for PyTorch and MLX for machine learning, you can build a fast, efficient, and reproducible workflow. Keep your environment documented in a Brewfile and dotfiles repository, prefer native binaries over Rosetta translation, and you will enjoy the full performance benefits that Apple Silicon has to offer for years to come.