Skip to content

Latest commit

Β 

History

793 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

dotgibsonCILast CommitContributorsForksStargazersIssuesMIT License


Logo

🍎 dotfiles-MacBook

The macOS OS-native layer β€” Homebrew, AeroSpace tiling, and desktop tooling over the shared Core.
Explore the docs Β»

View Demo Β· Report Bug Β· Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. What's In This Layer
  4. Contributing
  5. License
  6. Contact

About The Project

dotfiles-MacBook is the OS-native layer for macOS (Apple Silicon / Intel) β€” one node in a cross-platform dotfiles system. The shared Core (zsh, tmux, Neovim, git, starship, mise) is authored once in dotfiles-core and vendored under core/ via git subtree, so a clone is self-contained. This repo adds only what is specific to macOS: the Brewfile (brew bundle), Ghostty, the 1Password SSH agent, the native pbcopy clipboard β€” plus a committed tiling-desktop layer: AeroSpace, SketchyBar, and Karabiner, themed to match Core.

macOS is its own lineage β€” built directly on Homebrew, not stamped from the Fedora template. The full docs live on the documentation site.

The system is three layers, each building on the one below:

Layer Lives in Owns
Core dotfiles-core β†’ vendored into every OS repo's core/ zsh, tmux, nvim, git, starship β€” identical everywhere
OS-native dotfiles-{MacBook,Windows,Fedora,Arch,Debian,openSUSE,Alpine,Gentoo} (this repo among them) package manager, clipboard, paths
Role dotfiles-Offense, dotfiles-Defense offensive / defensive tooling

Languages

  • Ruby

The Brewfile is a Ruby DSL (brew bundle); everything else is shell + config over Core.

Tools

  • Homebrew
  • Ghostty
  • AeroSpace
  • SketchyBar
  • Karabiner

(back to top)

Getting Started

Prerequisites

A Mac and the Xcode Command Line Tools (xcode-select --install) β€” that brings Git. bootstrap.sh provisions the rest via Homebrew. Already have a Mac configured a different way? See the migration guide to move onto this layout safely.

Installation

git clone https://github.com/dotgibson/dotfiles-MacBook ~/dotfiles-MacBook
cd ~/dotfiles-MacBook
./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

core/ is a vendored copy and is already present in a clone β€” there is no submodule step.

Flag What it does
--dry-run, -n print every planned action; change nothing
--links-only just (re)create symlinks, no installs
--no-brew symlinks + mise, skip Homebrew and brew bundle
--set-shell make the Homebrew zsh your login shell (chsh)
--macos-defaults also run macos/defaults.sh (system prefs)
--only zsh,nvim link ONLY these module groups
--skip desktop link everything EXCEPT these module groups
--uninstall remove the symlinks and restore backed-up files
--quiet, -q show only CHANGES + the summary
--json machine-readable summary on stdout (for automation)
-h, --help the same list, from the installer itself

Module groups are zsh nvim tmux git prompt tools desktop β€” the first six come from Core, desktop is this layer's own (ghostty, fastfetch, aerospace, sketchybar, karabiner).

Exit codes

Code Meaning
0 clean run
1 could not run (not macOS, missing core/, no Command Line Tools)
2 usage error (unknown flag, bad --only/--skip selector)
3 ran, but one or more steps failed β€” the box is degraded
130 interrupted (Ctrl-C); bootstrap is idempotent, just re-run

Exit 3 is the one to watch in automation. Some steps must not abort the run β€” mise install, macos/defaults.sh, chsh, the tpm clone β€” so a failure there leaves you installed but degraded (no runtimes, no tmux plugins). The closing line says so, the failed steps are listed under the summary, and the exit code distinguishes it from both a clean run and a bootstrap that never started.

The closing checklist

A clean exit still is not a finished machine, so the run ends with a next steps block β€” probed, not hardcoded, so it names only what is actually outstanding and says nothing on a box where everything is done:

==> next steps
  β€’ Karabiner-Elements β€” open it once, approve its driver extension, then grant
    it Input Monitoring (System Settings β†’ Privacy & Security)
  β€’ git identity is still the seeded placeholder β€” edit ~/.config/git/local.gitconfig
  βœ“ AeroSpace is running and responding
  βœ“ tmux plugins installed (6)
  βœ“ pre-commit hook installed

Two of those bootstrap now simply does: it installs the tmux plugins headlessly (rather than leaving you to press prefix + I) and runs pre-commit install, so the local lint and gitleaks gate exists from the first run. The βœ“ lines are the proof they landed.

The GUI permissions are the ones only you can grant. macOS keeps those grants in a system database that is unreadable without Full Disk Access, so bootstrap cannot ask "was this allowed?" β€” each βœ“ there reports a behavioural check (the driver extension is approved, AeroSpace answers its socket) and is worded as exactly that, never as more.

