Skip to content

JamesDHW/dotstrap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dotstrap

Bootstrap your Mac config with one command.

A tiny installer that consumes any dotfiles repo that follows the dotstrap spec.

Motivation

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; simply rm -rf to 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

Quick start

/bin/zsh -c "$(curl -fsSL https://raw.githubusercontent.com/JamesDHW/dotstrap/main/bootstrap.sh)" -- \
  --repo https://github.com/<owner>/<your-config-repo>.git

What dotstrap does

  • 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 .zshrc that sources all ~/.config/*/.zshrc fragments, and leaves a stub ~/.zshrc in $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/Brewfile to include file references to each module Brewfile.
  • Run brew install to 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.d script once (idempotent)

Warning: do not commit secrets

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!

The dotstrap spec

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 Brewfile at the root (generated by homebrew-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

How it works

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:

dotstrap only installs config; you own the actual files. Only run on repos you trust!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages