#!/usr/bin/env bash # catchup-machine.sh — bring this machine's rulesets state and all .ai/-using # projects in sync with the canonical rulesets repo. Idempotent; safe to re-run. # # Steps: # 1. git pull --ff-only on ~/code/rulesets # 2. make install (refresh ~/.claude/ symlinks for any new skills/commands/rules) # 3. make audit APPLY=1 (rsync .ai/ template content into every project) # 4. make doctor (verify install) # # Use case: after a fresh clone of rulesets on a new machine, or after the # canonical source has advanced and the local machine needs to catch up. # # Projects with uncommitted .ai/ changes are skipped by step 3 — surface them # at the end so the user can commit/stash and re-run. set -euo pipefail REPO="$HOME/code/rulesets" if [ ! -d "$REPO" ]; then echo "ERROR: $REPO not found — clone rulesets first" >&2 exit 1 fi cd "$REPO" echo "=== Step 1/4: Pull rulesets ===" if git diff --quiet --ignore-submodules HEAD -- 2>/dev/null; then git pull --ff-only origin main else echo "WARN: working tree is dirty — skipping pull. Commit or stash first to update." fi echo echo "=== Step 2/4: make install (refresh symlinks) ===" make install echo echo "=== Step 3/4: make audit APPLY=1 (sync .ai/ across projects) ===" # Don't bail on non-zero exit — audit returns 1 when any project was skipped or # applied. Both are expected outcomes here. set +e make audit APPLY=1 NO_DOCTOR=1 audit_exit=$? set -e echo echo "=== Step 4/4: make doctor (verify install) ===" make doctor echo echo "Done." if [ "$audit_exit" -ne 0 ]; then echo echo "Note: audit step exited non-zero, which is expected if any project was" echo "skipped (uncommitted .ai/) or applied (drift fixed). Re-read the audit" echo "output above to see what landed." fi