--dry-run skips the block entirely: nothing ran, so every item would read as outstanding.

--json output

One object on stdout, nothing else (the human log goes to stderr):

{
  "dry_run": false,
  "ok": false,
  "linked": 40, "backed_up": 0, "seeded": 2, "skipped": 0,
  "removed": 0, "restored": 0,
  "tools": { "zsh": true, "starship": true, "mise": true, "fzf": true,
             "nvim": true, "tmux": true, "git": true },
  "errors": ["mise install failed β€” …; re-run: mise install"],
  "warnings": ["not yet on PATH: starship β€” open a new shell, …"],
  "next_steps": ["AeroSpace is not responding β€” launch it and grant it Accessibility …"]
}

ok is true iff errors is empty, and mirrors exit 0 vs exit 3 β€” check it alone if you want one field. warnings are notices that do not degrade the run (a tool that just needs a fresh shell), so they never clear ok. tools reports whether each headline binary resolved on PATH at the end of the run.

next_steps is the outstanding half of the closing checklist β€” work that is left for a person, not a defect. It never clears ok either, because nothing failed; without it a fleet-provisioning script reading ok alone would call a box finished while its keyboard remapper is still inert. Empty on a machine with nothing left to do, and empty under --dry-run, which probes nothing.

--uninstall --json emits the same object, and is the only mode that fills removed / restored. It reports "tools": {} β€” an uninstall never probes PATH, so an empty object there means "not measured", not "nothing installed".

If something goes wrong, --uninstall is the way back. It removes only symlinks that point into this repo β€” never a real file, never a foreign link β€” and restores the most recent .pre-dotfiles.* backup it made. Pair it with --dry-run to see exactly what it would do first.

(back to top)

What's In This Layer

Only what changes with the OS. The heavy lifting β€” the shell modules, editor, and prompt β€” comes from vendored Core; this repo owns the macOS specifics:

  • Brewfile β€” Homebrew packages (CLI + casks + fonts), the source of truth
  • os/macos.zsh, os/macos.gitconfig, os/macos.conf β€” the macOS overlays
  • macos/defaults.sh β€” the defaults write system-preferences script (opt-in)
  • aerospace/, sketchybar/, borders/, karabiner/, ghostty/, fastfetch/ β€” the desktop + terminal tooling
  • core/ β€” vendored from dotfiles-core (read-only here; edit upstream)

The things worth knowing β€” Homebrew on /opt/homebrew vs /usr/local, the native pbcopy/pbpaste clipboard, the 1Password SSH agent, and the macOS keychain β€” are written up on the hub, alongside the migration guide for moving an existing Mac onto this layout:

β†’ dotfiles-MacBook on the documentation hub

(back to top)

Contributing

This is an OS-native layer, so the contribution rule is a boundary rule:

  1. Never hand-edit core/. It is a vendored copy of dotfiles-core and is overwritten on the next sync. Fix shared config upstream in dotfiles-core, run make audit there, then make sync fans it out here.
  2. Keep changes genuinely macOS. If it would be identical on every machine, it belongs in Core; if it changes with the operator, it belongs in a role repo.
  3. Green the gate. make lint bundles the repo-owned checks locally and pre-commit install mirrors them at commit time, so "passes locally" means "passes in CI". The full suite:
Gate Covers
shellcheck Β· shfmt Β· bash -n repo-owned bash
zsh -n the zsh entry files (no .sh extension, so the bash globs miss them)
make test-repo bootstrap (incl. provision), the zsh loader, defaults.sh β€” ~150 assertions
file hygiene (CI) .pre-commit-config.yaml's upstream hooks over the whole tree β€” whitespace, EOF newlines, line endings, merge markers, shebang ↔ exec bit, yaml/json/toml
make config-check every repo-owned .json / .jsonc / .toml parses
make markdownlint repo-owned markdown, against .markdownlint.jsonc
make secrets gitleaks over the repo-owned tree
make verify-core the vendored Core subtree hasn't drifted β€” diffed byte-for-byte against the vendored subset of upstream at the recorded commit (CI sets VERIFY_CORE_STRICT=1 so "couldn't reach upstream" fails instead of skipping)
actionlint the workflows themselves
macOS smoke (CI) the entry points on real Darwin β€” clipboard, Brewfile, bootstrap

CI requires a single aggregated ci ok context rather than each job by name, so adding or renaming a leg needs no ruleset change.

Bugs and ideas: open an issue.

(back to top)

License

Distributed under the MIT License. See LICENSE for more information.

(back to top)

Contact

Garrett Allen - @gerrrrt - garrettallen2@gmail.com - LinkedIn

Project Link: dotgibson

(back to top)

About

🍎 The macOS layer β€” Homebrew, AeroSpace tiling, sketchybar & karabiner, over a shared zsh/nvim/tmux core. Keyboard-driven, drift-free.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages