Files
mac/docs/plans/2026-09-15-mac-setup-design.md
T
Mortdecai fa76fd4a73 init: scaffold mac project + inventory + setup design
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 18:54:04 -04:00

7.5 KiB

Mac setup design — 2026-09-15

Design for turning the stock MacBook Pro (16" 2021 M1 Pro, macOS 26.2 Tahoe) into a quiet, Linux-feeling, Ableton-first machine, managed over SSH from steel141. Inventory baseline: ../reference/inventory-2026-09-15.md.

Goals (priority order)

  1. Ableton Live 12 runs clean: no sleep/App Nap/notifications mid-session, project files never touched by cloud sync, backed up to tank.
  2. Feels like Linux to a bash user: GNU userland unprefixed, ip a works, kitty, bash 5, fast key repeat, no press-and-hold accents, window snapping.
  3. Stock macOS noise off: Dock stripped, Spotlight web/Siri suggestions off, Photos analysis / Game Center / Handoff / iPhone Mirroring / Screen Time off.
  4. Homelab reachable: tank over SMB, ssh aliases, Gitea, Tailscale.

Non-goals

  • Disabling SIP, Gatekeeper, or FileVault. All stay on.
  • Removing anything under /System/Applications (sealed volume). Hide from Dock only.
  • Swapping Cmd<->Ctrl globally. Live's shortcuts are Cmd-native on Mac.
  • yabai (needs partial SIP disable). Tiling is AeroSpace if wanted later; Rectangle now.
  • Running samples/projects off the SMB share. Local disk only; SMB is a source to copy from.
  • Time Machine (over SMB it's fragile and backs up the whole disk; rsync of the folders that matter is simpler and Linux-familiar).

Decisions taken in this design (defaults — override in DECISIONS.md)

Fork Choice Why
Login shell Homebrew bash 5, set via chsh after adding to /etc/shells Seth's steel141 shell is bash; macOS ships bash 3.2. zsh stays installed.
Cmd/Ctrl Untouched Live + every Mac tutorial assume Cmd. kitty handles Ctrl+Shift+C/V itself.
Window snapping Rectangle (Homebrew cask) Zero-config snapping. Upgrade path: AeroSpace if tiling turns out to matter.
Backup launchd user agent -> rsync -a --delete of ~/Music/Ableton and ~/Documents to pve173:/tank/backups/mac/ nightly over SSH Transparent, one file, restorable with plain rsync. Needs a Mac->pve173 SSH key.
Hostname PARAMETER — not yet chosen Seth names machines (bebop, yoga, steel141). setup.sh takes it as HOSTNAME=.
iCloud Account stays (Find My, Keychain). iCloud Drive "Desktop & Documents" sync OFF Sync mid-save corrupts/evicts DAW project files. GUI-only toggle -> manual checklist.
Spotlight Indexing stays ON; Siri Suggestions + web results OFF Finder search still useful; Live's browser has its own index.

Components

All live in ~/bin/mac/. Pushed to git.sethpc.xyz/Seth/mac. Applied by ssh mac from steel141 (seth is the console user, so defaults write + killall Dock/Finder/SystemUIServer take effect from an SSH session).

Brewfile

Single manifest, applied with brew bundle --file=Brewfile. Contents:

  • Formulae: bash coreutils findutils gnu-sed grep gawk gnu-tar iproute2mac tmux htop ripgrep fd jq wget rsync git tree
  • Casks: kitty rectangle tailscale
  • NOT in Brewfile: Ableton Live (licensed download from ableton.com, manual).

scripts/setup.sh

Idempotent bash, set -euo pipefail, run on the Mac as seth. Sections, in order:

  1. preflight — refuse if not arm64 macOS 26.x; require HOSTNAME env var; xcode-select --install if CLT missing (blocks on a GUI prompt the first time — documented).
  2. backup — for each defaults domain about to be written, defaults export <domain> ~/.mac-setup-backup/<domain>-<epoch>.plist (skip if domain absent). Also pmset -g custom and launchctl print gui/$UID to the same dir. This dir is rsync'd back to ~/bin/mac/.backup/ by the runner on steel141.
  3. brew — install Homebrew if missing; brew bundle; write shellenv + gnubin PATH block into ~/.bash_profile (guarded by marker comments so re-runs don't duplicate).
  4. shell — add /opt/homebrew/bin/bash to /etc/shells if absent; chsh -s if current shell differs.
  5. hostnamescutil --set ComputerName/LocalHostName/HostName $HOSTNAME.
  6. defaults (Linux feel) — key repeat KeyRepeat=2 InitialKeyRepeat=15; ApplePressAndHoldEnabled=false; natural scrolling off; Finder: path bar, status bar, all extensions, ~ as new-window target, list view, no .DS_Store on network/USB volumes; no window animations (NSAutomaticWindowAnimationsEnabled=false); hot corners cleared.
  7. defaults (debloat) — Dock: autohide, no recents, persistent-apps rewritten to Finder/kitty/Live/System Settings (Live entry only if /Applications/Ableton Live 12*.app exists); Spotlight Siri suggestions off; Game Center + Handoff (NSUserActivityTrackingEnabled) + Screen Time related agents disabled with launchctl disable gui/$UID/<label> only after the label is confirmed present on this OS. Remove the "SparkFun Pro Micro" PPP network service (networksetup -removenetworkservice).
  8. power (DAW)sudo pmset -c sleep 0 displaysleep 0 disksleep 0 powernap 0; battery profile untouched. App Nap off for Live via defaults write com.ableton.live NSAppSleepDisabled -bool true.
  9. homelab~/.ssh/config seeded with the steel141 aliases (pve*, bebop, etc.); tank SMB mount instructions written (mount itself is GUI / mount_smbfs at login — see checklist); Tailscale cask installed, login is GUI.
  10. backup agent — install ~/Library/LaunchAgents/xyz.sethpc.mac-backup.plist (StartCalendarInterval 03:30) running scripts/backup.sh (the rsync).
  11. applykillall Dock Finder SystemUIServer.

Each section prints [skip] when already in desired state. No section prompts except the CLT install and sudo for pmset/chsh/hostname.

scripts/backup.sh

rsync -a --delete -e ssh ~/Music/Ableton ~/Documents root@192.168.0.173:/tank/backups/mac/. Logs to ~/Library/Logs/mac-backup.log. Uses claude-style key ~/.ssh/id_ed25519 generated on the Mac and installed on pve173 (manual step, one-time).

docs/manual-checklist.md

GUI-only steps on Tahoe, in order, each with the exact Settings path: iCloud Drive Desktop&Documents off; Photos analysis off; Screen Time off; iPhone Mirroring off; Focus mode "DAW" (all notifications silenced, shown in Control Center); Rectangle accessibility grant; kitty full-disk-access grant (for ~/Music/Ableton under TCC); Tailscale login; Live install + Suite Packs download; audio interface buffer/sample rate in Live once one is attached.

Verification

  • setup.sh run twice in a row: second run is all [skip] lines, exit 0.
  • ip a, ls --color, sed --version (GNU), echo $BASH_VERSION -> 5.x, hostname -> chosen name — all over ssh mac.
  • pmset -g custom shows AC sleep 0 powernap 0, battery unchanged.
  • defaults read com.apple.dock persistent-apps shows only the 4 entries.
  • backup.sh dry-run (-n) lists files; real run creates /tank/backups/mac/Ableton on pve173.
  • Live: open a project, leave it 15 min on AC, confirm no sleep and no notifications appear (Focus on).

Rollback

Every defaults domain has a pre-write plist in .backup/; restore with defaults import <domain> <file> + killall Dock Finder. pmset -g custom snapshot restores with the same flags. chsh -s /bin/zsh reverts shell. brew bundle cleanup / brew uninstall for packages. Nothing in this design is irreversible.

Order of operations

  1. Seth picks hostname -> DECISIONS.md.
  2. Write Brewfile, setup.sh, backup.sh, manual-checklist.md.
  3. Run setup.sh over SSH (CLT prompt needs Seth at the lid once).
  4. Seth walks manual-checklist.md.
  5. Install Live, attach interface, verify.
  6. Handoff.