Skip to content

Scripts

Four small, readable files that automate the fiddly parts of this guide. They share the same rules:

  • Dry run by default. Nothing changes until you add --apply. (health-check.sh never changes anything.)
  • Idempotent. Running a script twice is safe; the second run reports that everything is already set.
  • No destructive defaults. Nothing is deleted; replaced LaunchAgent files are backed up.
  • --help on every script explains every option.

Download the scripts into ~/bin and make them executable:

Terminal window
mkdir -p ~/bin
mv ~/Downloads/setup-power.sh ~/Downloads/health-check.sh ~/Downloads/install-launchagent.sh ~/bin/
chmod +x ~/bin/*.sh
xattr -d com.apple.quarantine ~/bin/*.sh 2>/dev/null || true # clear the "downloaded from the internet" flag
~/bin/setup-power.sh --help

They use only tools that ship with macOS (bash, pmset, systemsetup, launchctl, plutil), so there’s nothing else to install.

Keeps the Mac awake and makes it restart by itself. Covered in Stay awake & auto-recover.

Terminal window
~/bin/setup-power.sh # dry run: current values and planned changes (never uses sudo)
~/bin/setup-power.sh --apply # apply (asks for your password)
~/bin/setup-power.sh --apply --daily-poweron 04:30 # also power on daily at 04:30
Setting Command it runs
Never sleep pmset -a sleep 0 disksleep 0
Display may sleep (default 10 min, --display-sleep N) pmset -a displaysleep 10
Wake for network access (skip with --no-wake-on-network) pmset -a womp 1
Restart after power failure pmset -a autorestart 1
Keep TCP connections alive pmset -a tcpkeepalive 1
Restart after freeze (skip with --no-restart-on-freeze) systemsetup -setrestartfreeze on
Optional daily power-on pmset repeat wakeorpoweron MTWRFSU HH:MM:00

Example dry run:

Mode: DRY RUN — nothing will be changed. Re-run with --apply to make changes.
Power settings (pmset):
[change] sleep: 1 -> 0
[change] disksleep: 10 -> 0
[ok] displaysleep = 10
[change] autorestart: 0 -> 1
[ok] tcpkeepalive = 1
[ok] womp = 1
would run: sudo pmset -a sleep 0 disksleep 0 autorestart 1
Restart after freeze (systemsetup):
[unknown] restart after freeze: reading it needs admin rights, and dry runs never use sudo.
Check it yourself: sudo systemsetup -getrestartfreeze
would run (if not already On): sudo systemsetup -setrestartfreeze on
Dry run complete. Re-run with --apply to make these changes.

A dry run never calls sudo, so it can’t read the one value that needs admin rights (restart after freeze) and reports it as unknown, with the command to check it yourself. With --apply, the script uses sudo to read it first and only changes it if it isn’t already on.

To undo, use System Settings → Energy, or sudo pmset restoredefaults.

Read-only report of what’s running and what isn’t — run it after every restart, or on a schedule. Exit status is 1 if anything failed, so you can use it in other scripts.

Terminal window
~/bin/health-check.sh
~/bin/health-check.sh --app Cursor --app Claude --agent com.example.cursor-worker

Save your expectations in ~/.config/mac-ai-server/health-check.conf so a plain health-check.sh checks them:

# Apps that must be running (exact process names)
app=Cursor
app=Claude
app=Google Drive
# LaunchAgents that must be loaded
agent=com.example.cursor-worker

Example output:

Mac mini AI server — health check
System
INFO macOS 26.0
WARN Up for 4 min — it rebooted recently. Check everything below came back.
Power (pmset)
PASS System sleep disabled (sleep 0)
PASS Restart after power failure on (autorestart 1)
PASS Wake for network access on (womp 1)
Unattended restart
INFO FileVault is On — after a power cut the Mac waits for a password before your apps start.
Remote access
PASS Remote Login (SSH) is listening
PASS Screen Sharing is listening
PASS Tailscale is connected
Apps
PASS Cursor is running
FAIL Claude is NOT running (required)
LaunchAgents
PASS com.example.cursor-worker is running
Summary: 8 pass, 1 warn, 1 fail

Turns any command into a LaunchAgent that starts at login and is restarted if it exits (or runs every N seconds with --interval). Covered in Login items & LaunchAgents.

Terminal window
# Dry run: prints the plist and the launchctl commands
~/bin/install-launchagent.sh --label com.example.cursor-worker --workdir ~/code/my-project \
-- ~/.local/bin/agent worker start --name your-mac-mini
# Install and load it
~/bin/install-launchagent.sh --apply --label com.example.cursor-worker --workdir ~/code/my-project \
-- ~/.local/bin/agent worker start --name your-mac-mini
# Remove it (the plist is moved to a backup folder, not deleted)
~/bin/install-launchagent.sh --apply --label com.example.cursor-worker --uninstall
Option Meaning
--label Reverse-DNS job name (required)
--workdir DIR Working directory, absolute path (default: home)
--interval SECS Run every SECS seconds instead of keeping it alive
--log-dir DIR Log folder, absolute path (default ~/Library/Logs/<label>/)
--env KEY=VALUE Extra environment variables (repeatable)
--uninstall Unload and back up the plist

com.example.ai-worker.plist is a commented plist you can edit by hand: replace YOUR_USER, adjust the command and folders, and follow the load instructions at the top of the file.

The scripts live in the scripts/ folder of this site’s repository, with a test suite that runs them against stand-in versions of the macOS commands. See the repository README for how to run ShellCheck and the tests yourself.