Skip to content

Instantly share code, notes, and snippets.

@somebox
Forked from foz/osx-setup.sh.md
Last active July 9, 2026 09:31
Show Gist options
  • Select an option

  • Save somebox/6b00f47451956c1af6b4 to your computer and use it in GitHub Desktop.

Select an option

Save somebox/6b00f47451956c1af6b4 to your computer and use it in GitHub Desktop.
Set up an OSX machine from zero to awesome. Uses Homebrew (and cask, fonts, etc). Focused on Ruby/Rails development, includes rvm, xquartz, editor fonts, sublime text, and many tools.
#!/usr/bin/env bash
# Generic macOS workstation setup
#
# A pragmatic, public bootstrap for developer / technical-productivity Macs.
# It installs Homebrew, common CLI utilities, runtimes, terminal/editor/agentic
# coding apps, viewers, media tools, and a curated font set.
#
# Philosophy:
# - Open-source / cross-platform first.
# - Commercial apps only when explicitly useful/common for this workflow.
# - Excludes project/hobby/local-infra apps (games, CAD/3D printing,
# electronics, Home Assistant, OBS, Syncthing, etc.).
#
# Usage:
# bash -c "$(curl -fsSL https://gist.githubusercontent.com/somebox/6b00f47451956c1af6b4/raw/osx-setup.sh)"
#
# Environment flags:
# INSTALL_CASKS=0 # install CLI tools only
# INSTALL_FONTS=0 # skip fonts
# APPLY_DEFAULTS=1 # apply a small set of macOS defaults (off by default)
set -euo pipefail
INSTALL_CASKS="${INSTALL_CASKS:-1}"
INSTALL_FONTS="${INSTALL_FONTS:-1}"
APPLY_DEFAULTS="${APPLY_DEFAULTS:-0}"
bold() { printf '\033[1m%s\033[0m\n' "$*"; }
ok() { printf '\033[1;32m✓ %s\033[0m\n' "$*"; }
warn() { printf '\033[1;33m! %s\033[0m\n' "$*"; }
if [[ "$(uname)" != "Darwin" ]]; then
echo "This script is macOS-only." >&2
exit 1
fi
bold "macOS workstation setup"
# --- Xcode command line tools ---
if xcode-select -p >/dev/null 2>&1; then
ok "Xcode Command Line Tools installed"
else
warn "Installing Xcode Command Line Tools (a GUI prompt may appear)..."
xcode-select --install || true
warn "Re-run this script after Command Line Tools finish installing."
exit 0
fi
# --- Homebrew ---
if command -v brew >/dev/null 2>&1; then
ok "Homebrew installed"
else
warn "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
# Apple Silicon vs Intel brew shellenv
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
BREWFILE="$(mktemp)"
trap 'rm -f "$BREWFILE"' EXIT
cat > "$BREWFILE" <<'BREWFILE'
# --- Cross-platform base utilities ---
brew "bat" # cat with syntax highlighting
brew "chezmoi" # dotfile manager
brew "cloc" # count lines of code
brew "d2" # diagrams from text
brew "direnv" # per-directory env vars
brew "eza" # modern ls replacement
brew "fastfetch" # system info summary
brew "fd" # friendly find
brew "fzf" # fuzzy finder
brew "gh" # GitHub CLI
brew "git" # version control
brew "git-filter-repo" # rewrite git history safely
brew "gnupg" # gpg crypto tools
brew "gping" # ping with graph
brew "grc" # colorize command output
brew "htop" # fancy top with color TUI
brew "jq" # JSON processor
brew "just" # command runner
brew "lazygit" # git TUI
brew "lynx" # terminal web browser
brew "most" # pager with colors
brew "nmap" # network scanner
brew "pinentry" # gpg password prompts
brew "pv" # pipe progress viewer
brew "pwgen" # password generator
brew "ripgrep" # fast grep
brew "rsync" # file sync/copy
brew "sevenzip" # 7z archive tool
brew "sqlite" # sqlite database CLI
brew "starship" # fast shell prompt
brew "tig" # git history TUI
brew "tldr" # short command examples
brew "tree" # directory tree view
brew "trippy" # network route TUI
brew "trufflehog" # secret scanner
brew "uv" # fast Python package tool
brew "vim" # terminal editor
brew "watch" # repeat command viewer
brew "wget" # download files
brew "yq" # YAML processor
brew "zoxide" # smarter cd
# --- Shell / terminal niceties ---
brew "asciinema" # terminal recorder
brew "cmatrix" # terminal screensaver
brew "cowsay" # silly text cows
brew "figlet" # ASCII art text
brew "glances" # system monitor TUI
brew "lolcat" # rainbow text output
brew "multitail" # tail many logs
brew "sl" # steam locomotive joke
brew "tty-clock" # terminal clock
brew "wtfutil" # personal dashboard TUI
# --- Runtimes + build basics ---
brew "cmake" # build system generator
brew "deno" # TypeScript runtime
brew "go" # Go compiler/toolchain
brew "ninja" # fast build tool
brew "node" # JavaScript runtime
brew "pipx" # Python CLI app installer
brew "python@3.13" # Python runtime
brew "rustup" # Rust toolchain installer
# --- DevOps / containers ---
brew "docker-compose" # compose CLI plugin/tool
brew "kubernetes-cli" # kubectl
# --- Networking ---
brew "mtr" # traceroute + ping
brew "speedtest-cli" # internet speed test
# --- Media / conversion / viewer support ---
brew "exiftool" # inspect media metadata
brew "ffmpeg" # audio/video Swiss army knife
brew "flac" # FLAC audio tools
brew "imagemagick" # image conversion tools
brew "lame" # MP3 encoder
brew "mp3info" # MP3 metadata tool
brew "mpg123" # MP3 player
brew "mpg321" # MP3 player fallback
brew "vorbis-tools" # Ogg/Vorbis tools
brew "yt-dlp" # video/audio downloader
# --- macOS app management ---
brew "mas" # Mac App Store CLI
# --- Common macOS apps: productivity, dev, terminal, viewers, agentic coding ---
# Open-source / cross-platform first. Commercial exceptions intentionally kept:
# 1Password, Claude/Claude Code, Cursor, VS Code, Obsidian, Docker Desktop, Spotify.
cask "1password" # password manager
cask "1password-cli" # 1Password terminal CLI
cask "audacity" # audio editor
cask "claude" # Claude desktop app
cask "claude-code" # Claude coding agent
cask "cursor" # AI code editor
cask "db-browser-for-sqlite" # SQLite GUI browser
cask "docker-desktop" # Docker Desktop app
cask "firefox" # open-source browser
cask "ghostty" # minimalist powerful terminal
cask "handbrake-app" # video transcoder
cask "inkscape" # vector graphics editor
cask "obsidian" # local markdown notes
cask "opencode-desktop" # agentic coding desktop
cask "qlmarkdown" # QuickLook markdown preview
cask "signal" # secure messaging
cask "spotify" # music streaming
cask "stats" # menu bar system stats
cask "visual-studio-code" # code editor
cask "vlc" # media player
# --- Fonts ---
# Curated favorites for terminal, IDEs, and UI work. Keep this list selective;
# Ghostty bundles JetBrains Mono Nerd Font glyphs, but these are preferred
# across editors, terminals, and design/dev workstations.
cask "font-departure-mono" # retro monospace terminal font
cask "font-maple-mono" # clean coding monospace
cask "font-monaspace" # GitHub coding font family
cask "font-mononoki-nerd-font" # compact nerd font
cask "font-inconsolata" # classic monospace
cask "font-source-code-pro" # Adobe coding font
cask "font-inter" # readable UI sans
cask "font-inter-tight" # compact UI sans
cask "font-lexend" # accessibility-focused sans
cask "font-league-spartan" # bold geometric display font
cask "font-exo" # geometric tech sans
cask "font-grandstander" # playful display font
cask "font-doto" # dotted display font
cask "font-powerline-symbols" # terminal prompt symbols
BREWFILE
if [[ "$INSTALL_CASKS" != "1" ]]; then
warn "INSTALL_CASKS=0 set; removing casks from temporary Brewfile."
sed -i.bak '/^cask /d' "$BREWFILE"
fi
if [[ "$INSTALL_FONTS" != "1" ]]; then
warn "INSTALL_FONTS=0 set; removing font casks from temporary Brewfile."
sed -i.bak '/^cask "font-/d' "$BREWFILE"
fi
warn "Running brew bundle..."
brew bundle --file="$BREWFILE" --no-upgrade || {
warn "brew bundle reported errors. Some GUI casks may require interactive sudo."
warn "Re-run manually with: brew bundle --file=$BREWFILE"
}
# --- Optional macOS defaults ---
if [[ "$APPLY_DEFAULTS" == "1" ]]; then
warn "Applying small set of macOS defaults..."
defaults write NSGlobalDomain AppleShowAllExtensions -bool true
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write com.apple.screencapture type png
defaults write com.apple.screencapture disable-shadow -bool true
defaults write com.apple.dock autohide -bool true
killall Dock >/dev/null 2>&1 || true
killall Finder >/dev/null 2>&1 || true
fi
cat <<'NEXT'
Done.
Recommended next steps:
1. Open a new shell.
2. Authenticate GitHub CLI: gh auth login
3. Configure your dotfiles (optional): chezmoi init --apply <your-repo>
4. If you installed fzf: $(brew --prefix)/opt/fzf/install
This gist is intentionally generic. Personal/project-specific setup belongs in
your private dotfiles repo.
NEXT
@Dashon-Hawkins

