macOS, tiled and keyboard-driven. The macOS layer β Homebrew, AeroSpace tiling, and desktop tooling over the shared core.
brew Β· aerospace Β· zsh Β· nvim
macOS (Apple Silicon / Intel) terminal environment β the OS-native layer of a
ten-repo dotfiles system. The shared Core (zsh modules, tmux, Neovim, git,
mise, starship, clipboard) is vendored under core/ as a git subtree from
dotfiles-core; this repo adds only what is specific to macOS.
Identity of the operator lives in Core. Identity of the machine lives here. Offensive/engagement tooling lives in
dotfiles-Kaliβ not here.
bootstrap.sh Homebrew + brew bundle + symlink wiring (idempotent)
Brewfile macOS packages (CLI + casks + fonts) β you provide
core/ vendored Core subtree (do not edit here; edit dotfiles-core)
os/
macos.zsh interactive shell extras β ~/.config/zsh/os.zsh
macos.gitconfig osxkeychain + excludes + gpg β ~/.config/git/os.gitconfig
macos.gitignore global git excludes β ~/.config/git/ignore
macos.conf tmux en0 + battery bits β ~/.config/tmux/os.conf
zsh/
zshenv β ~/.zshenv (sets ZDOTDIR + XDG + universal env)
zprofile β ~/.config/zsh/.zprofile (Homebrew, juliaup, 1Password agent)
zshrc β ~/.config/zsh/.zshrc (history + completion + the loader)
macos/
defaults.sh `defaults write` system prefs (opt-in) β you provide
ghostty/
config Ghostty terminal config β ~/.config/ghostty/config
ssh/
config SSH client config (keys never tracked) β you provide
git clone <your-remote>/dotfiles-MacBook ~/dotfiles-MacBook
cd ~/dotfiles-MacBook
# core/ is a vendored subtree and is ALREADY present in a clone β no extra step.
# (You only run `git subtree add --prefix=core β¦` when building this repo from scratch.)
./bootstrap.sh --links-only --dry-run # preview the symlink plan (changes nothing)
./bootstrap.sh # Homebrew + brew bundle + symlinks
exec zsh
./bootstrap.sh --macos-defaults # optional: apply system prefs (may need logout)Flags: --dry-run/-n (print every planned action, change nothing),
--links-only (just symlinks), --no-brew (skip Homebrew/bundle),
--set-shell (make the Homebrew zsh your login shell), --macos-defaults
(also run macos/defaults.sh; that script takes its own --dry-run too).
~/.zshenv sets ZDOTDIR=~/.config/zsh, so the rest of zsh lives there.
.zprofile (login) sets Homebrew/PATH; .zshrc (interactive) sources the Core
modules + the macOS layer + your local overrides, in order:
tools β options β history β aliases β git β functions β fzf β bindings
β plugins β op β maint β update β os β local
options.zsh owns compinit + setopts and history.zsh owns history config
(both run before plugins.zsh). toolsβ¦update are Core; os is
os/macos.zsh; local is your untracked ~/.config/zsh/local.zsh. The order
is load-bearing β see the comments in zshrc.
Edit in dotfiles-core, then from there run ./bin/sync-core.sh, or here:
git subtree pull --prefix=core <your-remote>/dotfiles-core main --squash
./bootstrap.sh --links-only- Homebrew lives at
/opt/homebrew(Apple Silicon) or/usr/local(Intel);.zprofilehandles both. - Clipboard is native β Core's
clip/clip-pasteshell out topbcopy/pbpaste. - 1Password SSH agent β
.zprofilepointsSSH_AUTH_SOCKat the 1Password socket; comment it out if you don't use it. - Credentials β git uses the macOS keychain via
osxkeychain.
Static analysis is the test suite here β dotfiles can't really be unit-tested, so
shellcheck + shfmt + bash -n are what guard every change. The same commands run
locally and in CI:
brew bundle # installs the lint toolchain (see Brewfile "Dev: lint & format")
make lint # shellcheck + shfmt -d + bash -n + zsh -n (what CI gates)
make test-repo # behavioral tests for THIS repo (bootstrap, zsh loader, defaults)
make test # vendored Core load-order + function tests (needs zsh)
make test-all # both of the above
make fmt # auto-format repo-owned bash in place
make help # list all targets (bootstrap, doctor, sync-core, β¦)
pre-commit install # optional: run the same gate at commit timemake test-repo (in test/test-repo.sh) is hermetic and runs anywhere: it exercises
bootstrap.sh (arg-parse, did-you-mean, dry-run no-op, output hygiene), the
zsh/zshrc loader (sources in canonical order β not just zsh -n), the macOS
completion wiring, and macos/defaults.sh. Every mutation is sandboxed; no real
provision ever runs.
The repo-owned zsh modules (zsh/zshenv, zsh/zprofile, zsh/zshrc,
os/macos.zsh) have no .sh extension, so they're gated separately by
make zsh-syntax (zsh -n), folded into make lint.
- CI β
.github/workflows/ci.ymlruns theshell lintjob (make {shellcheck,fmt-check,syntax,zsh-syntax,test-repo}), acore regressionjob (make test), amacos smokejob (clipboard round-trip, Brewfile parse, real-Darwin bootstrap/defaults dry-run,make test-repo), andactionlint. Triggers are de-duplicated (pushonmain/tags,pull_requestelsewhere; docs-only changes skip the shell suite) and superseded runs cancel (concurrency). All linters β shellcheck, shfmt, actionlint β are version-pinned and cached.pre-commitmirrors every gate locally. - Reproducible installs β the committed
Brewfileis the source of truth (Homebrew 6.x removedBrewfile.lock.json, so there's no lockfile to pin hashes).make brew-checkverifies every entry is installed on a provisioned machine; themacos smokejob validates theBrewfileparses (brew bundle list --all). - Style β repo-owned bash is 2-space (
shfmt -i 2);.editorconfigis the source of truth andshfmt/editors both read it. - Scope β
core/is a vendored git-subtree fromdotfiles-core; the lint targets and pre-commit hooks exclude it on purpose. Editing it here would diverge the subtree, so its Lua/shell is linted in that repo's CI.make core-advisorysurfaces anycore/findings locally without gating.
These were found during audit but belong to dotfiles-core (fix there, then
git subtree pull / sync-core.sh brings them down β don't hand-edit core/):
core/tmux/scripts/tmux-scratch.shβ shebang is#!/bin/bash; every other script uses#!/usr/bin/env bash.core/tmux/scripts/tmux-sessionizer.shβ superseded bytmux-sesh.sh(percore.manifest); it's dead and should be removed upstream.core/maint/dotfiles-maint.shβ ShellCheck SC2015 (A && B || C) and SC2016.core/tmux/scripts/tmux-menu.shβ ShellCheck SC2016.