Table of Contents
Yet another installation of my personal notes for setting up a new (or cleanly installed) MacOS computer. I will try really hard to reproduce the steps in an order that make then easiest to execute.
Note that none of the steps below require an Apple ID, but I did sign in from the start to make it easier to transfer links etc from a laptop during setup.
bootstrapping from another system
I do copy some things over from my previous computer, but it's pretty minimal. Here's the command to gather up what I need to transfer.
tar --exclude '.gnupg/S.*' -cf dotfiles.tar .aws .gitconfig .gnupg .netrc .pypirc .saml2aws .ssh
It's also handy to know all of the projects I'm working on:
cd ~/src for dname in */.git; do git -C $(dirname $dname) remote -v; done > ~/remotes.txt
system update
The first thing I did this time around was to perform a system software update to get all of that waiting out of the way.
Developer tools
Also takes a while. This can be done from the command line:
xcode-select --install
system settings
turn off spelling autocorrect
Search for "spelling" --> Spelling and Prediction --> unselect "Correct spelling automatically" and others
unmap Control + left,right
I use Control plus the left and right arrow keys to move between windows in emacs and tmux. Disable the default mapping to mission control:
System Settings --> Keyboard Shortcuts pane --> Keyboard Shortcuts button --> Mission Control -> uncheck mission control: move left/right a space
Turn on FileVault
System Settings --> Security & privacy --> FileVault
(this was actually enabled by work IT, but leaving here as a reminder)
Window management
Remove the default window margins
Desktop & Dock --> unselect "tiled windows have margins"
I have Ccontrol-Option-Command-m in muscle memory to maximize a window, so add a keyboard shortcut:
Keyboard --> Keyboard Shortcuts --> App Shortcuts --> + Menu title: Fill Shortcut: ⌃⌥⌘M
homebrew
Still a one-liner, now bash rather than ruby:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew doctor
Homebrew is installed to /opt/local on an Apple Silicon Mac. I add the path in my zsh profile like this:
if [[ -d /opt/homebrew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
CLI applications
Many packages are installed later with additional elaboration or in as dependencies for other applications; here are some more or less standalone packages that I routinely install up front.
brew install duckdb && \ brew install fd && \ brew install fswatch && \ brew install fzf && \ brew install gcc && \ brew install git && \ brew install graphviz && \ brew install htop && \ brew install jq && \ brew install latex2rtf && \ brew install mcfly && \ brew install node && \ brew install npm && \ brew install pandoc && \ brew install pngpaste && \ brew install rg && \ brew install tmux && \ brew install tree && \ brew install wget && \ brew install xsv
mactex (takes forever)
brew install --cask mactex
zsh
zsh is the default shell on MacOS.
Install my dotfiles.
cd ~ git clone git@github.com:nhoffman/dotfiles.git dotfiles/mac/bin/install_dotfiles.zsh
emacs
I install emacs using https://emacsformacosx.com
Install my emacs configuration:
cd ~ git clone git@github.com:nhoffman/emacs-config.git .emacs.d
Run setup scripts (come back and do this after python is set up):
cd ~/.emacs.d bin/python-setup.sh
iTerm2
brew install --cask iterm2
Install using homebrew above. Update a few settings.
Settings –> Profiles –> Keys and do these things:
- General: select "Left/right option key acts as": +Esc
- Key Bindings: + –> Keyboard shortcut "OPT+<left arrow>": Send Escape sequence "b"
- Key Bindings: + –> Keyboard shortcut "OPT+<right arrow>": Send Escape sequence "f"
(may have to delete or replace an existing mapping)
Default appearance (I use 15 point on a 15" monitor, 14 on a 13"):
- Settings –> Profiles –> Colors –> Color Presets –> Light Background
- Settings –> Profiles –> Text –> Change Font –> 15 point
Tabs on left:
- Settings –> Appearance –> Tab Bar Location –> Left
Install shell integration:
curl -L https://iterm2.com/shell_integration/install_shell_integration.sh | bash
- Install python runtime by selecting "Scripts" –> "Manage" –> "Install Python Runtime".
- Enable the Python API under "Settings" –> "General" –> "Magic"
python
I avoid using the system python for anything, and I'm all in on uv. It can be installed using homebrew, but I've settled on using the standalone installer to take advantage of the self update.
curl -LsSf https://astral.sh/uv/install.sh | env INSTALLER_NO_MODIFY_PATH=1 sh uv python install 3.13 uv python pin 3.13
The path for uv and installed tools is managed in my dotfiles. Here's the relevant excerpt:
# assumes installation using `brew install uv`
if [[ -d "$HOME/.local/share/uv" ]]; then
export UV_VENV_HOME="$HOME/.local/share/uv/venv"
export UV_PYTHON_PREFERENCE=only-managed
# pinned version stored in ~/.python-version
local python_version=3.13
local python_pinned="$(uv python pin 2> /dev/null)"
if [[ -z $python_pinned ]]; then
uv python pin "$python_version"
elif [[ "$python_pinned" != "$python_version" ]]; then
echo "desired python version is $python_version but $(uv python pin) is pinned"
fi
mkdir -p "$UV_VENV_HOME"
mkvenv(){
local pth=$1
if [[ -n $VIRTUAL_ENV ]]; then
deactivate
fi
if [[ -z "$pth" ]]; then
uv venv && source ".venv/bin/activate"
else
uv venv "$pth" && source "$pth/bin/activate"
fi
}
select-env(){
fd -I --hidden -p -d 3 --regex 'bin/activate$' "${1-.}" | \
awk -F'/' '{print $(NF-2) ":" $0}' | \
fzf --delimiter=":" --with-nth=1 --preview="echo {}" | \
cut -d':' -f 2-
}
venv(){
local target="$(select-env .)"
if [[ -f "$target" ]]; then
echo "$target"
source "$target"
fi
}
fi
llm
I use Simon Willison's llm quite a bit, so might as well set it up here.
uv tool install llm llm install llm-anthropic llm install llm-cmd llm keys set claude --value "$(netrc api.anthropic.com)" llm keys set litellm --value "$(netrc litellm.dlmp.uw.edu)"
Configure access to a litellm query router.
cat > "$(dirname "$(llm logs path)")/extra-openai-models.yaml"<<EOF - model_id: litellm-gpt-4o model_name: gpt-4o-2024-11-20 api_base: "https://litellm.dlmp.uw.edu" api_key_name: litellm - model_id: litellm-gpt-4o-mini model_name: gpt-4o-mini api_base: "https://litellm.dlmp.uw.edu" api_key_name: litellm - model_id: litellm-gpt-4.1 model_name: gpt-4.1 api_base: "https://litellm.dlmp.uw.edu" api_key_name: litellm - model_id: litellm-gpt-4.1-mini model_name: gpt-4.1-mini api_base: "https://litellm.dlmp.uw.edu" api_key_name: litellm - model_id: litellm-o3 model_name: o3 api_base: "https://litellm.dlmp.uw.edu" api_key_name: litellm - model_id: litellm-o4-mini model_name: o4-mini api_base: "https://litellm.dlmp.uw.edu" api_key_name: litellm EOF
llm models default litellm-gpt-4.1
other python packages
uv tool install awscli uv tool install git+https://gitlab.labmed.uw.edu/ngh2/awx.git
R
Installed the arm64 package from https://cran.r-project.org/bin/macosx/
Some packages that I know I'll need:
R --slave << EOF
packages <- c("lattice", "RSQLite", "latticeExtra", "argparse", "data.table", "tidyverse")
install.packages(packages, repos="https://ftp.osuosl.org/pub/cran/", dependencies=TRUE, clean=TRUE, Ncpus=4)
EOF
Also:
brew install --cask rstudio
postgresql
Install from https://postgresapp.com/downloads.html
This installs multiple versions of postgres. My zsh profiile includes the path to the CLI for the latest version, eg:
PATH="/Applications/Postgres.app/Contents/Versions/latest/bin:$PATH"
Docker desktop
Use Homebrew.
brew install --cask docker
Mac M2 Sonoma setup
Table of Contents
Yet another installation of my personal notes for setting up a …
Mac M2 Ventura setup
Table of Contents
Yet another installation of my personal notes for setting up a …
Remap keys for emacs on a remote Windows machine
I have been working on a Windows machine via remote desktop, and am gradually making it bearable. Emacs is miraculously easy to install to my user's account, but it was not immediately obvious how to reproduce my usual configuration of mapping Option to ESC. One solution is provided by Karabiner-Elements …
Mac M1 Monterey setup
Table of Contents
Yet another installation of my personal notes for setting up a new (or cleanly installed) MacOS computer …
Clean install of MacOS Big Sur
Table of Contents
Yet another installation of my personal notes for setting up a new (or cleanly installed) MacOS computer. The …
Clean install of MacOS Catalina
Table of Contents
Another installation of my personal notes for setting up a …
Clean install of MacOS Mojave
Table of Contents
Another installation of my personal …
Clean install of MacOS High Sierra
Table of Contents
I make it a practice to blow …
Setting up a new Mac (Sierra)
Table of Contents
- Edit 2017-01-09: provide upgrade path to Pulse …