Most dev environments accumulate. A plugin here, a config there, a version manager someone on Stack Overflow recommended in 2019. The result is a shell that takes 800ms to start and a workflow full of friction you've stopped noticing.
This guide sets up a fast, opinionated baseline. Everything here is a decision, not a suggestion.
Prerequisites
macOS or Linux
Homebrew on macOS (
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)")A terminal and basic comfort editing text files
The shell
zsh is the default on macOS since Catalina. On Linux:
sudo apt install zsh # Debian/Ubuntu
sudo dnf install zsh # Fedora/RHEL
chsh -s $(which zsh) # Set as default, then restart terminal
Verify it took:
echo $SHELL
# /bin/zsh or /usr/bin/zsh
Plugins
Two plugins worth installing — nothing else. Clone them:
mkdir -p ~/.zsh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting ~/.zsh/zsh-syntax-highlighting
Open ~/.zshrc (create it if it doesn't exist):
nano ~/.zshrc
Add these two lines:
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
Save and reload:
source ~/.zshrc
What changes: commands from your history appear as greyed-out suggestions while you type — hit → to accept. Invalid commands turn red before you run them. Both save more time than they look like they will.
Skip oh-my-zsh. It's slow, loads things you don't need, and makes your config someone else's problem.
The prompt
Starship replaces the default shell prompt with one that shows git branch, dirty state, active language version, and last command exit status — in under 5ms.
Install
# macOS
brew install starship
# Linux or macOS alternative
curl -sS https://starship.rs/install.sh | sh
Configure
Open ~/.zshrc:
nano ~/.zshrc
Add this line at the very end of the file:
eval "$(starship init zsh)"
Reload:
source ~/.zshrc
Your prompt updates immediately. The default config works well out of the box. When you're ready to customize — colours, which segments show, order — config lives in ~/.config/starship.toml. Full reference here.
Language versions
Don't install Node, Python, or Ruby globally. Use mise — one tool that replaces nvm, pyenv, rbenv, and asdf.
Install
brew install mise
Configure
Open ~/.zshrc:
nano ~/.zshrc
Add:
eval "$(mise activate zsh)"
Reload:
source ~/.zshrc
Per-project versions
In each project root, create .mise.toml:
[tools]
node = "20"
python = "3.12"
Then run once:
mise install
The right version activates automatically when you cd into the project. No more nvm use at the start of every session. Full docs.
The editor
VS Code if you want something that works immediately. Neovim if you're willing to invest a week for a tool you'll use for a decade.
Pick one. Using both is just avoiding the decision.
For VS Code, three extensions that earn their place:
Error Lens — shows errors on the line they occur, not buried in a separate panel
GitLens — inline blame, history, and diff without leaving the file
Prettier — formats on save, eliminates style arguments entirely
To enable format on save, open VS Code settings (Cmd+, on macOS), search formatOnSave, and check the box. Or add directly to settings.json:
{
"editor.formatOnSave": true
}
Git
The config most engineers never set up:
nano ~/.gitconfig
[alias]
co = checkout
st = status -sb
lg = log --oneline --graph --decorate --all
undo = reset HEAD~1 --mixed
[push]
default = current
[pull]
rebase = true
[core]
autocrlf = input
What each setting does:
git lg— branch graph in the terminal, no GUI neededpush.default = current— no more--set-upstreamon every new branchpull.rebase = true— keeps history linear without thinking about itundo— rolls back the last commit without losing your changes
Reload is automatic — .gitconfig is read fresh on each git command.
Aliases
Add to ~/.zshrc:
# Navigation
alias ..='cd ..'
alias ...='cd ../..'
# Safer defaults (prompts before overwriting)
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'
# Reload config without opening a new shell
alias reload='source ~/.zshrc'
# Common tools
alias dc='docker compose'
alias k='kubectl'
Run source ~/.zshrc after saving. Rule: alias things you type three times a day. Not things you type once a month.
Dotfiles
The setup above spans several files across your home directory. Put them all in a git repo and symlink them back.
mkdir ~/dotfiles
# Move configs in, then symlink:
ln -s ~/dotfiles/.zshrc ~/.zshrc
ln -s ~/dotfiles/.gitconfig ~/.gitconfig
New machine setup becomes: clone the repo, run the symlink script. chezmoi handles this with templating if your setup varies across machines. A plain shell script works just as well if it doesn't.
A dev environment that fights you is a tax on every working hour. Set this up once.
