Automate switching between macOS and Windows on T2 chip MacBooks (2018-2020 Intel Macs with Boot Camp).
Apple's T2 security chip blocks all command-line methods for changing the startup disk (bless, nvram, bcdedit). Only Apple's signed GUI apps can communicate with the T2 chip to change boot settings.
GUI automation scripts for each OS:
switch-to-windows.sh- Run on macOS, reboots to Windowsswitch-to-macos.ps1- Run on Windows, reboots to macOS
brew install cliclickFirst-time setup: Grant the following permissions to the app running the script:
-
Accessibility permissions:
- Go to System Settings → Privacy & Security → Accessibility
- Add and enable the app that's running the script:
- Terminal.app - if running from Terminal
- iTerm - if using iTerm
- GitHub Runner - if running via GitHub Actions (usually located in
~/actions-runner)
-
Automation permissions:
- Go to System Settings → Privacy & Security → Automation
- Find your terminal app (Terminal, iTerm, etc.)
- Enable both System Events and System Settings
Without these permissions, the script cannot interact with System Preferences or send clicks/keystrokes.
winget install AutoHotkey.AutoHotkeyFirst-time setup: Ensure Boot Camp icon is in the system tray overflow area (click the ^ arrow in taskbar to verify).
# On macOS - switch to Windows
export MACOS_PASSWORD="your-password"
./switch-to-windows.sh
# On Windows - switch to macOS
.\switch-to-macos.ps1macOS password is needed for Startup Disk authentication:
# Option 1: Environment variable (recommended for CI)
export MACOS_PASSWORD="your-password"
./switch-to-windows.sh
# Option 2: Edit script directly
# Edit switch-to-windows.sh line 5
MACOS_PASSWORD="your-password-here"Use a single Mac as a dual-OS self-hosted runner. The workflow re-queues itself before rebooting, so the job automatically retries on the correct OS.
-
Install
ghCLI on the runner (both OSes)# macOS brew install gh # Windows (in admin PowerShell) winget install GitHub.cli
-
Create a Personal Access Token (PAT)
- Go to GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens
- Create token with these permissions:
repo- Full control (for workflow access)workflow- Update GitHub Action workflows
- Or use classic token with
repoandworkflowscopes
-
Add repository secrets
- Go to your repo → Settings → Secrets and variables → Actions
- Add these secrets:
WORKFLOW_PAT- Your PAT from step 2MACOS_PASSWORD- Your Mac login password (for Startup Disk auth)
-
Copy workflow file
cp dual-os-build.yml .github/workflows/
1. Workflow triggered with target_os=windows
2. Job starts on macOS (wrong OS)
3. gh workflow run queues new run
4. switch-boot.sh reboots to Windows
5. Job fails (machine rebooted)
6. Machine boots to Windows
7. New queued job starts on Windows
8. Correct OS - build proceeds
- name: Switch to Windows (from macOS)
if: runner.os == 'macOS' && inputs.target_os == 'windows'
env:
GH_TOKEN: ${{ secrets.WORKFLOW_PAT }}
MACOS_PASSWORD: ${{ secrets.MACOS_PASSWORD }}
run: |
gh workflow run "${{ github.workflow }}" -f target_os=windows
sleep 5
./switch-to-windows.sh
exit 1
- name: Switch to macOS (from Windows)
if: runner.os == 'Windows' && inputs.target_os == 'macos'
env:
GH_TOKEN: ${{ secrets.WORKFLOW_PAT }}
shell: pwsh
run: |
gh workflow run "${{ github.workflow }}" -f target_os=macos
Start-Sleep -Seconds 5
.\switch-to-macos.ps1
exit 1MACOS_PASSWORDis passed as environment variable, not command-line argument- Secrets are masked in GitHub Actions logs
- Consider using a dedicated CI user account with limited permissions
- MacBook Pro 16,1 (2019) with T2 chip
"cliclick" cannot be opened because it is from an unidentified developer
xattr -d com.apple.quarantine $(which cliclick)Script runs but nothing happens
- Check accessibility permissions: System Settings → Privacy & Security → Accessibility
- Check automation permissions: System Settings → Privacy & Security → Automation
- Ensure System Events and System Settings are enabled for your terminal app
- Ensure Terminal/iTerm/runner app is listed and enabled in both sections
- Try removing and re-adding the app from the list
Clicks go to wrong location
- Display resolution may differ from script coordinates
- Edit
switch-to-windows.shand adjust coordinates for your setup
Boot Camp not found
- Ensure Boot Camp icon is in the overflow tray (click
^in taskbar) - Check no other tray icon starts with 'B' (keyboard shortcut conflict)
- Verify AutoHotkey v2 is installed (not v1)
AutoHotkey not found
winget install AutoHotkey.AutoHotkey- Manual selection: Hold
Optionat startup to pick boot disk - Recovery: Hold
Cmd+Rat startup for Recovery Mode - NVRAM reset: Hold
Option+Cmd+P+Rfor 20 seconds
MIT