Bootstrap your Mac config with one command.
A tiny installer that consumes any dotfiles repo that follows the
dotstrapspec.
Setting up a new Mac often means moving dotfiles, Brewfiles, shell config, and system tweaks by hand. On a new or client machine, you need your tools fast to hit the ground running. Config tends to scatter for different; you should always know what lives where and why it was installed.
dotstrap aims to be:
- fast: bootstrap your tools and config, as you like them, with one command which is available on a fresh Mac
- modular: all config lives in
~/.config/<module>; easy to find and track; simplyrm -rfto remove - low-maintenance: store config updates in a git repo and simply push to keep up-to-date for later
- composable: pull tools and config from multiple git repos to compose mutliple dotstrap profiles
/bin/zsh -c "$(curl -fsSL https://raw.githubusercontent.com/JamesDHW/dotstrap/main/bootstrap.sh)" -- \
--repo https://github.com/<owner>/<your-config-repo>.git- Install Homebrew if not already installed.
- Ensure a
~/.config/directory exists. - Generate a base
~/.zshenv(if absent) that redirects zsh config to~/.config/zsh. - Generate base config modules for:
zsh: provides an entry-point.zshrcthat sources all~/.config/*/.zshrcfragments, and leaves a stub~/.zshrcin $HOME for compatibility.homebrew: manages package installs via homebrew-file, aggregating all module Brewfiles.
- Clone the target repo into
~/.config/, creating one folder per module.- Existing modules are never overwritten; in case of clashes, the user’s modules win.
- New modules from the repo are added automatically.
- Update the root
~/.config/Brewfileto includefilereferences to each module Brewfile. - Run
brew installto install any new packages required by those modules.
On repeat runs:
- Existing modules are left untouched.
- Any new modules from the repo are added.
- The root Brewfile is refreshed to include missing module references, ensuring new packages are installed without duplicating existing ones.
Coming soon:
- Run each
postinstall.dscript once (idempotent)
It's essential for your security that you don't publish any:
- API keys or secrets
- Config that may reveal that you are using vulnerable software
Example:
It's easier to commit secrets by mistake than you expect.
Let's take your zsh history as an example. In this configuration, your $ZDOTDIR is inside ~/.config/, which is part of you dotstrap profile, and may be committed and pushed to GitHub. The way that zsh stores command history is with a file stored inside $ZDOTDIR/.zsh_history - if you run a command in your terminal (curl 'https://github.com/...' -H 'x-authorization: Bearer <SUPER-SECRET-TOKEN>') and do not have .zsh_history in your .gitignore, then zsh will add this <SUPER-SECRET-TOKEN> to your history file, which you then commit and publish to a public repo.
For this reason, I would recommend that you store your dotstrap profile in a private git repo!
dotstrap assumes you are using zsh, but could easily be tweaked for those using fish (etc.).
A compliant config repo:
- Can be cloned with Git (public is simplest, but don't publish any secrets!)
- Organizes config as modules under
~/.config/<module>/ - Contain a
Brewfileat the root (generated byhomebrew-file)
Each module may include:
.zshrc— a shell fragment to be sourced- (coming soon)
postinstall.d/— optional scripts (*.sh, *.applescript) run once after install
Example:
~/.config/
git/
.zshrc
nvim/
.zshrc
init.lua
Brewfile
Example repo: https://github.com/JamesDHW/dotstrap-profile-example
dotstrap creates a ~/.zshenv which contains the following:
# XDG: https://specifications.freedesktop.org/basedir-spec/latest/
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
# This is where zsh will put its config files
export ZDOTDIR="$XDG_CONFIG_HOME/zsh"This means that when you open a new zsh, the ~/.config/zsh/.zshrc will run:
# ~/.config/zsh/.zshrc
# Load per-tool snippets: any ~/.config/*/.zshrc except this one
# Note: snippets are loaded in alphabetical order, configuration in ~/.config/bat/.zshrc will override ~/.config/aws/.zshrc
for f in "$XDG_CONFIG_HOME"/*/.zshrc(N); do
[[ "$f" == "$ZDOTDIR/.zshrc" ]] && continue
source "$f"
done
# Load .zshrc in home directory in case there's extra config there
source "$HOME/.zshrc"
alias zshrc="vim ~/.config/zsh/.zshrc"This loads the .zshrc fragments in each config module, such as the core module, homebrew, which sets up brew and brew-file, which creates and stores a lockfile of all your system dependencies:
# ~/.config/homebrew/.zshrc
export PATH="/opt/homebrew/bin:$PATH"
export HOMEBREW_BREWFILE="$HOME/.config/Brewfile"
[ -f "$(brew --prefix)/etc/brew-wrap" ] && source "$(brew --prefix)/etc/brew-wrap"Warning:
dotstraponly installs config; you own the actual files. Only run on repos you trust!