The command that actually toggles macOS dark mode from the terminal, instantly and with no restart, is one line of AppleScript run through osascript:
osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to not dark mode'Run it and the whole desktop flips: menu bar, Dock, Finder, and every app that respects the system appearance switch over the moment the line returns. not dark mode reads the current state and inverts it, so the same command toggles back and forth. There is no daemon to kick, no killall, no log out, and no reboot. It works on every macOS from Mojave (10.14, the release that introduced Dark Mode) through Tahoe.
If you found this page looking for the defaults write … _HIEnableThemeSwitchHotKey trick, skip it. That one does not switch the theme at all, and I explain why further down.
Force it on or force it off
not dark mode is great for a toggle bound to a hotkey, but for a script you usually want to set an explicit state rather than flip whatever happens to be current. Set the boolean directly:
# Force Dark
osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to true'
# Force Light
osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to false'Setting dark mode to true is the programmatic equivalent of clicking Dark in System Settings, Appearance; false is the same as clicking Light. These are idempotent: forcing Dark when you are already in Dark does nothing and does not error, which is exactly what you want in a script that runs on a schedule.
If you would rather drive it from JavaScript for Automation (JXA) than AppleScript, the same property is reachable that way and behaves identically:
osascript -l JavaScript -e 'Application("System Events").appearancePreferences.darkMode = true'It is the same System Events bridge under the hood, so it needs the same Automation grant and flips live with no restart. Pick whichever language your tooling already speaks.
Read the current state first
When a script needs to branch on the appearance (do one thing in Dark, another in Light), read the boolean instead of guessing:
osascript -e 'tell app "System Events" to tell appearance preferences to get dark mode'It prints true if Dark is active and false if Light is. That gives you a clean conditional in a shell script without parsing a plist:
if [ "$(osascript -e 'tell app "System Events" to tell appearance preferences to get dark mode')" = "true" ]; then
echo "Dark mode is on"
else
echo "Dark mode is off"
fiThe first run asks for permission
The first time you run any of these, macOS pops an Automation consent dialog: "Terminal wants access to control System Events." Click OK and it never asks again for that terminal app. This is TCC (Transparency, Consent, and Control) doing its job, because the script is reaching into another process to change a system setting.
If you ever click the wrong button, or a script runs but the appearance does not change, the grant lives in System Settings, Privacy & Security, Automation. Find your terminal app in that list and make sure System Events is checked underneath it. A non-interactive runner (a launchd job, a cron line, a CI step) has to be pre-authorized there once, because there is no human present to click the dialog.
One thing that bites people after a big upgrade: macOS Sequoia (15) tightened TCC, and a major OS update can drop the existing Automation grant, so a toggle that worked yesterday silently does nothing until you re-approve System Events for your terminal. If a previously-working script goes quiet right after an update, that consent list is the first place to look.
Why the _HIEnableThemeSwitchHotKey advice is wrong
A trick that circulates widely tells you to run something like this:
# This does NOT toggle the theme. Do not use it.
sudo defaults write /Library/Preferences/.GlobalPreferences.plist _HIEnableThemeSwitchHotKey -bool trueIt does not switch your appearance. All it does is flip a private, long-dead preference that was meant to arm a keyboard hotkey for theme switching, and that hotkey has not functioned in current macOS for years. The dead giveaway is the instruction that almost always rides along with it: "you need to restart for it to take effect." The real appearance switch is instant. Any command that claims a reboot is required is touching the wrong key, because the genuine setting (appearance preferences set dark mode, above) flips live with no restart. It also asks for sudo and writes a system-wide plist, where dark mode is a per-user setting, another sign it is aimed at the wrong place. Use the osascript line.
A reusable toggle function
If you flip appearance often, wrap the toggle in a tiny shell function in your ~/.zshrc. The te_ prefix keeps it from colliding with anything else on your path:
# Toggle macOS dark/light from the shell. No sudo, no restart.
te_darkmode() {
osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to not dark mode'
}Then te_darkmode flips the desktop from anywhere. Bind it to a global key with a tool like skhd if you want a single keystroke that genuinely works, unlike the dead hotkey above.
No sudo, because it is a per-user setting
None of these commands need sudo. Appearance is stored per user, so changing it is something your own session is allowed to do without elevation. If you find a snippet that reaches for sudo to set dark mode, treat that as another sign it is editing the wrong thing. Your account toggling its own look is not a privileged operation, the same way setting your own system volume does not need root either.
This is the same osascript and System Events bridge that drives a lot of macOS terminal automation, including setting the desktop wallpaper from the command line. It is worth getting comfortable with, because once you can read and set one appearance toggle, the same pattern controls a long list of UI settings that have no dedicated CLI.
See also
- Change the system volume from the macOS command line: the modern 0 to 100
osascriptform, no sudo, plus reading the current level. - Set the desktop wallpaper from the macOS command line: the same System Events bridge, with multi-display handling.
- Set the date and time from the macOS command line: the BSD
dategrammar and why a common flag-based trick does not actually set the clock.
Sources
Authoritative references this article was fact-checked against.
- osascript man page (ss64 reference)ss64.com
- Use a light or dark appearance on Mac (Apple Support)support.apple.com
- Allow apps to control other apps on Mac (Apple Support)support.apple.com





