Skip to content

Instantly share code, notes, and snippets.

@jamescamping
Last active June 11, 2025 01:03
Show Gist options
  • Save jamescamping/f477809c1545c27ed60d20009b06a3a8 to your computer and use it in GitHub Desktop.
Save jamescamping/f477809c1545c27ed60d20009b06a3a8 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Credit to @adamshand for the original script https://github.com/adamshand/dotfiles/blob/main/bin/darwin/executable_wifi-toggle.sh
# Automatically toggle macOS Wi-Fi based on ethernet status (uses launchd).
# If ethernet is active, Wi-Fi is disabled. If ethernet is inactive, Wi-Fi is enabled.
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
LAUNCHD_SERVICE_NAME="nz.haume.wifi-toggle"
LAUNCHD_SERVICE_FILE="${HOME}/Library/LaunchAgents/${LAUNCHD_SERVICE_NAME}.plist"
DEBUG="yes"
# Multiple ethernet regexes - the script will check each one and use the first active interface found
# Each regex must match a single interface from networksetup -listnetworkserviceorder
# eg. "(2) CalDigit TS3" or "(1) Apple USB Ethernet Adapter"
ETHERNET_REGEXES=(
"CalDigit TS3"
"Apple USB Ethernet Adapter"
"Thunderbolt Ethernet"
)
WIFI_REGEX="(Wi-Fi|Airport)"
print_usage() {
echo -e "Automatically toggle macOS Wi-Fi based on ethernet status (uses launchd)\n"
echo "Usage: $(basename $0) [ on | off | help ]"
echo " on - start automatically toggling Wi-Fi (install launchd service)"
echo " off - stop automatically toggling Wi-Fi (uninstall launchd service)"
echo " run - Toggle Wi-Fi status (run by launchd)"
exit 1
}
print_error() {
echo -e "ERROR: $1" >&2
exit 1
}
print_debug() {
test -n "$DEBUG" && echo -e "DEBUG: $1" >&2
}
notify() {
# Configure notifications in: System Settings > Notifications > Script Editor
osascript -e "display notification \"by $(basename $0)\" with title \"$1\""
}
is_launchd_enabled() {
if launchctl print gui/$(id -u)/nz.haume.wifi-toggle > /dev/null 2>&1; then
print_debug "is_launchd_loaded(): $LAUNCHD_SERVICE_NAME already loaded"
return 0
else
print_debug "is_launchd_loaded(): $LAUNCHD_SERVICE_NAME not loaded"
return 1
fi
}
enable_launchd() {
echo "Creating launchd service: $LAUNCHD_SERVICE_FILE"
cat <<EOF > "$LAUNCHD_SERVICE_FILE"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${LAUNCHD_SERVICE_NAME}</string>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>$(realpath "$0")</string>
<string>run</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration</string>
</array>
</dict>
</plist>
EOF
echo "Enabling launchd service: $LAUNCHD_SERVICE_NAME"
launchctl bootstrap gui/$(id -u) "$LAUNCHD_SERVICE_FILE"
}
disable_launchd() {
echo "Disabling launchd service: $LAUNCHD_SERVICE_NAME"
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/nz.haume.wifi-toggle.plist
rm "$LAUNCHD_SERVICE_FILE"
}
get_interface() {
test -z "$1" && print_error "get_interface(): no regex provided"
INTERFACE=$(networksetup -listnetworkserviceorder | grep -E -A 1 "^\([0-9]+\).* $1" | grep -E -o "en[0-9]+")
if [ -z "$INTERFACE" ]; then
return 1
elif [[ "$INTERFACE" == *$'\n'* ]]; then
print_error "Multiple ethernet interfaces match: $1"
fi
print_debug "get_interface(): regex '$1' -> interface '$INTERFACE'"
echo "$INTERFACE"
return 0
}
is_interface_active() {
test -z "$1" && print_error "is_interface_active(): no interface provided"
if ifconfig "$1" 2>&1 | grep -q "status: active"; then
echo -n "active"
return 0
else
echo -n "inactive"
return 1
fi
}
find_active_ethernet() {
print_debug "Checking ethernet regexes: ${ETHERNET_REGEXES[*]}"
for regex in "${ETHERNET_REGEXES[@]}"; do
print_debug "Trying ethernet regex: '$regex'"
if interface=$(get_interface "$regex"); then
print_debug "Found interface '$interface' for regex '$regex'"
interface_status=$(is_interface_active "$interface")
print_debug "Interface '$interface' status: '$interface_status'"
if [ "$interface_status" == "active" ]; then
print_debug "Found active ethernet interface: '$interface'"
echo "active"
return 0
fi
else
print_debug "No interface found for regex '$regex'"
fi
done
print_debug "No active ethernet interfaces found"
echo "inactive"
return 0
}
toggle_wifi() {
WIFI_INTERFACE=$(get_interface "$WIFI_REGEX")
if [ $? -ne 0 ]; then
print_error "No Wi-Fi interface found matching: $WIFI_REGEX"
fi
# Check if any ethernet interface is active
ETHERNET_STATUS=$(find_active_ethernet)
WIFI_STATUS=$(is_interface_active "$WIFI_INTERFACE")
print_debug "ethernet status: '$ETHERNET_STATUS', wifi status: '$WIFI_STATUS'"
if [ "$ETHERNET_STATUS" == "active" ] && [ "$WIFI_STATUS" == "active" ]; then
print_debug "disabling wifi"
networksetup -setairportpower "$WIFI_INTERFACE" off
notify "Wi-Fi Disabled"
elif [ "$ETHERNET_STATUS" == "inactive" ] && [ "$WIFI_STATUS" == "inactive" ]; then
print_debug "enabling wifi"
networksetup -setairportpower "$WIFI_INTERFACE" on
notify "Wi-Fi Enabled"
else
print_debug "not toggling wifi status"
fi
}
### main script
if [ "${OSTYPE:0:6}" != "darwin" ]; then
print_error "This script only runs on macOS"
fi
if [ "$1" == "run" ]; then
toggle_wifi
elif [ "$1" == "on" ]; then
if is_launchd_enabled; then
print_error "launchd service already enabled"
else
enable_launchd
fi
elif [ "$1" == "off" ]; then
if is_launchd_enabled; then
disable_launchd
else
print_error "launchd service already disabled"
fi
else
print_usage
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment