UNAME := $(shell uname -s) # Use --no-folding so every directory under a package becomes a real # directory in $HOME containing individual file symlinks, rather than # a single directory-level symlink. This keeps runtime writes (fish's # fish_variables, fisher plugins' conf.d/, etc.) inside $HOME instead # of silently propagating into the repo source via a folded symlink. # Edits to tracked files still go through their per-file symlink to # the repo source as before. STOW := stow --no-folding .DEFAULT_GOAL := install # Every target in this file is phony — all real work lives in script/ # and this Makefile is just a dispatcher. If you add a new target, # list it in .PHONY below. .PHONY: install install-darwin install-codespaces sync-codespace-plugins stow-common .PHONY: setup-git-config regen-git-config macos-preferences .PHONY: brew fisher mise doctor test clean # Dispatcher is explicitly serial. Parallel `make -j` on overlapping stow # packages would race during directory folding, and none of this benefits # from parallelism anyway. .NOTPARALLEL: # Platform-conditional prerequisites, composed at parse time. Under # .NOTPARALLEL, prerequisites run left-to-right in the order listed, # so `install`'s chain is: setup-git-config → stow-common → extras. EXTRA_INSTALL := ifeq ($(UNAME),Darwin) EXTRA_INSTALL += install-darwin endif ifneq ($(CODESPACES),) EXTRA_INSTALL += install-codespaces endif # `mise` runs last: under .NOTPARALLEL prerequisites run left-to-right, so # the stowed global config is available before runtimes are installed. # The script installs the official mise release on macOS and guard-skips on # other hosts where mise is unavailable. install: setup-git-config stow-common $(EXTRA_INSTALL) mise stow-common: ./script/stow-package common # Assumes setup-git-config + stow-common have already run (i.e. was # invoked via `make install`). Safe to re-run as a standalone repair # workflow — the script is idempotent. install-darwin: ./script/install-darwin # Apply macOS defaults and reload preference-related LaunchAgents. This is # also run by install-darwin after the darwin package has been stowed. macos-preferences: ./script/apply-macos-preferences # Assumes setup-git-config has already run. Stows the codespaces # package, provisions the CLI tools, then syncs editor + terminal plugins. install-codespaces: ./script/stow-package codespaces ./script/install-codespace-tools ./script/sync-codespace-plugins # Reconcile Neovim + tmux plugin state. Split from tool provisioning so it # can be re-run on its own whenever the declared plugin set changes. Safe # to re-run — idempotent and guard-skips when a tool or config is missing. sync-codespace-plugins: ./script/sync-codespace-plugins # Render templates/git-config.tmpl into ~/.config/git/config and inject the # per-host identity with `git config --file`. Prompts on first run; silent # thereafter. See the script for details. setup-git-config: ./script/setup-git-config regen-git-config: setup-git-config brew: brew bundle --global # Bootstrap fisher if missing, then update plugins. Matches the old # run_onchange_after_30-fisher-update.sh.tmpl. No-op if fish is absent. fisher: @if command -v fish >/dev/null 2>&1; then \ fish -c 'curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher && fisher update'; \ else \ echo "fish not on PATH; skipping"; \ fi # Install mise on macOS, then trust the config and install all runtimes. # Other platforms use an existing mise binary or guard-skip when absent. mise: ./script/install-mise doctor: ./script/doctor # Static check every script, then run the functional test suite. # shellcheck is cheap — run it first so a lint failure short-circuits # before we spin up mktemp sandboxes. Scripts are discovered via # git ls-files so adding one to script/ can't silently go unlinted. test: git ls-files -z 'script/*' | xargs -0 -r shellcheck -x ./script/test # Uninstall all stowed packages from $HOME. Does NOT delete the repo, # the generated ~/.config/git/config, or the per-host identity file. # Leading `-` tolerates `stow -D` on a package that wasn't previously # stowed (modern stow is a no-op in that case, but older versions and # some edge cases error). clean: -$(STOW) -D -t $$HOME common ifeq ($(UNAME),Darwin) -$(STOW) -D -t $$HOME darwin endif ifneq ($(CODESPACES),) -$(STOW) -D -t $$HOME codespaces endif