<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: fullstackjam</title>
    <description>The latest articles on Forem by fullstackjam (@fullstackjam).</description>
    <link>https://forem.com/fullstackjam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F762592%2Fcfd284ef-a5c5-48cc-86ec-64f43c473d38.jpg</url>
      <title>Forem: fullstackjam</title>
      <link>https://forem.com/fullstackjam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fullstackjam"/>
    <language>en</language>
    <item>
      <title>Every way to automate a Mac setup, ranked by mass of YAML you'll write</title>
      <dc:creator>fullstackjam</dc:creator>
      <pubDate>Sun, 15 Feb 2026 06:55:08 +0000</pubDate>
      <link>https://forem.com/fullstackjam/every-way-to-automate-a-mac-setup-ranked-by-mass-of-yaml-youll-write-984</link>
      <guid>https://forem.com/fullstackjam/every-way-to-automate-a-mac-setup-ranked-by-mass-of-yaml-youll-write-984</guid>
      <description>&lt;p&gt;I've set up more Macs than I care to admit. Personal machines, work laptops, loaners, that one time I rage-wiped my drive at 2am because I broke my Python environment beyond repair.&lt;/p&gt;

&lt;p&gt;Every time it's the same thing. Open Terminal. Desert. No git, no node, no docker. Finder hiding file extensions. The Dock taking nine years to auto-hide. All your aliases, gone.&lt;/p&gt;

&lt;p&gt;Two hours of &lt;code&gt;brew install&lt;/code&gt; later you've got maybe half your tools back. A week later you realize you forgot &lt;code&gt;jq&lt;/code&gt;. Two weeks later you realize every commit at your new job says "unknown" because you never set your git email.&lt;/p&gt;

&lt;p&gt;I've tried every level of automation to fix this. Here's what I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your setup is bigger than you think
&lt;/h2&gt;

&lt;p&gt;I counted once. 83 things across 8 categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Package manager&lt;/strong&gt; — Homebrew, always step zero&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI tools&lt;/strong&gt; (30+) — ripgrep, fd, fzf, bat, eza, lazygit, gh, jq, delta, zoxide...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GUI apps&lt;/strong&gt; (15+) — VS Code, Warp, Raycast, Rectangle, OrbStack, Chrome, Arc...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Languages &amp;amp; runtimes&lt;/strong&gt; — Node, Go, Python, Rust, plus pnpm/uv/cargo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shell&lt;/strong&gt; — Oh-My-Zsh, Starship, plugins, your &lt;code&gt;.zshrc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dotfiles&lt;/strong&gt; — &lt;code&gt;.gitconfig&lt;/code&gt;, &lt;code&gt;.vimrc&lt;/code&gt;, &lt;code&gt;.ssh/config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git identity&lt;/strong&gt; — the two lines everyone forgets every time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;macOS preferences&lt;/strong&gt; — &lt;code&gt;defaults write&lt;/code&gt; commands for Dock speed, Finder, key repeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you think your setup is "just Homebrew and VS Code," you're undercounting by about 70%.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Brewfile
&lt;/h2&gt;

&lt;p&gt;Simplest option. Homebrew has it built in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew bundle dump &lt;span class="nt"&gt;--file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/Brewfile   &lt;span class="c"&gt;# export&lt;/span&gt;
brew bundle &lt;span class="nt"&gt;--file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/Brewfile        &lt;span class="c"&gt;# restore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I ran with one for about a year. Zero dependencies, easy to read, throw it in a repo and you're done.&lt;/p&gt;

&lt;p&gt;Problem: it only handles packages. No shell config, no macOS preferences, no git identity. You're automating about 30% of the job and doing the rest by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shell script
&lt;/h2&gt;

&lt;p&gt;Next step up. Write a bash script that does everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
brew &lt;span class="nb"&gt;install &lt;/span&gt;ripgrep fd bat fzf node go lazygit gh
brew &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--cask&lt;/span&gt; visual-studio-code warp raycast
defaults write NSGlobalDomain AppleShowAllExtensions &lt;span class="nt"&gt;-bool&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;defaults write com.apple.dock autohide-delay &lt;span class="nt"&gt;-float&lt;/span&gt; 0
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Your Name"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"you@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Covers more ground. Also breaks more often. Mine died halfway through once because of a network hiccup and I had no idea what had actually installed. Run it twice and Oh-My-Zsh complains, git config overwrites everything, Homebrew spams "already installed" warnings.&lt;/p&gt;

&lt;p&gt;Someone on Reddit responded to mine with their 200-line version. Which kinda proved the point — if you need 200 lines of bash to set up a laptop, bash might not be the right tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  chezmoi
&lt;/h2&gt;

&lt;p&gt;Dotfile manager. Templates your configs so one repo works across machines, encrypts secrets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;chezmoi init &lt;span class="nt"&gt;--apply&lt;/span&gt; your-github-username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I gave it two months. Spent more time learning its directory conventions than actually setting up my dotfiles. Worth it if you have five machines running different OSes. Overkill if you just want &lt;code&gt;.zshrc&lt;/code&gt; on two Macs.&lt;/p&gt;

&lt;p&gt;Doesn't install software. You still need a Brewfile on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  nix-darwin
&lt;/h2&gt;

