Skip to main content
  1. Posts/

Dotfiles demystified: a practical guide with Homebrew and GNU Stow

Table of Contents

Spend enough time around developers and you’ll run into people who treat their dotfiles with the reverence other people reserve for family heirlooms. The “perfect dotfiles setup” pinned on a GitHub profile. The aggressive bragging in PR threads. The mystique. But once you strip the culture off, what are dotfiles actually, and why does keeping them organized pay off?

What are dotfiles?
#

Dotfiles are plain text configuration files that customize your shell, editor, version control, and other tools. The name comes from the leading dot in their filenames, which makes them hidden by default on Unix-based systems. The common ones:

  • .zshrc: shell configuration.
  • .gitconfig: Git settings.
  • .vimrc or .config/nvim/init.vim: text editor preferences.

They’re the place where you encode every small preference that makes your environment feel like yours.


Why keep dotfiles?
#

1. Consistency across machines
#

Have you ever switched to a new computer and felt like your productivity dropped because nothing worked the way you liked? Dotfiles solve that. With your configurations stored in a remote repo, you can set up a new machine in minutes and pick up exactly where you left off.

2. Version control for your setup
#

Your development environment evolves. By keeping your dotfiles in a Git repo, you can:

  • Track changes over time.
  • Revert to previous configurations if something breaks.
  • Experiment with new setups without fear of losing your existing one.

3. Sharing and inspiration
#

Browsing other developers’ dotfiles is one of the better ways to find useful tools. Aliases, shell functions, plugin lists, prompt configs: most of what’s worth stealing surfaces in someone else’s repo first.


Setting up your dotfiles
#

Instead of managing your dotfiles directly in the home directory, a more modular and organized approach is to use a .dotfiles directory as both the repository and working directory. This keeps your home directory clean and lets you use symlinks to place configuration files where needed.

Step 1: Initialize the repository
#

Run the following to set up a bare Git repository in ~/.dotfiles:

cd $HOME
mkdir .dotfiles
cd .dotfiles
git init

Step 2: Add and commit files with GNU Stow
#

Instead of manually creating symbolic links for each file, you can use stow, a powerful tool that automates the process based on directory structure. We also automate the installation of Homebrew itself in the install script below to ensure it is available on any machine. For more details, see my guide for installing Homebrew. Install stow via Homebrew:

brew install stow

Organize Your Dotfiles
#

Copy or move the dotfiles you want to track into your .dotfiles directory so that the dotfiles match the structure they had in the home directory. For example, files should be stored in a way that mirrors their expected paths (GNU Stow will use this structure to create symlinks in the home directory):

~/.dotfiles/
├── .zshrc
├── .gitconfig

For example, here I’m copying my .gitconfig and .zshrc into the ~/.dotfiles directory and renaming the originals to retain them as a backup.

cp ~/.gitconfig ~/.dotfiles/
cp ~/.zshrc ~/.dotfiles/
mv ~/.gitconfig ~/.gitconfig.bak
mv ~/.zshrc ~/.zshrc.bak

Use GNU Stow to Symlink Files#

To create symlinks, navigate to your .dotfiles directory and use stow .:

cd ~/.dotfiles
stow .

By default, stow ignores directories like .git to prevent them from being symlinked. However, if a .stow-local-ignore file is present, it overrides the default ignores and only excludes patterns you define. For example, to ensure .git and .gitignore are skipped, your .stow-local-ignore file might look like this:

.git
.gitignore
README.md

For detailed customization options, refer to the GNU Stow documentation.

If you ever need to remove all of the symlinks created by GNU Stow you can run the below:

cd ~/.dotfiles
stow -D .

Once your files are organized and symlinked, you can track them in Git:

cd ~/.dotfiles
git add .
git commit -m "Organized dotfiles with stow"
git push origin main

Automating setup with install scripts
#

To simplify the setup process across machines, create an installation script. This script can:

  1. Use Homebrew to reinstall dependencies.
  2. Symlink your configuration files to their correct locations using GNU Stow.

Steps to create the install script
#

  1. Create and ignore an install directory

    The install scripts don’t need symlinks created… This will prevent GNU Stow from creating symlinks for these.

    cd ~/.dotfiles
    mkdir install
    touch .stow-local-ignore
    echo "install" > .stow-local-ignore
  2. Export currently installed apps in Homebrew

    This command creates a Brewfile that lists all your Homebrew-installed packages and casks, ensuring your setup can be replicated on new machines.

    brew bundle dump --describe --file ~/.dotfiles/install/Brewfile
  3. Create the Script File:

    Use touch to create the script file:

    cd ~/.dotfiles
    mkdir install
    cd install
    touch install.sh
  4. Open the File in an Editor:

    Open the file in your preferred text editor. If you’re using a graphical editor, enable viewing of hidden files (e.g., Cmd+Shift+. on macOS). Alternatively, use a terminal editor like nano or vim:

    nano install.sh
  5. Add the Following Script:

    #!/usr/bin/env bash
    
    # Install Homebrew and packages
    if ! brew --version &>/dev/null; then
        /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    fi
    brew bundle --file ~/.dotfiles/Brewfile --verbose
    
    # Symlink configuration files using GNU Stow
    stow .
  6. Make the Script Executable:

    chmod +x install.sh
  7. Run the Script:

    Execute the script to set up your environment:

    ./install.sh

Storing macOS settings
#

If you use macOS, many system settings can be configured via the defaults command. For example, you can adjust Dock behavior, Finder preferences, and more. To export settings:

  1. Manually configure settings via defaults write commands.
  2. Save them to a script (e.g., macos-settings.sh) within your .dotfiles/install/ directory.

Example macOS settings script
#

Create a macos-settings.sh file in your .dotfiles/install/ directory:

#!/usr/bin/env bash

# Apply macOS settings
if [[ "$OSTYPE" == "darwin"* ]]; then
   # Example macOS settings
   # Move Dock to the left
   defaults write com.apple.dock orientation left
   # Set Dock tile size
   defaults write com.apple.dock tilesize -int 30
   # Restart Dock to apply changes
   killall Dock
fi

Make the script executable:

chmod +x ~/.dotfiles/macos-settings.sh

While this post focuses more on dotfiles, check out Mathias Bynens’ macOS defaults script for inspiration.


Best practices for dotfiles
#

  • Keep It Modular: Break configurations into smaller files (e.g., .zsh_aliases, .zsh_exports) for readability and reuse.
  • Document Your Setup: Add comments in your dotfiles to explain obscure configurations.
  • Back Up Regularly: Even with Git, it’s worth having a backup plan in case of catastrophic failure. One common approach is to host your dotfiles in a remote repository on GitHub, GitLab, or a similar platform. This not only ensures your configurations are safe but also allows you to easily clone them to new machines. Avoid storing sensitive information, such as secrets or credentials, in your dotfiles repository. Instead, ensure that these files are excluded by adding them to a .gitignore file. This prevents them from being staged or committed accidentally.
  • Start Simple: Avoid overcomplicating. Stick to essentials and add as needed.

Additional resources
#

Dotfiles repay the time you put into them. With a structured directory, an install script, and version control, setting up a new machine becomes a single-command operation instead of an afternoon. Start small — track your shell config and Git config first, add more as you find friction worth removing.

Chandler Thompson
Author
Chandler Thompson
Perpetual Hobbyist.

Related