Alan Shortis
Subcribe to the RSS feed

Whether you're starting a new job or buying your own hardware, it's pretty normal for a couple of years to pass between new machines and the set up required to start writing code. This is how I do it.

Table of contents

The first few hours after taking delivery of a new Mac could be spent trying to remember what apps I actually need, how exactly do I run JavaScript locally, and how did I make my terminal look so good AND so easy to use. Below, I run though my approach to getting things just so.

There are some steps that could have unintended consequences. If you're unsure about anything listed below, stop and think before continuing. I accept no liability for any issues that could result from using this guide.

macOS

Once you've started up your machine and logged in/set up the OS, the first thing you should do is check for any updates to the operating system. If there are some, install them.

If you use iCloud and didn't already sign in as part of the OS installation, sign in now. It'll get your files syncing nice and early, and if you're using two Macs it'll sync the clipboard so you can cut and paste between machines.

You don't need to dig around in system preferences to get everything just right. There are a series of commands you can run in the terminal, either one by one or condensed down to a shell script to set everything in one hit (though I prefer not to do this).

Open the default terminal and run each of these commands:

Finder

# Set sidebar icon size to medium
defaults write NSGlobalDomain NSTableViewDefaultSizeMode -int 2

# Expand save panel by default
defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode -bool true
defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode2 -bool true

# Expand print panel by default
defaults write NSGlobalDomain PMPrintingExpandedStateForPrint -bool true
defaults write NSGlobalDomain PMPrintingExpandedStateForPrint2 -bool true

# Expand the following File Info panes:
# “General”, “Open with”, and “Sharing & Permissions”
defaults write com.apple.finder FXInfoPanesExpanded -dict \
  General -bool true \
  OpenWith -bool true \
  Privileges -bool true

# Automatically quit printer app once the print jobs complete
defaults write com.apple.print.PrintingPrefs "Quit When Finished" -bool true

# Remove duplicates in the “Open With” menu (also see `lscleanup` alias)
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user

# Set Downloads as the default location for new Finder windows
defaults write com.apple.finder NewWindowTarget -string "PfDe"
defaults write com.apple.finder NewWindowTargetPath -string "file://${HOME}/Downloads/"

# Don't show icons for hard drives, servers, and removable media on the desktop
defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool false
defaults write com.apple.finder ShowHardDrivesOnDesktop -bool false
defaults write com.apple.finder ShowMountedServersOnDesktop -bool false
defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool false

# Don't show anything on the desktop
defaults write com.apple.finder CreateDesktop false

# Show hidden files by default
defaults write com.apple.finder AppleShowAllFiles -bool true

# Show all filename extensions
defaults write NSGlobalDomain AppleShowAllExtensions -bool true

# Show status bar
defaults write com.apple.finder ShowStatusBar -bool true

# Show path bar
defaults write com.apple.finder ShowPathbar -bool true

# Allow text selection in Quick Look
defaults write com.apple.finder QLEnableTextSelection -bool true

# When performing a search, search the current folder by default
defaults write com.apple.finder FXDefaultSearchScope -string "SCcf"

# Disable the warning when changing a file extension
defaults write com.apple.finder FXEnableExtensionChangeWarning -bool false

# Use list view in all Finder windows by default
defaults write com.apple.finder FXPreferredViewStyle -string "Nlsv"

# Disable the warning before emptying the Trash
defaults write com.apple.finder WarnOnEmptyTrash -bool false

User Experience

# Set the icon size of Dock items
defaults write com.apple.dock tilesize -int 36

# Set the zoomed size for the Dock items
defaults write com.apple.dock largesize -int 86

# Autohide the dock
defaults write com.apple.dock autohide -int 1

# Change minimize/maximize window effect
defaults write com.apple.dock mineffect -string "scale"

# Minimize windows into their application’s icon
defaults write com.apple.dock minimize-to-application -bool true

# Enable spring loading for all Dock items
defaults write com.apple.dock enable-spring-load-actions-on-all-items -bool true

# Set mouse and trackpad tracking speed
defaults write -g com.apple.mouse.scaling 3
defaults write -g com.apple.trackpad.scaling 3

# Enable secondary (right) click with a mouse
defaults write com.apple.driver.AppleBluetoothMultitouch.mouse MouseButtonMode TwoButton

# Disable "natural" scrolling
defaults write NSGlobalDomain com.apple.swipescrolldirection -bool false

# Speed up key repeat rate
defaults write NSGlobalDomain KeyRepeat -int 2

# Stop iTunes from responding to the keyboard media keys
launchctl unload -w /System/Library/LaunchAgents/com.apple.rcd.plist 2> /dev/null

# Require password from sleep or screen saver after 3 seconds
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 3000

# Don’t automatically rearrange Spaces based on most recent use
defaults write com.apple.dock mru-spaces -bool false

# Don't automatically change spaces
defaults write com.apple.dock workspaces-auto-swoosh -bool false

# Copy a plain email address from the Mail app
defaults write com.apple.mail AddressesIncludeNameOnPasteboard -bool false

# Hot corners
# Values:
#  0: no-op
#  2: Mission Control
#  3: Show application windows
#  4: Desktop
#  5: Start screen saver
#  6: Disable screen saver
#  7: Dashboard
# 10: Put display to sleep
# 11: Launchpad
# 12: Notification Center
defaults write com.apple.dock wvous-tl-corner -int 2
defaults write com.apple.dock wvous-tl-modifier -int 0
defaults write com.apple.dock wvous-tr-corner -int 2
defaults write com.apple.dock wvous-tr-modifier -int 0
defaults write com.apple.dock wvous-br-corner -int 5
defaults write com.apple.dock wvous-br-modifier -int 0

Screenshots

# Save screenshots to {user}/Pictures instead of Desktop
defaults write com.apple.screencapture location -string "${HOME}/Pictures"

# Save screenshots in PNG format (other options: BMP, GIF, JPG, PDF, TIFF)
defaults write com.apple.screencapture type -string "png"

# Disable window shadow in screenshots
defaults write com.apple.screencapture disable-shadow -bool true

Miscellaneous

# Use Graphite Highlight Color
defaults write NSGlobalDomain AppleHighlightColor -string "0.780400 0.815700 0.858800"

# Disable "Ask Siri"
defaults write com.apple.assistant.support "Assistant Enabled" -bool false

# Remove Siri icon from status menu
defaults write com.apple.Siri StatusMenuVisible -bool false

# Disable Resume system-wide
# This will stop your mac trying to open everything when started
defaults write com.apple.systempreferences NSQuitAlwaysKeepsWindows -bool false

# Disable automatic termination of inactive apps
defaults write NSGlobalDomain NSDisableAutomaticTermination -bool true

# Disable the crash reporter
defaults write com.apple.CrashReporter DialogType -string "none"

# Check for software updates daily, not just once per week
defaults write com.apple.SoftwareUpdate ScheduleFrequency -int 1

# Increase sound qualty for Bluetooth headphones
defaults write com.apple.BluetoothAudioAgent "Apple Bitpool Max (editable)" 80
defaults write com.apple.BluetoothAudioAgent "Apple Bitpool Min (editable)" 80
defaults write com.apple.BluetoothAudioAgent "Apple Initial Bitpool (editable)" 80
defaults write com.apple.BluetoothAudioAgent "Apple Initial Bitpool Min (editable)" 80
defaults write com.apple.BluetoothAudioAgent "Negotiated Bitpool" 80
defaults write com.apple.BluetoothAudioAgent "Negotiated Bitpool Max" 80
defaults write com.apple.BluetoothAudioAgent "Negotiated Bitpool Min" 80

Nothing will take effect until the Finder and Dock have been killed. It's best to restart at this point.

