A lightweight macOS menu bar app for DNS profile switching
No Dock icon. It lives entirely in your menu bar.
- Switch DNS profiles with two clicks from the menu bar
- Ships with Cloudflare, Quad9, and AdGuard profiles
- Create custom profiles with any DNS servers
- "Off (DHCP)" resets to automatic DNS
- Apply to all network interfaces or just the primary one
- Launch at login support
- IPv4 and IPv6 server validation
- One administrator prompt per change, no stored credentials
| Profile | Primary | Secondary |
|---|---|---|
| Cloudflare | 1.1.1.1 |
1.0.0.1 |
| Quad9 | 9.9.9.9 |
149.112.112.112 |
| AdGuard | 94.140.14.14 |
94.140.15.15 |
Choose Off (DHCP) to clear these and return to your network's automatic DNS.
brew tap kacigaya/tap
brew install --cask dnsswitcher
# Remove quarantine attribute to avoid Gatekeeper warnings
xattr -d com.apple.quarantine /Applications/DNSSwitcher.app- Download the latest DMG from Releases
- Drag DNS Switcher to Applications
- Run
xattr -d com.apple.quarantine /Applications/DNSSwitcher.app - Launch the app. A globe icon with two circular arrows appears in the menu bar.
git clone https://github.com/kacigaya/dns-switcher.git
cd dns-switcher
make app
open ".build/apple/Products/Release/DNSSwitcher.app"Click the globe icon in the menu bar to see your DNS profiles. Select one to apply it. Choose Off (DHCP) to reset to automatic DNS. Open Preferences to manage profiles and settings. In Preferences, double-click a profile to edit it. Right-click a profile to edit or delete it. Press Delete to remove the selected profile.
The app never talks to a DNS resolver itself. It shells out to macOS's own
networksetup tool to read and write the DNS servers of each connected network
service, then flushes the resolver cache with dscacheutil -flushcache.
Reading the current state spawns several networksetup processes, so it happens
off the main thread: the menu opens instantly from the last known state and
updates in place once the fresh read lands.
Source layout:
| Path | Contents |
|---|---|
Sources/DNSSwitcher/App |
App entry point, delegate, settings window |
Sources/DNSSwitcher/MenuBar |
Status item and menu construction |
Sources/DNSSwitcher/DNS |
networksetup wrappers, DNS state snapshot, IP parsing |
Sources/DNSSwitcher/Models |
DnsProfile and its validation rules |
Sources/DNSSwitcher/Storage |
UserDefaults-backed profile store |
Sources/DNSSwitcher/UI |
SwiftUI settings screen and Liquid Glass helpers |
swift test # unit tests
make app # build and assemble DNSSwitcher.app
make dmg # build the distributable disk imageCI runs on macOS for every pull request. It builds with warnings as errors, runs
the tests, runs them again with Thread Sanitizer, and builds the app bundle.
Tests replace every privileged DNS command with a fake, so they never change the
network settings of the machine that runs them. Tagging vX.Y.Z runs the tests,
builds the DMG, publishes the release, and updates the Homebrew cask checksum.
macOS requires administrator privileges to change DNS settings via networksetup. The app first tries without elevation, and only when that fails does it ask, using AppleScript's with administrator privileges. All interfaces that need elevation are changed in a single privileged command, so you are asked at most once per switch. No credentials are stored.
- macOS 13.0 (Ventura) or later
- Building from source requires Xcode 26 or later on macOS 15.6 or later