This document assumes you're running a fresh and updated copy of the latest stable macOS release. As of June 2026, that is macOS Tahoe 26 for supported Macs.
- Command Line Interface
- System update and Disk Encryption
- System tweaks
- Projects Directory
- Homebrew
- Privacy
- AI
- Sublime Text and VS Code
- Vim
- ZSH
- SSH
- Git
- Node.js
- Python
- Composer
- VirtualBox
- Laravel Valet
- Docker
Throughout this document, you will encounter examples like this that contain one or more of the arguments listed:
sudo command -flag --flag directory file.extension # Comments are behind pound signsAnytime you see the above, it is referring to your CLI of choice, whether it's the built-in Terminal.app or a third-party terminal like iTerm2. Setting up a command-line shell to your liking is a good idea.
Step One - Update the system!
Apple Icon > System Settings > General > Software Updates
Step Two - Turn on FileVault for full disk encryption
Apple Icon > System Settings > Privacy & Security > FileVault
On a brand new machine or macOS installation, it shouldn't take long depending on the size of your drive. On Apple silicon Macs and Intel Macs with the Apple T2 Security Chip, data is encrypted automatically; FileVault adds protection by requiring your login password before the disk can be unlocked.
Alternatively, you can use a third-party encryption software like Veracrypt, which is open-source and well regarded by the security community.
Why do you want full-disk encryption? Theft.
You're most likely using a portable laptop of some kind. If you lose it, the laptop gets stolen or someone tries to hack into it, your personal data is at risk. Using full-disk encryption is an extra layer of security to keep your mind at ease in case of potential intrusion.
Two main caveats:
- Do not misplace or forget your FileVault recovery key or login password. Losing this password means you cannot log in and without the recovery key everything on your computer is inaccessible if you can't decrypt the files during a recovery. iCloud is one option to store the FileVault password. The other option is downloading it and storing it yourself. Using iCloud, Apple Support will be able to assist you with recovering data. On Apple's servers, iCloud isn't fully encrypted. So, while iCloud is convenient, it's less secure.
- If macOS gets corrupted and you need to download files from the drive after accessing the drive from an external case, it's not possible without the laptop password and FileVault recovery key. Make sure you're both backing up using Time Machine on an external drive or a NAS, and a cloud backup provider like Backblaze.
This is for online protection when you're not in your home network or not behind a router.
Apple Icon > System Settings > Network > Firewall
or
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate onApple's default system settings are limiting and don't show a lot of information. Let's change the settings for better usability around the system.
Note
For all CLI commands, keep in mind you probably have to either log out and log back in OR re-open Finder/Terminal to see the following changes
- [System Settings -> Trackpad -> Point & Click]
- [Tap to click] option
- [System Settings -> Trackpad]
- Click the [More Gestures]
- Enable "App Exposé" and Mission Control > [Swipe up with four fingers]
- [System Settings -> Accessibility]
- In the [Accessibility] sidebar, choose [Pointer Control]
- Click the button [Trackpad Options]
- Enable dragging style with [three-finger drag]
- [System Settings -> Keyboard]
- Move dial to the right in [Key repeat rate] and [Delay until repeat]
OR
defaults write NSGlobalDomain KeyRepeat -int 0defaults write NSGlobalDomain AppleShowAllExtensions -bool truedefaults write com.apple.finder ShowPathbar -bool true
defaults write com.apple.finder ShowStatusBar -bool truedefaults write com.apple.finder _FXShowPosixPathInTitle -bool truedefaults write -g AppleShowAllExtensions -bool truedefaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool truedefaults write com.apple.terminal StringEncodings -array 4Open an application from the web without being asked if that's what you really want to do. Of course it is.
defaults write com.apple.LaunchServices LSQuarantine -bool falseAnother update I prefer is to show all filename extensions in Finder.
[Finder > Settings > Advanced > Show all filename extensions]
This is likely outdated now, less useful than before, but sometimes it's still helpful.
chflags nohidden ~/Library
Alternatively, open Finder, press ⇧⌘H, ⌘2, ⌘J and check “Show Library Folder”. Unhiding this folder could be useful for manual backup, but it's not necessary.
One very important part of using Terminal in my workflow is being able to quickly type commands that run services. Sometimes, you might install something and it is still not available in the Terminal.
echo $PATH
Running this command will return a long string, separated by :, of various paths to services you can reference using line commands. If you install one of the services like Node and typing npm doesn't work, for example, use the above command to check to make sure you see a reference to the path to Node.
In my recent past, I've had issues with Composer's path not being set in the system path. I needed it to run Laravel Valet, which I talk about later in the document. In order to use Valet, I added Composer to the system path using the following command:
export PATH=$PATH:/Users/[username]/.composer/vendor/bin
Of course, [username] is the name of the macOS account you're using. echo $PATH now includes the above path after : to be in the returned string.
If you don't already have one, create a directory for your digital projects. I like to use ~/Sites/<project-name>, and the name Sites can be anything you want. I prefer my Sites folder to exist alongside the rest of my user profile folders.
cd # Go to home directory
mkdir -p ~/SitesDepending on the type of projects you work on, this might not be necessary or preferable.
Package managers make it so much easier to install and update applications (for Operating Systems) or libraries (for programming languages). The most popular one for macOS is Homebrew.
If you're using a native M-series Mac, Homebrew usually installs under /opt/homebrew. On older Intel Macs, it usually installs under /usr/local. The installer prints any shell profile commands you need to add to your path.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
In some cases, you'll have to run a few more commands in the terminal to allow the terminal to use brew in the path. If not, you might have to start a new terminal session.
Run the following command to make sure everything works:
brew doctor
To install a package (or Formula in Homebrew vocabulary) simply type:
brew install <formula>
Replace <formula> with the name of the formula you want to install.
Helpful commands:
brew outdated # check for outdated packages
brew upgrade <formula> # upgrade package to latest version
brew list --versions # check installed packages and versionsHere's a list of my favorite command-line tools and GUI apps that I need for development on a regular basis. Modify the list below as you need.
brew install git python composer lando-cli wireguard-tools
brew install --cask firefox brave-browser tor-browser mullvad-browser eloston-chromium slack visual-studio-code vscodium sublime-text@dev zed sequel-ace imageoptim vlc vnc-viewer signal virtualbox appcleaner mullvadvpn transmission kap libreoffice zoom qbittorrent scroll-reverser docker-desktop
Note
To explicitly install software applications with a GUI, use the flag --cask. An application like transmission can default to a CLI version instead of the GUI-based app.
brew install --cask transmission
Note
Don't use brew to install Node.js, we'll do that below using nvm
For repeatable installs, you can keep the same package list in a Brewfile and run brew bundle.
brew "git"
brew "python"
brew "composer"
brew "lando-cli"
brew "wireguard-tools"
cask "firefox"
cask "visual-studio-code"
cask "vscodium"
cask "sublime-text@dev"
cask "zed"
cask "virtualbox"
cask "docker-desktop"An optional but nice-to-have add-on is Command Line Tools for Xcode. These include compilers that will allow you to build things from source.
Note: if you already installed Homebrew above, it's likely that Xcode was installed for you so you can skip this section.
Xcode weighs something ~2GB and is useful for the iOS simulator but is not necessary unless you're developing iOS or Mac apps. Good news is Apple provides a way to install only the Command Line Tools, without Xcode.
Using Terminal, install the Xcode Command Line Tools:
xcode-select --install
There's not a straightforward way to update Xcode Command Line Tools, so we have to remove the existing tools to reinstall from scratch.
sudo rm -rf /Library/Developer/CommandLineTools
xcode-select --install
I think now is the time to briefly let you know that macOS communicates with remote Apple services by default. Apple collects data on how you use the operating system through a process called Differential Privacy. With this process, Apple knows how many people or devices use what and how often. Apple also knows about their users' habits as a collective, not individuals. There's not a lot of transparency about what's going on but there are many free and open source applications that help us shut down and block as many as we know about.
First, I recommend you look through PrivacyGuides.org. There's a ton of valuable software and links to consume.
One of the more popular OS network monitors and script blockers is called Little Snitch, which I don't personally use but know it has a great reputation. It will keep applications from reporting back stats that can compromise privacy and security.
Depending on your threat model, one other potential tweak to increase privacy is blocking all OCSP calls, which stirred moderate controversy in 2020.
As the 2020s move forward, it is clear that AI is necessary for many tasks. Used properly, it can give feedback that could be expected from senior developers and management. It can give immediate feedback and help that can increase productivity.
Using many code editors, you can integrate many different services like GitHub Copilot using models from OpenAI, Google, or Anthropic.
I can recommend T3 Chat as the most affordable service to use any of the above AI and more as standalone chat services. You can have extensive conversations and get code samples as feedback from the conversations.
The text editor is a developer's most important tool. Everyone has their preferences, but unless you're a hardcore Vim user, I recommend one of two editors: Sublime Text or VS Code.
As of 2025, most of my time is spent in a fork of Visual Studio Code. It found popularity at the end of the 2010s and is a staple open-source code editor for most front-end developers. I use it both personally and professionally because of various built-in features like git support, terminal integration, live sharing your code with another developer (using an extension), and a large repository of great extensions.
brew install --cask visual-studio-code
Using a terminal, add command line code access:
cat << EOF >> ~/.zprofile
# Add Visual Studio Code (code)
export PATH="\$PATH:/Applications/Visual Studio Code.app/Contents/Resources/app/bin"
EOF
I recommend using VSCodium because it strips away the telemetry and tracking that Microsoft/GitHub integrates into VS Code. However, VSCodium has issues with extensions like Live Share, so keep that in mind.
brew install --cask vscodium
Add command line codium access:
Go to the command palette (View | Command Palette...)
Choose Shell command: Install 'codium' command in PATH.
There's a ton of great tutorials and articles, such as VS Code Docs.
Because of the rise of AI since Copilot and the release of ChatGPT, there are multiple projects that take an approach treating AI as a primary integration. I've tried multiple of these editors and they're interesting and helpful if you are good at your craft and can request the right approaches.
Chris Coyier wrote about various code editors in 2025.
Since the early 2010s, my classical goto editor is Sublime Text, because, it just works and is faster than all the rest.
brew install --cask sublime-text@dev
I prefer using the dev build of Sublime Text, which requires a license.
Sublime Text is not free, but it has an unlimited "evaluation period". The seemingly expensive $99 price tag is worth the cost. If you can afford it, I suggest you support this awesome editor. :)
After installing Sublime Text, add Package Control. This is the most important addition you'll make to Sublime Text and it'll give you the power to install plugins, add-ons, themes, color schemes and more.
I recommend to change two color settings:
- Theme (which is how the tabs, the file explorer on the left, etc. look)
- Color Scheme (the colors of the code).
My favorite theme is Material Design Darker as well as Seti_UI Theme.
Go to Tools > Command Palette (Shift-Command-P), Highlight Package Control: Install Package and then search for your preferred theme, make sure it's highlighted then press Enter to install it.
Then go to Sublime Text > Preferences > Settings - User and add the following two lines (using Seti UI) and restart Sublime:
"theme": "Seti.sublime-theme",
"color_scheme": "Packages/Seti_UI/Scheme/Seti.tmTheme",
Let's configure our editor a little. Go to Sublime Text > Preferences > Settings - User and paste this code (and edit it if you want) from my Preferences.sublime-settings file.
I also recommend creating shortcuts so you can launch Sublime Text from the command-line
Now, we can open a file with subl myfile.html or start a new project in the current directory with subl .. Pretty cool!
It is a good idea to learn some very basic usage of Vim. It is a very popular open-source editor accessed using command-line shells and is usually pre-installed on Unix systems.
For example, when you run a git commit, it will open Vim to allow you to type the commit message.
I suggest you read a tutorial on Vim. Grasping the concept of the two "modes" of the editor, Insert (by pressing i) and Normal (by pressing Esc to exit Insert mode), will be the part that feels most unnatural. After that it's just remembering a few important keys.
Vim's default settings aren't great, and you could spend a lot of time tweaking your configuration (the .vimrc file). But if you're like me and just use Vim occasionally, you'll be happy to know that Tim Pope has put together some sensible defaults to quickly get started.
Keeping it simple:
vimtutor
And a minimal ~/.vimrc:
syntax on
set number
set expandtab
set shiftwidth=2
set tabstop=2
set mouse=a
Z Shell, or ZSH, was written to extend Bash and make improvements to how Bash works.
Install or confirm ZSH for your OS:
zsh --version
Install Oh My Zsh! for extra help and nice defaults.
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"Don't forget to customize ZSH!
Themes are available. Autosuggestions and Syntax Highlighting will improve ZSH user experience too.
Sign up and follow the videos recorded by Wes Bos to learn a ton more about ZSH and why it's so powerful. Or a free 80 minute video on YouTube by Karl Hadwen.
SSH is imperative, just like git and node as you'll see.
GitHub has excellent instructions for setting up git and connecting it to a GitHub account. This will help you to install the repos to your computer from GitHub as well as set up keys that you'll need to connect git and GitHub.
Now you can add a little shortcut to make SSHing into other boxes easier. Paste the following block of code into your SSH config file at ~/.ssh/config, changing the variables for any hosts that you connect to.
First:
ssh-keygen -t ed25519 -C "your_email@example.com"
Then:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
Below the above, you can add other sites as needed.
Host myssh
HostName example.com
User user
IdentityFile ~/.ssh/key.pem
With the above code, you can now run the alias myssh to connect.
ssh myssh
What's a developer without Git? Install Git, then configure your identity:
brew install git
git config --global user.name "Your Name Here"
git config --global user.email "your_email@youremail.com"
If you have 2FA enabled on GitHub (you should), you'll also need to follow the Add SSH Key to GitHub and be sure you're using the macOS instructions.
Note: It is important to remember to add .DS_Store (a hidden system file that's put in folders) to your .gitignore files. You can take a look at this repository's .gitignore file for inspiration.
Less keystrokes can be better, so here are optional and sensible shortcuts to a global Git config file.
touch ~/.gitconfig
Pick and choose any of these aliases to help you.
[user]
name = Firstname Lastname
email = you@example.com
[github]
user = username
[alias]
a = add
ca = commit -a
cam = commit -am
cm = commit -m
s = status
pom = push origin main
pog = push origin gh-pages
puom = pull origin main
puog = pull origin gh-pages
cob = checkout -b
co = checkout
fp = fetch --prune --all
l = log --oneline --decorate --graph
lall = log --oneline --decorate --graph --all
ls = log --oneline --decorate --graph --stat
lt = log --graph --decorate --pretty=format:'%C(yellow)%h%Creset%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)%an%Creset'
With the above aliases, I can run git s instead of git status or git ca instead of git commit -a when I have a bunch of file updates.
For modern JavaScript programming, Node.js is required. Using Node Version Manager (nvm) to install Node allows you to easily switch between Node versions and is useful for projects on different versions of Node.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bashWhen you enter a project, you can install Node using NVM.
nvm install node
Restart terminal and confirm that you are using the default version of Node and npm.
node -v && npm -v
For most projects, install the latest LTS version of Node.
nvm install --lts
Set the latest LTS version as the default.
nvm alias default 'lts/*'
If desired, install the current version of Node for testing newer platform features.
nvm install node
You can switch to another version of Node and use it by changing to the directory where you want to use Node and run the following.
nvm install xx.xx
nvm use xx.xx
Node modules are defined in a local package.json file inside your project. npm install will download external libraries and frameworks into each project's own node_modules folder by default. You'll never need to edit files in this folder, only reference them.
Update NVM
nvm install node --reinstall-packages-from=node
Automating npm to switch to the right Node is a nice little time saver. Add some code to your shell to allow this auto switch capability.
Put this into your $HOME/.zshrc after nvm initialization:
# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
local nvmrc_path
nvmrc_path="$(nvm_find_nvmrc)"
if [ -n "$nvmrc_path" ]; then
local nvmrc_node_version
nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")
if [ "$nvmrc_node_version" = "N/A" ]; then
nvm install
elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then
nvm use
fi
elif [ -n "$(PWD=$OLDPWD nvm_find_nvmrc)" ] && [ "$(nvm version)" != "$(nvm version default)" ]; then
echo "Reverting to nvm default version"
nvm use default
fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrcAfter saving the file, run source ~/.zshrc to reload the configuration with the latest changes made.
Even if you don't use Python in your day to day, it's likely you'll encounter something that requires it. Python 2 is years outdated, so install and use Python 3.
If you didn't already install it with brew above, install the latest Python with Homebrew.
brew install python
After installation, open a new terminal tab to make sure it installed correctly.
python3 --version
pip3 --version
On macOS, python may not point to Python 3 unless you add your own shell alias or symlink. Prefer python3 and pip3 unless a project says otherwise.
PHP is still one of the most used programming languages on the web, thanks in part to the amount of sites still using WordPress. We need a way to manage PHP scripts and packages similarly to how we manage JavaScript dependencies using npm.
One of the most popular PHP dependency managers is called Composer. The difference between Composer and npm, for example, Composer is usually installed as a global command, but dependencies are normally installed per project into that project's vendor directory. So you must run and setup Composer on every new project if you want to use it.
To install Composer globally, go to the Download page and run the package installer.
For macOS/Homebrew, include:
brew install composer
The free, open-source virtual machine called VirtualBox can be useful for isolated testing of older browsers or environments. This gives you a basic but very capable VM host for any operating system that supports virtual installations.
brew install --cask virtualbox
Note: VirtualBox supports macOS hosts on both Intel and Apple silicon Macs, but guest architecture matters. Apple silicon Macs generally need ARM-compatible guests.
In theory, I prefer a completely isolated environment that's self-contained like Docker. Practically, these environments can be bloated, inefficient, and using a lot of CPU processing or Memory.
Since the late 2010s, I've grown to appreciate a project from Laravel called Valet. Valet is free, very lightweight, and is relatively easy to set up. I pair it with DBngin, a free and open-source database hosting application.
These two paired together leave a small footprint.
Docker is regularly used for projects today. It features portability, encapsulation for the environment within the OS, and consistency for development environments.
brew install --cask docker-desktop
Docker can be quite powerful but complicated to set up. For this reason, I've enjoyed another project which is a wrapper around Docker called Lando. Originally designed for Drupal, it also supports WordPress, Node.js, and Laravel among others. You can find the latest executable file on GitHub.
brew install lando-cli
If you want the full app installer instead of the Homebrew CLI package, use the latest GitHub release.
Note
On Apple silicon Macs, Docker Desktop can use Apple's virtualization stack or Docker's newer VMM. HyperKit is legacy, so prefer the modern virtualization options unless a project has a specific compatibility issue.
For privacy, I recommend disabling tracking. Inside of your .lando.yml file, add the following:
stats:
- report: false
url: https://metrics.lando.dev
- How to Install Xcode, Homebrew, Git, RVM, Ruby & Rails on Mac OS X
- Web development environment setup in OSX 2015
- macOS Development Environment
- Setting Up A New Mac
- macOS Monterey: Setting up a Mac for Development
- How to set Python3 as a default python version on MacOS?
- Macbook Setup Guide For Web Programmers
- Friendly macOS defaults
- My 2023 New Mac Setup