If for some reason you want to see what any of these options are set to (probably useful if you already have your mouse tracking speed but you'd like to script it), you can replace write with read for any command. Though, something needs to have been set at some time to get a result:

defaults read -g com.apple.mouse.scaling
# '3'

SSH key for source control permissions

If you're working with anything in GitHub that's private, either in a personal repo, an organisation, or in GitHub enterprise, you'll need to set up an SSH key so that you can push/pull with permission as seamlessly as possible.

First follow the steps in Generating a new SSH key and adding it to the ssh-agent, then follow Adding a new SSH key to your GitHub account.

There are similar guides for Bitbucket, GitLab, and Azure DevOps.

If you've recently parted ways with a Mac make sure you delete keys from any services that had them.

Installing apps

Homebrew is a package manager for macOS, meaning you can install the apps you want (where available) from the command line. While it was originally for binaries and packages like Node, Cask extends its powers to include desktop apps.

Open the terminal and paste this command to install Homebrew or copy the command from the Homebrew website if you'd prefer, following the prompts:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Part of Homebrew's installation adds command line tools for Xcode, which saves us a step. It enables git and many other commands in the terminal, including svn if you use that particular flavour of source control.

Once this is done (it'll take a while), you can quickly verify that things are as they should be by running brew and git. Some helpful info and example commands should be shown if each command works.

It's a good idea to get Node.js installed right away. It's the foundation of almost all front end development now, and will also install npm which we'll need to get some global packages and for setting up our terminal later:

# Install Node.js
# You can install a specific version: brew install node@14
brew install node
brew install nvm

# Check Node and NPM have installed if you like
node -v
npm -v

# Some packages that are worth having globally
npm i -g yarn
npm i -g lighthouse
npm i -g nodemon
npm i -g typescript

Before we can install all the desktop apps we want we need to extend what's available to us by installing a new 'tap', homebrew-cask-versions:

brew tap homebrew/cask-versions

Time for our desktop apps:

# Browser
brew install --cask firefox-developer-edition

# Deveopment stuff
brew install --cask hyper
brew install --cask postman
brew install --cask visual-studio-code

# Design/visual stuff
brew install --cask adobe-creative-cloud
brew install --cask figma
brew install --cask vuescan

# Other stuff
brew install --cask slack
brew install --cask spotify
brew install --cask trainerroad

A better terminal

So far we have done everything in the built-in terminal which is totally fine for running occasional commands. However, if you're a developer you're more than likely spending plenty of time in there so improving the user experience will make you much more efficient. We can add some features to help autocomplete commands, remember folders we've been to, and show some contextual information about git branches beside every command.

Hyper

We already installed Hyper using Homebrew, so let's set it up.

I like the One Dark theme for everything, and like everything else in this guide we don't even need to leave the terminal to install this and a few other plugins:

# One Dark theme for Hyper
hyper i hyper-one-dark

# Adds searching with cmd+f
hyper i hyper-search

# Opens new tabs in the same directory as the current tab
hyper i hypercwd

There are plenty of other plugins and themes to choose from.

Oh My Zsh

macOS uses zsh by default now, but I like to use Oh My Zsh as it comes with a lot of useful extras. Install it via the terminal, or copy the command from their website if you'd prefer:

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

It'll only take a few seconds to install, and once it's finished the command prompt will look a little different. Don't worry too much about that as we're going to make it look great soon.

Aliases

Aliases are amazing. If you have long or complex commands that you need run frequently, like starting a server and a web application at the same time while moving between working directories, you can make a very short alias instead. You can also make aliases that are so small they almost seem pointless, but everyone likes a marginal gain.

To add your own, open .zshrc from your user folder (you'll need to open it from finder, and you will have needed to already have made hidden files visible) and at the bottom of the file there are some examples you can edit or replace.

I like to keep a separate .aliases file as I tinker with it pretty often. To do this, create that file in your user directory, then refer to it in .zshrc in place of the aliases already there:

[ -f .aliases ] && source .aliases

These are some of my aliases. It includes an alias to open my aliases. See if you can spot the ones added when I had a faulty keyboard on my 2016 MacBook Pro:

alias c="clear"
alias g="git"
alias gitt="git"
alias gittt="git"
alias gir="git"
alias aliases="cd ~ && code .aliases"
alias dev="npm run dev"
alias as="cd ~/Sites/short.is && npm run dev"

z

z is a little extra magic. It keeps a record of all the directories you've visited in the past and takes you back there even if you only know a little bit of the folder name.

For example, if you visit a folder ~/Sites/design/design-system pretty often, typing z design from ANY other location will take you directly to that folder. It's a huge time saver.

This isn't something we can magically install from the terminal, but it's still not very difficult. Download z.sh from the GitHub repository and save it as is in your user folder (the same place as your aliases and .zshrc). Next, open .zshrc again and add a reference to it at the bottom of the file:

# Include z
. ~/z.sh
zstyle ':completion:*' menu select

Quit Hyper and open it again to ensure the shell is restarted and all settings are loaded. To test that z working:

  • From your user folder (~), make a new folder named 'Sites': mkdir Sites. This is where I like to keep all my web work.
  • cd Sites to visit that folder.
  • Go up one level: ...
  • Type z si and hit enter. You should now be back in the 'Sites' directory.
  • Try the same trick from any other folder, no matter how deeply nested, and you should get the same result.

I love this because I don't need to keep a mental model of what's where, I just need to know roughly what the directory is called.

Auto suggestions

zsh-autosuggestions adds really clean suggestions to the command as you type. If you have ever previously typed git reset --hard origin/main (everyone has) it will show a greyed out suggestion to the right of the cursor. Hit tab, and it'll complete the line for you. This even works with things you've looked for with z for some combination special magic.

Install, or copy the command from the GitHub repository:

git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

Then, add to the plugin list in .zshrc:

plugins=(git zsh-autosuggestions)

There are a lot of plugins that you might like.

Powerlevel10k

Powerlevel10k is a theme for zsh, but it's so much more than decoration. It adds some contextual information to the command prompt and generally makes the terminal a nicer place to spend time. If you ever used Powerlevel9k you'll know that it was a huge headache to set up, but this new version is a breeze.

First, we need to install a font so we have all the icons available that the theme uses. Download from GitHub, then open them all with Font Book and click install.

Open .hyper.js from your user directory and update this line. If you skip this, the theme won't render as expected as the icons will be missing:

fontFamily: "MesloLGS NF",

Next, install the theme itself and apply it:

# Download the theme
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k

# Set the theme in .zshrc
echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>~/.zshrc

Quit Hyper and open it again, and you'll be met with a configuration wizard. It'll ask you about what you want to see, so take your time getting it right. In the end, it'll write changes to .zshrc and create a new file called .p10k.zsh with all your options. It's pretty dense file, so I wouldn't go and edit it manually. If you want to make some changes you can run p10k configure to start the configuration wizard again.

That's the terminal all done. Looking good.

Visual Studio Code

If you have a fresh install and no other Mac to work from, this is where things might get a little manual. The theme and font you choose might come down to taste, and the extensions you choose will depend on what you work on.

Settings sync

If you do have another Mac (permanently or temporarily until you hand it back to a previous employer), Visual Studio Code includes settings sync which lets you share all config and installed extensions across multiple machines. This is going to make set up as close to zero effort as possible.

The below steps are almost identical whether you're on the older Mac (that has the settings) and the newer Mac (that wants them):

  • Open VS Code. From gear icon at the bottom left select 'Turn on Settings Sync...'.
  • You'll be asked what you want to sync. I just choose everything, then click 'Sign in & Turn on'.
  • Select either Microsoft or GitHub to sign in, depending on where it was saved previously. I use GitHub for this.
  • After choosing GitHub, a browser window will open and ask you to authorize. Click continue (after checking you're where you expect to be of course). You'll probably need to login and handle 2FA etc.
  • If you're on the older Mac, it'll push your settings up to GitHub and you won't notice any changes.
  • If you're on the new Mac, you'll see things change pretty quickly, such as your chosen theme and extensions appearing.

Now, any changes made on either machine will appear on the other.

I like to keep a copy of my settings json file in GitHub, separate from the gist created by this plugin.

Done

This is what works for me, and I'd always suggest making adjustments to include things you like, and exclude things you don't. As someone who has both a work and personal Mac (check your contract, because it might be that your company has a claim to ANYTHING you work on with their hardware), being able to automate and sync settings makes for a really consistent experience which ultimately makes me more efficient.

I'm sure I'll be updating this all again before long.