Copy link
Copy Markdown

Please note the following issues/concerns/errors upon install:

  1. Pouring qt-5.11.0.high_sierra.bottle.tar.gz ==> Caveats We agreed to the Qt open source license for you. If this is unacceptable you shoulduninstall.`

This formula is keg-only, which means it was not symlinked into /usr/local, because Qt 5 has CMake issues when linked.

If you need to have this software first in your PATH run: _echo 'export PATH="/usr/local/opt/qt/bin:$PATH"' >> ~/.zshrc_

For compilers to find this software you may need to set: LDFLAGS: _-L/usr/local/opt/qt/lib_ CPPFLAGS: _-I/usr/local/opt/qt/include_ For pkg-config to find this software you may need to set: _PKG_CONFIG_PATH: /usr/local/opt/qt/lib/pkgconfig_

  1. Pouring lua-5.3.4_4.high_sierra.bottle.tar.gz ==> Caveats Please be aware due to the way Luarocks is designed any binaries installed via Luarocks-5.3 AND 5.1 will overwrite each other in _/usr/local/bin_.

This is, for now, unavoidable. If this is troublesome for you, you can build rocks with the --tree= command to a special, non-conflicting location and then add that to your **$PATH**.

  1. Error: Cask 'font-droid-sans' is unavailable: No Cask with this name exists. Did you mean one of these? **font-droid-sans-mono-for-powerline font-droidsansmono-nerd-font-mono font-droidsansmono-nerd-font**

  2. Error: Cask **'google-drive'** is unavailable: No Cask with this name exists. Did you mean “google-drive-file-stream”? y

  3. Error: Cask **'picturelife'** is unavailable: No Cask with this name exists.

@somebox

somebox commented Jul 9, 2026

Copy link
Copy Markdown
Author

Updated with modern dev environment (docker, ghostty, claude, etc.) and removed outdated osx and libs from the old days :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment