defaults & plists
Tweaking macOS through the preference database — and reloading so it sticks.
defaults & plists
Every preference on macOS — every checkbox in System Settings, every Dock autohide toggle, every app preference pane — is stored in a plist file. The defaults command is the universal interface for reading and writing them. Learn it once and you stop needing to chase "how do I configure X" articles.
Analogy
Picture the electrical panel in the utility closet of a house. The decorative wall switches in the living room — lamp, ceiling fan, dimmer — are the System Settings pane: easy, curated, fine for everyday use. But behind that is the breaker panel with hundreds of labelled toggles for circuits the builder never exposed: the porch light's daylight sensor, the garbage disposal interlock, the heated-floor thermostat. defaults is the flashlight and the breaker panel together. Each domain (com.apple.finder, NSGlobalDomain) is one circuit section; each key is one breaker; the type flag is whether the breaker takes an integer amperage, a boolean on/off, or a named setting. And because some appliances only read their circuit at startup, you have to flick them off and on — that's killall Finder.
How the database is laid out
Two locations you care about:
~/Library/Preferences/— per-user preferences/Library/Preferences/— system-wide preferences
Each file is named after its domain: com.apple.dock.plist, com.apple.finder.plist, com.apple.screencapture.plist. The domain is the reverse-DNS identifier the app uses; third-party apps follow the same convention (com.spotify.client.plist).
There's also a catch-all: NSGlobalDomain (aka .GlobalPreferences), which is inherited by every Cocoa app. Keyboard repeat, window animations, system accent colour — these live here.
Reading
defaults read # every key in every domain, huge dump
defaults read com.apple.dock # one domain's whole plist
defaults read com.apple.dock autohide # a single key
defaults read-type com.apple.dock autohide # just the type
Before you tweak anything, defaults read the domain and pipe it to a file. That's your rollback plan.
Writing
The write syntax:
defaults write <domain> <key> <type> <value>
The type flag matters. If you defaults write an integer key with -string "1", the value has the wrong type and the owning app will ignore it. Common flags:
| Flag | Example value |
|---|---|
-string |
"jpg" |
-int |
30 |
-bool |
true / false |
-float |
0.5 |
-array |
value1 value2 value3 |
-dict |
key1 value1 key2 value2 |
Screenshots to JPG:
defaults write com.apple.screencapture type -string "jpg"
Faster keyboard repeat (below the UI slider's floor):
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15
Show hidden files in Finder:
defaults write com.apple.finder AppleShowAllFiles -bool true
The killall pattern
Preferences are cached in memory by the owning process. A defaults write changes the plist on disk, but Finder won't pick up the change until it restarts. The idiom:
defaults write com.apple.finder AppleShowAllFiles -bool true
killall Finder
killall <name> sends SIGTERM to every process with that name; the process restarts and re-reads the plist. The common targets:
| Writing to... | killall target |
|---|---|
com.apple.finder |
Finder |
com.apple.dock |
Dock |
com.apple.screencapture |
SystemUIServer |
NSGlobalDomain (varies) |
Often SystemUIServer, or log out/in |
Some changes only take effect after a full logout — NSGlobalDomain AppleInterfaceStyle (light/dark), for example.
Undoing a tweak
defaults delete com.apple.dock autohide-time-modifier
killall Dock
delete removes the key; the app reverts to its compiled-in default. You can also write the opposite value; for booleans, writing false undoes true.
Finding the right key
The discovery workflow:
- Close the app you want to configure.
defaults read com.apple.dock > /tmp/before.plist- Open the app, flip one setting, close it.
defaults read com.apple.dock > /tmp/after.plistdiff /tmp/before.plist /tmp/after.plist
The diff is the key and value you just flipped. This is how every "dotfiles .macos" on GitHub was written.
plutil — for non-preference plists
Preferences go through defaults. Random plist files — Info.plist in an app bundle, a launchd agent plist — use plutil:
plutil -lint path/to.plist # validate XML
plutil -p path/to.plist # pretty-print
plutil -convert xml1 path/to.plist # convert binary plist to XML for editing
plutil -convert binary1 path/to.plist # back to binary (what launchd wants)
Modern plists are stored in a binary format for size. plutil -convert xml1 -o - path/to.plist is the quickest way to view one.
Why this matters
macOS has a thousand UI toggles and ten thousand that never made it to a UI. Every one of them is a defaults write away. Dotfiles-style tweaks scripts — .macos in a dotfiles repo — scale to hundreds of preferences applied in seconds on a new machine. Learn this one command and you control your Mac; ignore it and you spend the next decade clicking through System Settings.