A clean setup of Mac OS X 10.15 for Python development and more
For personal & professional use.
- Avoid committing secrets into this repo by running
pre-commit install
in this dir. - Want to copy a big dir from an old Mac? Below is
brew install rsync
! It's much faster than Finder's copying util.# boot old Mac while holding `T` to go in Target Disk Mode # password prompt should pop up rsync -au --progress <drag src folder> ~/backup
- Don't forget to take with your whole
.gnupg
folder,.gitconfig
,.envrc
etc! - Chrome settings/bookmarks are not backed up and are assumed to come from its builtin Sync.
# Do you understand zsh internals? I don't.
chsh -s /bin/bash && reset
# show hidden files (finder restart needed)
defaults write com.apple.finder AppleShowAllFiles YES
# disable google chrome dark mode when Mojave dark mode is enabled
defaults write com.google.Chrome NSRequiresAquaSystemAppearance -bool yes
Apple look & feel optimisations
System Preferences/Appearance/
Show scroll bars:
AlwaysClick in the scroll bar to:
Jump to the spot that's clicked
System Preferences/Keyboard/
- Slide
Key Repeat
toFast
- Slide
Delay Until Repeat
to tick one beforeShort
- Enable
Keyboard navigation
- Under
Text Input
, untick/remove allText Replacements...
- Slide
System Preferences/Security & Privacy/
- Under
FileVault
, turn on FileVault
- Under
System Preferences/Accessibility/
- Under
Zoom
, tickUse scroll gesture with modifier keys to zoom:
- Under
Display
, untickShake mouse pointer to locate
- Under
Pointer Control/Trackpad Options...
, tickEnable dragging/three finger drag
- Under
System Preferences/Trackpad/
- Under
Point & Click
, setClick Medium
, enable Tap to click - Under
Scroll & Zoom
, ticks 0, 1, 0, 1 - Under
More Gestures
, set everything to four fingers, disableSwipe between pages
, disableLaunchpad
, enableShow Desktop
- Under
System Preferences/Desktop & Dock/
- Tick
Automatically hide and show the Dock
- Untick
Show suggested and recent apps in Dock
- Tick
System Preferences/Language & Region/
- Set
Number Format
to 1 234 567.89 - Untick
Show suggested and recent apps in Dock
- Set
- Finder preferences
General
New Finder windows show:
home
Advanced
- Tick
Show all filename extensions
When performing a search:
Search the Current Folder
- Tick
- Finder View Options (go home: ⌘⇧H, then ⌘J)
- Change to list view
- Tick
Always open in List View
- Tick
Browse in List View
- Tick
Group by:
NoneSort by:
Name- Tick
Calculate all sizes
- Tick
Show Library Folder
- Click
Use as Defaults
- Finder
View
menu itemShow Tab Bar
Show Path Bar
Show Status Bar
- TextEdit preferences
New Document
Format
: Plain text- Untick
Check spelling as you type
Open and Save
- Untick
Add ".txt" extension to plain text files
- Under
Plain Text File Encoding
, select two timesUTF-8
- Untick
- Screenshot
Options
(to open: ⌘⇧5)- Save to
Clipboard
- Untick
Show Floating Thumbnail
- Save to
# install homebrew (which installs command-line tools)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
brew tap buo/cask-upgrade # `brew cu -a docker` - https://github.com/buo/homebrew-cask-upgrade#usage
# check whether all is good
brew doctor
# and some essentials
# - ruby, gcc-8 are linked in `.bash_profile`
# - node@14 (LTS at time of writing) installs npm
brew install \
git gitmoji bash-completion rsync curl openssl readline automake xz zlib sshfs htop ncdu direnv pwgen gcc rust sqlite3
iTerm nerd font
brew install --cask iterm2 font-inconsolata-lgc-nerd-font
# some blazing fast rust
cargo install ripgrep # rg (search for regex occurrences in directory, fastest regex implementation in the world)
cargo install zoxide # z (cd with auto-complete) - echo 'eval "$(zoxide init bash)"' > ~.bash_profile
brew install zenith # fancy htop with persistent network and disk I/O history graphs
cargo install --git https://github.com/ogham/exa.git # crates.io is heavily outdated at time of writing
cargo install tealdeer # rust implementation of tldr (man for lazy people)
tldr --update # populate cache
# use exa with icons and git status instead of builtin ls
# this is in .bash_profile already
alias ls="exa --all --group-directories-first --icons --level=2" # default level for --tree
alias ll="ls --long --sort=age --git --time=modified --time-style=iso"
# Docker CE - docker.com/community-edition - Open Docker.app manually to install helper and to enable CLI
brew install --cask docker
# Sublime Text - sublimetext.com
brew install --cask sublime-text
# Sublime Merge - sublimemerge.com
brew install --cask sublime-merge
# Google Chrome - google.com/chrome
brew install --cask google-chrome
# PIA VPN - privateinternetaccess.com - Requires manual install from ~/Library/Caches/Homebrew/downloads
brew install --cask private-internet-access
# Tunnelblick OpenVPN - tunnelblick.net
# brew install --cask tunnelblick
# The Unarchiver - theunarchiver.com
brew install --cask the-unarchiver
# f.lux - justgetflux.com - In Preferences/Sessions, tick 'Allow Display Sleep'
# brew install --cask flux
# VLC - videolan.org/vlc
brew install --cask vlc
# Slack - slack.com
# brew install --cask slack
# Zoom.us - zoom.us
brew install --cask zoom
# Whatsapp - whatsapp.com
# brew install --cask whatsapp
# Dropbox - dropbox.com
# brew install --cask dropbox
# Authy - authy.com - Set Master Password in preferences after init
# brew install --cask authy
# Jitsi Meet - jit.si
# brew install --cask jitsi-meet
# Maccy - maccy.app
brew install --cask maccy
# pdflatex - tug.org/mactex/
brew install --cask mactex-no-gui
# stats in menu bar https://github.com/exelban/stats
brew install --cask stats
# rectangle window resizer https://github.com/rxhanson/Rectangle
brew install --cask rectangle
When launching apps for the first time, you might have to accept the dev under System Preferences/Security & Privacy/General
Note: mas will not allow you to install (or even purchase) an app for the first time: it must already be in the Purchased tab of the App Store.
brew install mas
# DaisyDisk - daisydiskapp.com
# give full disk access under sysprefs security tab
mas install 411643860
# Amphetamine - roaringapps.com/app/amphetamine
mas install 937984704
# Telegram - macos.telegram.org - set password and enter behaviour after init
mas install 747648890
Note: first open Chrome for the first time
- Clone (a fork of) this repo and set things up
mkdir ~/git git clone https://github.com/ddelange/new-mac-setup.git ~/git/new-mac-setup ln -s ~/git/new-mac-setup/.bash_profile ~/.bash_profile && source ~/.bash_profile ln -s ~/git/.envrc ~/.envrc # tell direnv to look for env vars when entering/leaving ~ (same file works for nested directories in a cumulative fashion) touch ~/.env # fill this one with your secrets/env vars like `export PYENV_VERSION=vv` mkdir -p ~/.config/htop && ln -s ~/git/new-mac-setup/htoprc ~/.config/htop/htoprc # Sublime Text 3 backup # restore mkdir -p "${HOME}/Library/Application Support/Sublime Text 3/Packages/User" && \ rsync -a "${HOME}/git/new-mac-setup/sublime_text_user_settings/" "${HOME}/Library/Application Support/Sublime Text 3/Packages/User" # create rsync -a "${HOME}/Library/Application Support/Sublime Text 3/Packages/User/" "${HOME}/git/new-mac-setup/sublime_text_user_settings" # Chrome search engines backup # restore sqlite3 "${HOME}/Library/Application Support/Google/Chrome/Default/Web Data" < "${HOME}/git/new-mac-setup/search-engine-export.sql" # create (printf 'begin transaction;\n'; sqlite3 "${HOME}/Library/Application Support/Google/Chrome/Default/Web Data" 'select short_name,keyword,url,favicon_url from keywords' | awk -F\| '{ printf "REPLACE INTO keywords (short_name, keyword, url, favicon_url) values ('"'"%s"'"', '"'"%s"'"', '"'"%s"'"', '"'"%s"'"');\n", $1, $2, $3, $4 }'; printf 'end transaction;\n') > ./search-engine-export.sql
- iTerm2 preferences: under
General/Preferences
, tickLoad preferences from a custom folder or URL
and paste~/git/new-mac-setup
. Quit iTerm - Stats preferences: in
General/Import Settings...
, selectStats settings.plist
. Drag & drop menu bar items with ⌘+drag - iStat Menus preferences: in
File/Import Settings...
, selectiStat Menus Settings.ismp
. Drag & drop menu bar items with ⌘+drag - Quickly download audio & video with
yt
brew install ddelange/brewformulae/yt
- Note: pyvenv-virtualenv needs to be initialised in
~/.bash_profile
(already present there in the right order to cooperate with direnv), or in~/.bashrc
if both files are maintained separately:eval "$(pyenv init -)" if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi
- Set up latest Python versions (this needs the
LDFLAGS
andCPPFLAGS
in.bash_profile
):brew install pyenv pyenv-virtualenv # get your favourite python versions - github.com/momo-lab/pyenv-install-latest git clone https://github.com/momo-lab/pyenv-install-latest.git "$(pyenv root)"/plugins/pyenv-install-latest git clone https://github.com/concordusapps/pyenv-implict.git "$(pyenv root)"/plugins/pyenv-implict pyenv install -l | grep '^\s*[0-9]' # list all available python versions pyenv install-latest 2 pyenv install-latest 3.12 pyenv versions # see currently installed versions pyenv global $(pyenv install-latest --print 3.12) $(pyenv install-latest --print 2.7) # set default versions: prefer py3 over py2 # install virtualenv 'vv' based latest pyenv Python version 3.x, inheriting installed packages pyenv virtualenv $(pyenv install-latest --print 3.12) --system-site-packages vv312 # same for 'vv27' with python 2.7.x pyenv virtualenv $(pyenv install-latest --print 2.7) --system-site-packages vv27
- Auto-activate venv using direnv when cd'ing into a folder containing an
.envrc
and.env
:echo 'export PYENV_VERSION=vv312' >> ~/.env ln -s ~/git/.envrc ~/.envrc # if it wasn't done already
- Manage envs
pyenvls # alias in .bash_profile pyenv virtualenvs pyenv virtualenv --system-site-packages <venv-name> pyenv activate <venv-name> pyenv deactivate pyenv uninstall <venv-name>
- Add an env var like
export PYENV_VERSION=vv
to your direnv.env
file to automatically activate and deactivate when entering and leaving directories. Works as long as you don't put a dash (-
) in your venv name.
brew install tfenv tflint
tfenv install
tfenv use
Enable and set up 2FA. It's recommended to first delete any git configurations locally after enabling 2FA.
- Use built-in keychain and app password from above, and add a Mac specific global gitignore:
git config --global user.name "ddelange" git config --global user.email "14880945+ddelange@users.noreply.github.com" # fetch this from https://github.com/settings/emails git config --global credential.helper osxkeychain # EITHER curl -sLw "\n" "http://gitignore.io/api/macos,python,django,sublimetext" >> ~/.gitignore # for all possibilities see http://gitignore.io/api/list # OR cp .gitignore.global ~/.gitignore # can no longer be a symlink on git version 2.32+ git config --global core.excludesfile "~/.gitignore"
- Note: it's advised to add commit signature verification to Git.
- EITHER get the existing
~/.gnupg/
from your old machine - OR Generate a GPG key and tell Git to use it:
brew install gpg gpg --full-generate-key # recommended settings: enter, ed25519, enter gpg --list-secret-keys --keyid-format LONG # copy the signing key after 'sec ed25519/' gpg --armor --export <key-here> # paste this key at github.com/settings/keys git config --global user.signingkey <key-here> git config --global commit.gpgsign true git config --global gpg.program "$(which gpg)" # sign tags using git tag -s
- To enable password caching for 1 week:
echo "default-cache-ttl 604800" >> ~/.gnupg/gpg-agent.conf echo "max-cache-ttl 604800" >> ~/.gnupg/gpg-agent.conf echo "log-file /var/log/gpg-agent.log" >> ~/.gnupg/gpg-agent.conf
git config --global pull.rebase false
git config --global core.trustctime false # http://www.git-tower.com/blog/make-git-rebase-safe-on-osx
git config --global core.precomposeunicode false # http://michael-kuehnel.de/git/2014/11/21/git-mac-osx-and-german-umlaute.html
git config --global core.untrackedCache true # https://git-scm.com/docs/git-update-index#_untracked_cache
git config --global merge.log true # Include summaries of merged commits in newly created merge commit messages
git config --global push.default "simple" # https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault
git config --global push.followTags true # https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushfollowTags
git config --global init.defaultBranch master
Some of these aliases depend on one another, in which case it's noted in the comments.
git config --global alias.br "branch"
git config --global alias.ca "commit -am"
git config --global alias.cm "commit"
git config --global alias.co "checkout"
git config --global alias.mt "mergetool"
git config --global alias.st "status"
# split diff - needs icdiff (see below) - use `git icdiff` to keep output in terminal after less quits
git config --global alias.df '! f() { diff=$(git difft "$@") && test "$diff" && echo "$diff" | less -eR; }; f'
# who needs the default verbose git log? - also try `git lg --all`
git config --global alias.lg "log --graph --oneline"
# tested with GitHub remote - ref https://stackoverflow.com/questions/28666357#comment101797372_50056710
git config --global alias.defaultbranch '! f() { echo $(git remote show origin | grep "HEAD branch" | cut -d ":" -f 2 | xargs); }; f'
# summary of all configured aliases
git config --global alias.alias "! git config --get-regexp '^alias\.' | sed -e s/^alias\.// | grep -v ^'alias ' | sed 's/ /#/' | column -ts#"
# "commit all & push" - needs ca,pr - usage `git cap 'Fix bug'` - runs autoformatting pre-commit hooks, commits all modified tracked files with message, and push
git config --global alias.cap '! f() { git ca "$@" && git pr; }; f'
# "pull request" - push new or existing branch skipping the usual --set-upstream error - alias will be overwritten when git-extras is installed
git config --global alias.pr '! git push --set-upstream origin "$(git rev-parse --abbrev-ref HEAD)"'
# "delete merged" - delete all local branches (-D) that have been deleted (merged) on remote
git config --global alias.dm '! git fetch -p && for branch in `git branch -vv | grep '"': gone] ' | awk '"'{print $1}'"'"'`; do git branch -D $branch; done'
# "fetch purge" - before fetching, remove any remote-tracking references that no longer exist on the remote
git config --global alias.fp "fetch -p --all"
# "rinse & repeat" - needs defaultbranch,dm - usage `git gg [develop]` - return to default branch (or specified branch), delete merged and pull
git config --global alias.gg '! f() { git checkout "${1:-$(git defaultbranch)}" && git dm && git pull; }; f'
# "pull all" - pull all local branches and return to original branch
git config --global alias.pall '! f() { \
START=$(git branch | grep "\*" | sed "s/^.//"); \
for i in $(git branch | sed "s/^.//"); do \
git checkout $i; \
git pull || break; \
done; \
git checkout $START; \
}; f'
# "commit all amend" last commit, adding all modified tracked files to the it without editing the commit message
git config --global alias.amend "commit --amend --reset-author --no-edit -a"
# "commit all amend with message" - add all modified tracked files to the last commit with a new commit message
git config --global alias.camend "commit --amend --reset-author -am"
# "squash last" X commits - allowing to edit a pre-generated commit message before committing - known caveat: when trying to squash into an initial commit, the reset fails
git config --global alias.squashlast '!f(){ TEMP_MSG="$(mktemp)" && git log --format=%B HEAD...HEAD~${1} > "${TEMP_MSG}" && git reset --soft HEAD~${1} && git commit -n --edit --file "${TEMP_MSG}"; rm "${TEMP_MSG}"; }; f'
# "undo" whatever you did last, for instance an erroneous squashlast - ref https://megakemp.com/2016/08/25/git-undo/
git config --global alias.undo '! f() { git reset --hard $(git rev-parse --abbrev-ref HEAD)@{${1-1}}; }; f'
git df
(above) uses less that keeps a clean terminalgit icdiff
andgit difft
(below) uses new core.pager that leaves less output in terminal after exiting
git config --global --replace-all core.pager 'less -+$LESS -eFRSX' # with double quotes, $ will be evaluated
# with diff highlighting
pip install git+https://github.com/jeffkaufman/icdiff.git # installs git-icdiff for `git icdiff``
git config --global icdiff.options "--highlight --line-numbers --numlines=3 --color=always"
git config --global difftool.icdiff.cmd 'icdiff --highlight --line-numbers --numlines=3 --color=always $LOCAL $REMOTE'
# with syntax & diff highlighting
brew install difftastic
git config --global difftool.difft.cmd 'difft --display=side-by-side-show-both --color=always --background=light "$LOCAL" "$REMOTE"'
git config --global alias.difft 'difftool --tool difft --no-prompt'
On failed automatic merge, use Sublime Merge GUI for conflict resolution using git mergetool
or git mt
(see above).
git config --global mergetool.smerge.cmd 'smerge mergetool "$BASE" "$LOCAL" "$REMOTE" -o "$MERGED"'
git config --global mergetool.smerge.trustExitCode true
git config --global mergetool.keepBackup false
git config --global merge.tool smerge
Cleanup (different options)
brew cleanup --prune=0 # delete cache older than 0 days
- Sublime
s
,smerge
- line selctors: ⌘L, ⌘⇧L
- swap lines: ⌃⌘↑/↓
- swap selection shortcut TODO
- forward delete (⌦): fn⌫ or ^D
- cutpaste files: ⌘⌥V
- lock machine: ⌘⇧Q
- spotlight: ⌘␣
- screenshots: ⌘⇧3/4/5 and one window: ⌘⇧4, then ␣
- restore tab: ⌘⇧T
- ^↑/↓
- ⌘~ or ⌘` to switch windows
~.
to stop ssh- emoji chooser: ⌘^␣
- the shortcut-changing prefpane
Full Keyboard Symbol List
- ⌘ is command
- ⌥ is option
- ⌃ is control
- ⇧ is shift
- ⇪ is caps lock
- ← is left arrow
- → is right arrow
- ↑ is up arrow
- ↓ is down arrow
- ⇥ is tab
- ⇤ is backtab
- ↩ is return
- ⌤ is enter
- ⌫ is delete /backspace
- ⌦ is forward delete
- ⇞ is page up
- ⇟ is page down
- ↖ is home
- ↘ is end
- ⌧ is clear
- ␣ is space
- ⎋ is escape
- ⏏ is eject
- To revert to the classic iTunes playlist view from before v12.6:
- Open your iTunes library
- Open and run
Restore old iTunes playlists view.scpt
.
- Scroll horizontally using ⇧, then mouse wheel
Kubernetes CLI (kubectl)
Kubectl is a command line interface for running commands against Kubernetes clusters (like viewing logs or executing commands on pods).
See kubebash kubelogs kubebranch
for plug & play kubectl extensions (they are already in ~/.bash_profile
).
AppleScript to shorten links using the bitly API in a smart way directly with a keyboard shortcut
Not needed for 10.15, it is now built-in.
For almost any Gigabit Ethernet USB hub
- Unzip
AX88179_178A_macintosh_Driver_Installer_v2.13.0.zip
- Install driver
pkg
fromAX88179_178A.dmg
- Restart
- Automate this repo with zero.sh, e.g. https://github.com/msanders/setup
- Add low battery warning plist
- Add LaTeX scripts
- Add Dougs applescripts like Show in Playlists