# Managing Homebrew with Brewfile
A **Brewfile** is Homebrew's way of managing all your installed packages, casks, and even VS Code extensions in one declarative file. Combined with chezmoi, it makes your entire development environment portable and reproducible.
## What Problem Does This Solve?
**Without Brewfile:**
- Manually install packages one by one on new machines
- Forget which packages you had installed
- Different package versions across machines
- No version control for your tooling setup
**With Brewfile:**
- One command installs everything: `brew bundle install`
- Full history of what tools you use
- Identical environments across all machines
- Easy to share with team members
## Basic Workflow
### Step 1: Generate Your Current State
Generate a Brewfile from your current Homebrew installation:
```bash
# Create Brewfile in your home directory
brew bundle dump --file=~/Brewfile --force
```
This creates `~/Brewfile` with all your currently installed:
- `brew` packages (CLI tools)
- `cask` packages (GUI applications)
- `tap` repositories
- VS Code extensions (if VS Code is installed)
### Step 2: Review and Clean Up
Edit `~/Brewfile` to remove things you don't want to track:
```bash
# View your Brewfile
cat ~/Brewfile
# Edit it
nano ~/Brewfile # or use your preferred editor
```
**Common things to keep:**
- Essential CLI tools: `git`, `tmux`, `tpm`, `curl`, `wget`
- Development tools: `node`, `python`, `docker`, `gh`
- Your terminal: `ghostty`, `alacritty`, etc.
- Editors: `neovim`, `cursor`, `sublime-text`
**Common things to remove:**
- One-off experiments you don't use anymore
- Applications you installed for specific projects
- Duplicates or deprecated packages
### Step 3: Install from Brewfile
On any machine, install everything in your Brewfile:
```bash
brew bundle install --file=~/Brewfile
```
This is idempotent—running it multiple times is safe. It only installs missing packages.
## Integration with chezmoi
### Pattern 1: Manual Sync (Simplest)
**Don't** manage the Brewfile with chezmoi. Instead, regenerate it before syncing:
```bash
# Before committing config changes
brew bundle dump --file=~/Brewfile --force
cd ~/.local/share/chezmoi
git add .
git commit -m "Update configs and regenerate Brewfile"
git push
# On new machine
brew bundle install --file=~/Brewfile
chezmoi init
chezmoi apply
```
**Pros:**
- ✅ Always reflects current state
- ✅ No merge conflicts
- ✅ Simple mental model
**Cons:**
- ⚠️ Brewfile isn't version-controlled
- ⚠️ Must remember to regenerate before syncing
### Pattern 2: chezmoi-Managed Brewfile (Recommended)
Add Brewfile to chezmoi for version control:
```bash
# Add Brewfile to chezmoi
chezmoi add ~/Brewfile
# On new machine, install from Brewfile first
brew bundle install --file=~/Brewfile
# Then apply chezmoi configs
chezmoi init
chezmoi apply
```
**Workflow on your main machine:**
```bash
# Install new tool
brew install newtool
# Regenerate Brewfile
brew bundle dump --file=~/Brewfile --force
# Add to chezmoi and commit
chezmoi add ~/Brewfile
cd ~/.local/share/chezmoi
git add .
git commit -m "Add newtool to Brewfile"
git push
```
**Workflow on other machines:**
```bash
# Pull latest configs
chezmoi update
# Install new packages
brew bundle install --file=~/Brewfile
```
**Pros:**
- ✅ Version-controlled package list
- ✅ Git history of what tools you added/removed
- ✅ Can see diffs between machines
**Cons:**
- ⚠️ Must manually regenerate Brewfile
- ⚠️ Potential for drift if you forget to regenerate
### Pattern 3: Automated Sync (Advanced)
Use chezmoi scripts to automate the sync:
Create `~/.local/share/chezmoi/.chezmoiscripts/run_before_apply.sh`:
```bash
#!/bin/bash
# Auto-update Brewfile before applying configs
echo "Updating Brewfile from current Homebrew state..."
brew bundle dump --file=~/Brewfile --force
```
Add to chezmoi:
```bash
chezmoi add ~/.local/share/chezmoi/.chezmoiscripts/run_before_apply.sh
```
Now every time you run `chezmoi apply`, it regenerates your Brewfile automatically!
**Pros:**
- ✅ Never forget to regenerate
- ✅ Always in sync
**Cons:**
- ⚠️ May capture temporary installs you didn't want to track
- ⚠️ Less explicit about what changed
## Recommended Workflow for Your Setup
Based on your chezmoi + tmux + Ghostty setup, I recommend **Pattern 2** (chezmoi-managed with manual regeneration):
### Initial Setup
```bash
# 1. Install tmux and tpm via Homebrew
brew install tmux tpm
# 2. Regenerate Brewfile
brew bundle dump --file=~/Brewfile --force
# 3. Add to chezmoi
chezmoi add ~/Brewfile
# 4. Commit
cd ~/.local/share/chezmoi
git add .
git commit -m "Add Brewfile with tmux and tpm"
git push
```
### Daily Workflow
**When installing new tools:**
```bash
# Install the tool
brew install sometool
# Immediately regenerate Brewfile
brew bundle dump --file=~/Brewfile --force
# Add to chezmoi
chezmoi add ~/Brewfile
# Commit
cd ~/.local/share/chezmoi
git add Brewfile
git commit -m "Add sometool to Brewfile"
git push
```
**When syncing to another machine:**
```bash
# Pull latest configs
chezmoi update
# Install missing packages
brew bundle install --file=~/Brewfile
```
## Brewfile Structure
Here's what a typical Brewfile looks like:
```ruby
# Homebrew taps (third-party repositories)
tap "homebrew/cask"
tap "homebrew/cask-fonts"
# CLI tools
brew "git" # Version control
brew "tmux" # Terminal multiplexer
brew "tpm" # Tmux plugin manager
brew "chezmoi" # Dotfile manager
brew "ripgrep" # Fast search tool
brew "fzf" # Fuzzy finder
brew "gh" # GitHub CLI
# GUI applications
cask "ghostty" # Terminal emulator
cask "docker" # Containerization
cask "cursor" # Code editor
# VS Code extensions (if VS Code installed)
vscode "github.copilot"
vscode "esbenp.prettier-vscode"
```
## Pro Tips
### Keep It Organized
Add comments to your Brewfile to remember why you installed things:
```ruby
# Terminal tools
brew "tmux" # Session management
brew "tpm" # Tmux plugins
# Audio production
brew "lilypond" # Music notation
cask "reaper" # DAW
```
### Check What Would Be Installed
Before installing, see what's missing:
```bash
brew bundle check --file=~/Brewfile
```
### Cleanup Unused Packages
Remove packages not in your Brewfile:
```bash
brew bundle cleanup --file=~/Brewfile --force
```
⚠️ **Warning:** This removes anything not listed in your Brewfile!
### Install Only Specific Categories
```bash
# Only install brews, skip casks
brew bundle install --file=~/Brewfile --no-cask
# Only install casks
brew bundle install --file=~/Brewfile --no-brew
```
## Troubleshooting
### Brewfile conflicts on chezmoi update
If chezmoi shows conflicts in Brewfile:
```bash
# Accept incoming version (from Git)
chezmoi merge ~/Brewfile
# Or regenerate from current state
brew bundle dump --file=~/Brewfile --force
chezmoi add ~/Brewfile
```
### Package fails to install
```bash
# Update Homebrew first
brew update
# Try installing individually
brew install packagename
# Check for issues
brew doctor
```
### TPM installed via Homebrew doesn't work
When installing TPM via Homebrew, update your `.tmux.conf`:
```bash
# Change from:
run '~/.tmux/plugins/tpm/tpm'
# To:
run '/opt/homebrew/opt/tpm/share/tpm/tpm'
```
Or create a symlink:
```bash
mkdir -p ~/.tmux/plugins
ln -s /opt/homebrew/opt/tpm/share/tpm ~/.tmux/plugins/tpm
```
## Next Steps
- [[1. chezmoi]] - Managing dotfiles with chezmoi
- [[Computer Tech/Unix/tmux/2. tmux Configuration with chezmoi]] - Syncing tmux config
- [[Computer Tech/Unix/tmux/3. TPM - Tmux Plugin Manager]] - Using TPM installed via Homebrew
**Related:**
- [Homebrew Bundle Documentation](https://github.com/Homebrew/homebrew-bundle)
- [[Dev Environment Stack]] - Understanding configuration layers