&lt;p&gt;The nuclear option. Full declarative config for your entire Mac.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;systemPackages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nv"&gt;ripgrep&lt;/span&gt; &lt;span class="nv"&gt;fd&lt;/span&gt; &lt;span class="nv"&gt;bat&lt;/span&gt; &lt;span class="nv"&gt;fzf&lt;/span&gt; &lt;span class="nv"&gt;nodejs&lt;/span&gt; &lt;span class="nv"&gt;go&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nv"&gt;homebrew&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;casks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"visual-studio-code"&lt;/span&gt; &lt;span class="s2"&gt;"warp"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;defaults&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;dock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;autohide&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at that config. It's elegant. Same file → same system, every time, with rollback. The problem is getting there. Nix has its own language, its own package manager, its own way of thinking. I spent most of a weekend on the Nix discourse forums trying to figure out why my shell wasn't loading.&lt;/p&gt;

&lt;p&gt;If you're already in the Nix ecosystem, this is the obvious choice. If not, budget 1-2 weeks before it starts paying off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ansible
&lt;/h2&gt;

&lt;p&gt;Jeff Geerling's &lt;a href="https://github.com/geerlingguy/mac-dev-playbook" rel="noopener noreferrer"&gt;mac-dev-playbook&lt;/a&gt; is the popular option here. Idempotent, which is nice. But writing enterprise YAML to install VS Code on your personal laptop feels absurd. And when a playbook fails, the error messages read like server logs.&lt;/p&gt;

&lt;p&gt;Good for 500 corporate laptops. Overkill for one developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  How they actually compare
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Brewfile&lt;/th&gt;
&lt;th&gt;Shell script&lt;/th&gt;
&lt;th&gt;chezmoi&lt;/th&gt;
&lt;th&gt;nix-darwin&lt;/th&gt;
&lt;th&gt;Ansible&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Packages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GUI apps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shell config&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;macOS prefs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dotfiles&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollback&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idempotent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5 min&lt;/td&gt;
&lt;td&gt;10 min&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;td&gt;1-2 weeks&lt;/td&gt;
&lt;td&gt;2-3 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Coverage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~30%&lt;/td&gt;
&lt;td&gt;~70%&lt;/td&gt;
&lt;td&gt;~20%&lt;/td&gt;
&lt;td&gt;~90%&lt;/td&gt;
&lt;td&gt;~70%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No single tool covers everything. Most people end up combining two or three. &lt;br&gt;
I got tired of that and built &lt;a href="https://openboot.dev" rel="noopener noreferrer"&gt;OpenBoot&lt;/a&gt; — handles packages, apps, shell, macOS prefs, and git config in one TUI. Biased obviously, but the comparison above shows where it fits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 2026 CLI toolkit
&lt;/h2&gt;

&lt;p&gt;The tools that keep showing up in every setup I see:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ripgrep&lt;/strong&gt; and &lt;strong&gt;fd&lt;/strong&gt; — fast grep and find. I can't remember &lt;code&gt;find&lt;/code&gt;'s syntax anyway. &lt;strong&gt;fzf&lt;/strong&gt; makes Ctrl+R actually usable. &lt;strong&gt;zoxide&lt;/strong&gt; — type &lt;code&gt;z blog&lt;/code&gt; and you're there from anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;bat&lt;/strong&gt; — cat with syntax highlighting, you won't go back. &lt;strong&gt;eza&lt;/strong&gt; — ls with git status. &lt;strong&gt;jq&lt;/strong&gt; — if you touch JSON. &lt;strong&gt;delta&lt;/strong&gt; — readable git diffs in the terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;lazygit&lt;/strong&gt; — I was stubborn about the command line until I had to interactive-rebase 30 commits. Haven't gone back.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 2026 GUI picks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;VS Code&lt;/strong&gt; still wins on extensions. &lt;strong&gt;Cursor&lt;/strong&gt; is the first editor that's actually pulling me away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warp&lt;/strong&gt; for terminal. &lt;strong&gt;Raycast&lt;/strong&gt; over Alfred — clipboard history alone. &lt;strong&gt;Rectangle&lt;/strong&gt; for window management, free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OrbStack&lt;/strong&gt; replaced Docker Desktop and my fans went quiet. If you're still on Docker Desktop, just try it.&lt;/p&gt;

&lt;p&gt;Newer stuff that stuck: &lt;strong&gt;Ghostty&lt;/strong&gt; (stupid fast native terminal), &lt;strong&gt;Zed&lt;/strong&gt; (for massive files), &lt;strong&gt;Ollama&lt;/strong&gt; (local LLMs for plane rides), &lt;strong&gt;uv&lt;/strong&gt; (Python finally has a sane package manager), &lt;strong&gt;Bun&lt;/strong&gt; (replaced Node for throwaway scripts).&lt;/p&gt;




&lt;p&gt;What's your setup? I'm curious how many people actually use nix-darwin day-to-day vs. just a Brewfile. And is anyone still using mackup or has everyone moved on?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Full version with more code examples and detailed walkthroughs: &lt;a href="https://blog.fullstackjam.com/2026/mac-setup-automation-guide-2026/" rel="noopener noreferrer"&gt;blog.fullstackjam.com/2026/mac-setup-automation-guide-2026&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mac</category>
      <category>automation</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
