init: scaffold mac project + inventory + setup design

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mortdecai
2026-09-15 18:54:04 -04:00
commit fa76fd4a73
6 changed files with 246 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
.env
.env.*
*.key
*.pem
GITEA_API.md
.backup/
+42
View File
@@ -0,0 +1,42 @@
# mac
> Ops home for Seth's MacBook Pro — debloat, Linux-feel, Ableton-first.
## Start Here
**Read the latest handoff first:** `.claude/handoffs/` (most recent file).
It has session state, in-progress work, and ordered next steps.
Then check `IDEA.md` for the project brief and `DECISIONS.md` for settled choices.
## Project Identity
Configuration + scripts for Seth's MacBook Pro (arrived 2026-09-15). Three
goals, in priority order: (1) Ableton Live 12 runs clean — this is the DAW
box now that Wine on steel141 is abandoned; (2) feels like Linux to a Linux
user — GNU coreutils, `ip`, familiar shell, ssh-able from steel141; (3) stock
macOS noise turned off. Sibling of `~/bin/ableton/` (which is now an archive
of the Wine attempt) and `~/bin/thinkpad-yoga/` (same "ops home for a
laptop" shape).
## Current State
- **Phase:** ideation
- **Repo:** not yet
- **Deploy target:** the MacBook, `ssh mac` (192.168.0.94, user seth, en0 Wi-Fi)
- **Hardware:** MacBookPro18,1 (16" 2021), M1 Pro, 32 GB, 512 GB. **macOS 26.2 Tahoe.**
- Remote Login enabled + claude key installed 2026-09-15. `ssh mac` works from steel141.
- **FileVault is on** — no SSH after a reboot until the password is typed at the lid.
- Stock state is already clean: no Homebrew/CLT, only Safari in /Applications,
Siri off, Apple Intelligence opted out. Full snapshot:
`docs/reference/inventory-2026-09-15.md` — read when checking "was X stock?".
- No changes made yet.
## Conventions
- All changes as scripts under `scripts/` (bash, idempotent, `set -euo pipefail`);
never one-off `defaults write` in a chat that isn't also committed.
- Before any `defaults write`: `defaults read <domain> > .backup/<domain>-$(date +%s).plist`
- Before any `launchctl disable`/`bootout`: record current `launchctl print` state to `.backup/`
- Homebrew `Brewfile` at repo root is the package manifest — `brew bundle` is the install
- macOS gotchas go in this file's Conventions; per-decision reasoning goes in `DECISIONS.md`
+12
View File
@@ -0,0 +1,12 @@
# DECISIONS.md — mac Decision Log
Project-specific decisions. For global/cross-cutting decisions, see `~/bin/DECISIONS.md`.
Format: `YYYY-MM-DD: <decision> — <why>`
## Architecture
## Implementation
## Deferred / Rejected
<!-- Decisions NOT to do something are just as valuable -- prevents re-proposing rejected ideas -->
+22
View File
@@ -0,0 +1,22 @@
# IDEA.md — Project Idea
## What is this?
Ops home for Seth's new MacBook Pro (Sept 2026). Debloat it, make it feel like
a Linux box to a Linux user, and tune it for Ableton Live 12 (native — the
steel141/Wine route was abandoned 2026-09-14, see `~/bin/ableton/`).
## Problem it solves
Stock macOS is noisy (Siri, Spotlight indexing everything, iCloud nags,
Photos/Music/News/TV auto-launch, animations, Dock junk) and the CLI is BSD
userland with zsh — `ip a` doesn't exist. Want: quiet machine, GNU-flavoured
shell, homelab reachability (SMB to tank, ssh aliases), and a DAW-first
config (no Time Machine mid-set, no sleep/App Nap on Live, audio not
tripped by notifications).
## Constraints / preferences
- Manage over SSH from steel141 (`ssh mac`, 192.168.0.94 LAN / Tailscale later)
- Homebrew for everything installable; scripted + idempotent, not hand-clicked
- `defaults write` changes are reversible — dump before changing (`.backup/`)
- Don't fight SIP/Gatekeeper; disable *services*, don't rip out system apps
- Ableton Suite Packs come with the license (in-app download); third-party
packs live at `/tank/Downloads/Software/Milkie/` via SMB from 192.168.0.173
+135
View File
@@ -0,0 +1,135 @@
# 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. **hostname** — `scutil --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. **apply** — `killall 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.
+29
View File
@@ -0,0 +1,29 @@
# Mac inventory — 2026-09-15 (first SSH, pre-any-changes)
Read when: deciding what to disable/install, or checking "was X already like that out of the box".
## Hardware / OS
- MacBookPro18,1 = 16" 2021, Apple M1 Pro (8P+2E), 32 GB, 512 GB SSD (425 Gi free, 14 Gi used)
- macOS 26.2 Tahoe (build 25C56), arm64
- Uptime 28 days at first login (used/refurb unit); 15-min load was 12.5 right after Seth's setup — settled to idle within the hour (post-setup indexing/iCloud sync, not a persistent hog)
- Hostname: ComputerName "Seth's MacBook Pro", LocalHostName `Seths-MacBook-Pro`
- LAN: en0 Wi-Fi 192.168.0.94. No Tailscale. Stray PPP service "SparkFun Pro Micro" (modem entry from a previously-attached USB board)
## Software state (stock)
- Shell zsh. No Homebrew, no Xcode CLT
- /Applications: Safari + Utilities only. ~/Applications empty
- No third-party LaunchDaemons/LaunchAgents. No user login items
- Dock: full stock Tahoe set (Apps, Safari, Messages, Mail, Maps, Photos, FaceTime, Phone, Calendar, Contacts, Reminders, Notes, TV, Music, Games, App Store, iPhone Mirroring, System Settings, Terminal)
## Services / security
- Siri: off (`Assistant Enabled = 0`). Apple Intelligence: opted out at Setup Assistant (`opted_out_buddy = 1`)
- iCloud: 1 account signed in
- Spotlight: indexing enabled on /
- Time Machine: no destinations
- SIP enabled, Gatekeeper enabled, **FileVault ON** (=> after a reboot, SSH is unreachable until someone types the password at the lid; plan remote work accordingly)
- Remote Login: enabled by Seth 2026-09-15; claude@steel141 ed25519 key installed in ~/.ssh/authorized_keys
- Screen Sharing: not running
- pmset: sleep 1 / displaysleep 10 / disksleep 10 / powernap 1 / hibernatemode 3 / lowpowermode 0
## Audio
- Built-in mic + speakers only. No interface attached at inventory time