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

 
 
 

Contributors

Languages