Add setup.sh bootstrap script for fresh machines

Runs the whole README runbook in one go: relocates the repo off the USB
stick, installs CLT + Homebrew, brew bundle, symlinks, copied configs,
fish as default shell, and the .NET SDK, then prints the remaining
manual steps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MN5eka2MuNJP9uCMdTda75
This commit is contained in:
Trevi Awater
2026-09-07 19:11:26 +02:00
parent 2c89b8f169
commit 250baaaba1
2 changed files with 120 additions and 1 deletions

View File

@@ -10,7 +10,25 @@ Two kinds of files live here:
- **Copied** — files that can't be symlinked (`/etc/hosts`, Claude/Serena settings, - **Copied** — files that can't be symlinked (`/etc/hosts`, Claude/Serena settings,
the brewfile). Refresh them from the machine with `./update.fish`. the brewfile). Refresh them from the machine with `./update.fish`.
## Fresh machine setup ## Fresh machine setup — the fast way
Get this repo onto the machine (USB stick copy or a clone) and run:
```bash
/bin/bash setup.sh
```
The script is idempotent and does steps 19 below automatically: it copies the
repo to `~/Repositories/personal/macos-configuration` (so it works straight off
a USB stick), installs Command Line Tools and Homebrew, runs the brew bundle,
creates all symlinks, restores the copied configs, sets fish as the default
shell, and installs the .NET SDK. At the end it prints the manual steps that
remain (1Password/SSH keys, iTerm2 profile import, `gh auth login` + repo
cloning, WireGuard, app sign-ins).
The sections below document what the script does, for reference or manual runs.
## Fresh machine setup — step by step
### 1. Install Command Line Tools and clone this repo ### 1. Install Command Line Tools and clone this repo

101
setup.sh Executable file
View File

@@ -0,0 +1,101 @@
#!/bin/bash
# Bootstrap a fresh Mac from this repo. Idempotent — safe to re-run.
#
# /bin/bash setup.sh
#
# Works when run straight from a USB stick or a fresh clone: it first copies
# the repo to ~/Repositories/personal/macos-configuration (so symlinks never
# point at removable media) and continues from there.
set -uo pipefail
REPO_HOME="$HOME/Repositories/personal/macos-configuration"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
step() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; }
# --- 0. Relocate off removable media / into the canonical path -------------
if [ "$SCRIPT_DIR" != "$REPO_HOME" ]; then
step "Copying repo from $SCRIPT_DIR to $REPO_HOME"
mkdir -p "$REPO_HOME"
cp -R "$SCRIPT_DIR/." "$REPO_HOME/"
exec /bin/bash "$REPO_HOME/setup.sh"
fi
cd "$REPO_HOME"
# --- 1. Xcode Command Line Tools -------------------------------------------
if ! xcode-select -p >/dev/null 2>&1; then
step "Installing Xcode Command Line Tools (accept the GUI prompt)"
xcode-select --install
until xcode-select -p >/dev/null 2>&1; do
sleep 10
done
else
step "Xcode Command Line Tools already installed"
fi
# --- 2. Homebrew ------------------------------------------------------------
if [ ! -x /opt/homebrew/bin/brew ]; then
step "Installing Homebrew"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else
step "Homebrew already installed"
fi
eval "$(/opt/homebrew/bin/brew shellenv)"
# --- 3. Packages, casks, VS Code extensions --------------------------------
step "Installing brewfile bundle (this takes a while)"
brew bundle --file="$REPO_HOME/brewfile" || true
# --- 4. Symlink configs ------------------------------------------------------
step "Symlinking configuration files"
mkdir -p ~/.config/fish ~/.kube ~/.nuget/NuGet ~/.ssh
ln -sf "$REPO_HOME/fish-config.fish" ~/.config/fish/config.fish
ln -sf "$REPO_HOME/starship.toml" ~/.config/starship.toml
ln -sf "$REPO_HOME/ssh-config" ~/.ssh/config
ln -sf "$REPO_HOME/kube-config" ~/.kube/config
ln -sf "$REPO_HOME/.npmrc" ~/.npmrc
ln -sf "$REPO_HOME/NuGet.Config" ~/.nuget/NuGet/NuGet.Config
# --- 5. Copied configs -------------------------------------------------------
step "Restoring copied configs"
mkdir -p ~/.claude ~/.serena
cp "$REPO_HOME/claude-settings.json" ~/.claude/settings.json
cp "$REPO_HOME/serena_config.yml" ~/.serena/serena_config.yml
echo "Updating /etc/hosts (sudo)"
sudo cp "$REPO_HOME/hosts" /etc/hosts
# --- 6. Fish as default shell ------------------------------------------------
if ! grep -q /opt/homebrew/bin/fish /etc/shells; then
step "Registering fish as a shell (sudo)"
echo /opt/homebrew/bin/fish | sudo tee -a /etc/shells
fi
if [ "$(dscl . -read "/Users/$USER" UserShell | awk '{print $2}')" != "/opt/homebrew/bin/fish" ]; then
step "Setting fish as default shell"
chsh -s /opt/homebrew/bin/fish
fi
# --- 7. .NET 10 SDK ----------------------------------------------------------
if [ ! -x "$HOME/.dotnet/dotnet" ]; then
step "Installing .NET 10 SDK"
/opt/homebrew/bin/fish "$REPO_HOME/install-dotnet10.fish"
else
step ".NET SDK already installed"
fi
# --- 8. Point git remote at SSH ---------------------------------------------
if [ -d "$REPO_HOME/.git" ]; then
git -C "$REPO_HOME" remote set-url origin git@github.com:awatertrevi/macos-configuration.git 2>/dev/null || true
fi
step "Done. Remaining manual steps:"
cat <<'EOF'
1. Open 1Password, sign in, enable Settings > Developer > SSH Agent,
and put the *.pub files referenced in ssh-config into ~/.ssh/.
2. iTerm2 > Settings > Profiles > Import JSON Profiles > iterm-profile.json.
3. gh auth login, then: fish clone-resoftware-repos.fish
4. Optional: import meerkoet-proxy.conf into the WireGuard app.
5. Sign in to iCloud, browsers, Slack, Spark, Google Drive, Docker,
Todoist, JetBrains Toolbox; restore Alfred/BTT licenses.
EOF