cheat sheet
defaults
Read, write, search, and delete macOS preference plists with the `defaults` CLI: data types, domains, current-host scope, the killall dance, finding undocumented keys via plist diffing, and a curated bootstrap recipe.
defaults — macOS Preferences From the Command Line
What it is
defaults is Apple's command-line front-end to the user defaults system — the same property-list (plist) database that every macOS app reads on launch and that System Settings writes when you flip a toggle in the GUI. It ships with macOS at /usr/bin/defaults, requires no install, and is the only first-party way to script the hundreds of hidden, undocumented preferences that don't appear in System Settings — Dock auto-hide delay, screencapture format, Finder hidden-file visibility, key-repeat speed, and so on. Reach for defaults when you want a reproducible bootstrap script that turns a brand-new Mac into "your" Mac, or when an app exposes a setting only via a Terminal write. The closest analogue on Windows is reg.exe/Set-ItemProperty writing to HKCU\Software; on Linux it's gsettings for GNOME or dconf directly.
Install
defaults is part of the macOS base system. There is nothing to install and the binary path is the same on every macOS release.
which defaults
defaults help | head -5
Output:
/usr/bin/defaults
Command line interface to a user's defaults.
Syntax:
'defaults' [-currentHost | -host <hostname>] followed by one of the following:
Scope-narrowing notice
Apple has announced that defaults "will be changed in an upcoming major release to only operate on preferences domains". General plist manipulation (reading/writing arbitrary .plist files via the path-style defaults read /path/to/file.plist form) will move to a separate command-line tool. Scripts that target real preference domains by reverse-DNS name (com.apple.dock, com.apple.finder, NSGlobalDomain) will continue to work unchanged; any script that points defaults at an arbitrary plist file outside ~/Library/Preferences/ should be migrated to plutil now.
# This style — domain by reverse-DNS — keeps working
defaults read com.apple.dock autohide
# This style — defaults pointed at an arbitrary file — is on the chopping block
defaults read /path/to/Some.plist SomeKey
# Migrate to plutil:
plutil -extract SomeKey raw /path/to/Some.plist
Output: (none — exits 0 on success)
Syntax
The base invocation has three positions: a verb (read, read-type, write, delete, rename, domains, find, import, export), an optional domain (the application's bundle identifier, or -g/NSGlobalDomain for system-wide), and verb-specific arguments. An optional -currentHost or -host <hostname> prefix scopes the operation to a per-host plist subtree under ~/Library/Preferences/ByHost.
defaults [-currentHost | -host <hostname>] <verb> [<domain>] [<key>] [<value-with-type-flag>]
Output: (none — exits 0 on success)
Essential options
| Verb / flag | Meaning |
|---|---|
read | Print one key, every key in a domain, or every domain |
read-type | Print the type (boolean/integer/float/string/array/dict/data) of a key |
write | Set or overwrite a key |
delete | Remove a key or an entire domain |
rename | Rename a key within a domain |
domains | List every known domain |
find <text> | Substring search across all domains for keys, values, and domain names |
import / export | Bulk move a plist file in or out of the database |
-g / NSGlobalDomain | Apply to system-wide defaults that every app inherits |
-currentHost | Scope to this specific host (per-machine prefs, e.g. screen-saver password delay) |
-bool true|false | Boolean value type |
-int N | Integer value type |
-float N.N | Float value type |
-string "text" | String value type |
-array ... | Array value (positional values follow) |
-array-add ... | Append to an existing array |
-dict ... | Dictionary value (key/value pairs follow) |
-dict-add k v | Add or overwrite a single key inside an existing dict |
-data <hex> | Binary value (rare; usually managed by the app) |
-date <ISO-8601> | Date value |
Domains and storage layout
A domain is a single plist file Apple writes under ~/Library/Preferences/; it is keyed by the app's reverse-DNS bundle identifier (e.g. com.apple.dock, com.apple.finder, com.googlecode.iterm2). The pseudo-domain -g (also known as NSGlobalDomain) is the system-wide preference file every Cocoa app inherits before its own domain is applied; it stores cross-app settings like key-repeat rates and the AppleInterfaceStyle (dark mode).
# List every known domain
defaults domains | tr ',' '\n' | head -10
# List the per-host subset (typically tied to hardware UUID)
defaults -currentHost domains | tr ',' '\n' | head -10
# Locate the plist file backing a domain
ls -lh ~/Library/Preferences/com.apple.dock.plist
ls -lh ~/Library/Preferences/ByHost/com.apple.screensaver.*.plist
Output:
ContextStoreAgent
Mail
com.apple.AddressBook
com.apple.AppStore
com.apple.Console
com.apple.HIToolbox
com.apple.LaunchServices
com.apple.Music
com.apple.Notes
com.apple.Preview
The plist files themselves are binary by default, but plutil -p (or defaults read) decodes them to a readable form:
plutil -p ~/Library/Preferences/com.apple.dock.plist | head -20
plutil -convert xml1 -o - ~/Library/Preferences/com.apple.dock.plist | head -20
Output:
{
"AppleShowAllExtensions" => 1
"autohide" => 1
"autohide-delay" => 0
"autohide-time-modifier" => 0.5
"launchanim" => 0
"magnification" => 0
"mineffect" => "scale"
"minimize-to-application" => 1
"orientation" => "bottom"
"show-process-indicators" => 1
"show-recents" => 0
"tilesize" => 48
}
Reading values
defaults read is the primary inspection verb. With no arguments it dumps every key in every domain; pass a domain to get just that app's plist; pass a key as well to get a single value. Pair with read-type to discover whether a value is stored as a bool, int, float, string, array, or dict — the type determines the -bool / -int / -string flag you'll use when writing it back.
# Everything (warning: thousands of lines)
defaults read | head -20
# One domain
defaults read com.apple.dock
# One key
defaults read com.apple.dock autohide
defaults read com.apple.dock tilesize
# Type of a key
defaults read-type com.apple.dock autohide
defaults read-type com.apple.dock tilesize
# Global-domain key (any Cocoa app inherits)
defaults read -g AppleInterfaceStyle
defaults read NSGlobalDomain AppleHighlightColor
# Per-host key
defaults -currentHost read com.apple.screensaver askForPasswordDelay
Output:
1
48
Type is boolean
Type is integer
Dark
0.709800 0.835300 1.000000 Blue
0
A common diagnostic pattern: pipe read through grep when you remember a setting's name fragment but not its exact key.
defaults read com.apple.finder | grep -i sidebar
defaults read | grep -i 'screencapture'
Output:
ShowSidebar = 1;
SidebarTagsSctionDisclosedState = 1;
"location" = "~/Pictures/Screenshots";
"type" = "png";
"include-date" = 1;
Writing values — types matter
defaults write requires you to be explicit about the value's type. Skipping the type flag (defaults write com.apple.dock autohide true) will store the string "true", which the Dock will silently ignore — the symptom is "I ran the command and nothing happened". Always pass -bool, -int, -float, -string, -array, -dict, -data, or -date so the value is committed in the correct CFType.
# Boolean — preferred over the legacy yes/no spelling
defaults write com.apple.dock autohide -bool true
# Integer
defaults write com.apple.dock tilesize -int 36
# Float — note the dotted decimal, not a string
defaults write com.apple.dock autohide-time-modifier -float 0.5
# String (single token, no quotes needed in shell)
defaults write com.apple.dock orientation -string left
# Array (positional values after -array)
defaults write com.apple.finder NewWindowTargetPath -array \
"file:///Users/alice/Documents/" "file:///Users/alice/Downloads/"
# Append to an existing array
defaults write com.apple.dock recent-apps -array-add "/Applications/Safari.app"
# Dictionary (key/value pairs)
defaults write com.apple.screensaver Default -dict \
moduleDict "{ moduleName = Flurry; path = '/System/Library/Screen Savers/Flurry.saver'; type = 0; }"
# Or surgically update a single key inside an existing dict
defaults write com.apple.dock persistent-apps -dict-add tile-data \
"<dict><key>file-data</key><dict>...</dict></dict>"
# Date (ISO-8601)
defaults write com.example.app LastChecked -date "2026-05-25T09:00:00Z"
Output: (none — exits 0 on success)
The companion verb read-type is the safe way to confirm what type to use:
defaults read-type com.apple.dock autohide
defaults read-type com.apple.dock tilesize
defaults read-type com.apple.finder NewWindowTargetPath
Output:
Type is boolean
Type is integer
Type is array
Killall — applying changes
Most macOS apps cache their defaults at launch and never re-read them while running. To apply a defaults write you typically killall the app (which sends SIGTERM and lets launchd restart it). The triumvirate is killall Dock, killall Finder, and killall SystemUIServer; some settings (key-repeat rates, AppleInterfaceStyle) require a full logout/login cycle instead.
# Apply Dock changes
killall Dock
# Apply Finder changes
killall Finder
# Apply menu-bar / control-center changes
killall SystemUIServer
# Apply changes to NotificationCenter
killall NotificationCenter
# Restart cfprefsd to force every other app's cache to invalidate (heavy-handed)
killall cfprefsd
# Force a full logout (requires login again)
osascript -e 'tell application "loginwindow" to «event aevtrlgo»'
Output: (none — exits 0 on success)
| Setting domain | killall target | Notes |
|---|---|---|
com.apple.dock | Dock | Includes Mission Control gestures |
com.apple.finder | Finder | Hidden-file visibility, default sort order |
com.apple.controlcenter / menu bar | SystemUIServer | Battery percentage, Wi-Fi icon, sound icon |
com.apple.screencapture | SystemUIServer | Screenshot format, save location |
com.apple.notificationcenterui | NotificationCenter | Banner position, do-not-disturb |
com.apple.universalaccess | logout | Accessibility tweaks |
NSGlobalDomain key-repeat | logout | InitialKeyRepeat, KeyRepeat |
Deleting and resetting
defaults delete removes a single key or an entire domain. Deleting a domain restores every key in it to its compiled-in default, which is the cleanest reset for an app that's gotten itself wedged (Dock arrangement glitches, Finder column widths, Mail toolbar layout). For "reset to factory" of a single setting, delete just the key.
# Delete one key
defaults delete com.apple.dock autohide
# Reset the entire Dock
defaults delete com.apple.dock
killall Dock
# Reset Finder
defaults delete com.apple.finder
killall Finder
# Reset the global domain (very heavy-handed; affects every Cocoa app)
defaults delete -g
# Rename a key (rare — usually only needed when an app rebrands a setting)
defaults rename com.example.app OldKey NewKey
Output: (none — exits 0 on success)
find — searching across every domain
defaults find substring-matches across every key, every value, and every domain name in the database. It's the right tool when you remember a setting's word but not where it lives — instead of grepping defaults read (which is slow and noisy), point find at the keyword.
defaults find autohide
defaults find screencapture
defaults find DSDontWrite
defaults find AppleHighlightColor
Output (defaults find autohide):
Found 3 keys in domain 'com.apple.dock': {
"autohide" = 1;
"autohide-delay" = "0.5";
"autohide-time-modifier" = "0.5";
}
Found 1 keys in domain 'com.apple.menuextra.battery': {
"ShowPercent" = "YES";
}
Import and export — moving plists
defaults export <domain> <path> writes a domain to an XML plist file; defaults import <domain> <path> reads one back in. Use them to copy a fully-configured app's preferences from one machine to another (Terminal profiles, iTerm2 settings, Karabiner-Elements bindings) without trying to reverse-engineer dozens of individual keys.
# Export Dock prefs to ~/dotfiles
defaults export com.apple.dock ~/dotfiles/macos/com.apple.dock.plist
# Or to stdout
defaults export com.apple.dock -
# Re-import on a new machine
defaults import com.apple.dock ~/dotfiles/macos/com.apple.dock.plist
killall Dock
Output: (none — exits 0 on success)
The exported XML is human-readable and diff-friendly:
<?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>autohide</key>
<true/>
<key>autohide-delay</key>
<real>0.0</real>
<key>orientation</key>
<string>bottom</string>
<key>tilesize</key>
<integer>48</integer>
</dict>
</plist>
Discovering undocumented keys via plist diffing
Most macOS hidden settings aren't documented anywhere — you have to find them. The reliable technique is to capture the plist before changing a setting in System Settings, change it, capture it again, and diff. The delta is the key (and value type) you'd write in a script.
# 1. Snapshot the Dock plist before changing anything
defaults read com.apple.dock > /tmp/dock-before.txt
# 2. Open System Settings, toggle "Automatically hide and show the Dock"
open "x-apple.systempreferences:com.apple.preference.dock"
# 3. Snapshot again
defaults read com.apple.dock > /tmp/dock-after.txt
# 4. Diff to spot the changed key
diff /tmp/dock-before.txt /tmp/dock-after.txt
Output:
3c3
< autohide = 0;
---
> autohide = 1;
For domains stored as binary plists, plutil -p is friendlier than defaults read because it always prints quoted, JSON-style output that diffs cleanly:
plutil -p ~/Library/Preferences/com.apple.dock.plist > /tmp/before.txt
# change a setting…
plutil -p ~/Library/Preferences/com.apple.dock.plist > /tmp/after.txt
diff /tmp/before.txt /tmp/after.txt
Output: (none — exits 0 on success)
Common tweaks — the curated shortlist
The settings below cover what most developers want to flip on a fresh install. Each block ends with the killall needed to apply it.
Dock
# Auto-hide the Dock with no delay
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock autohide-delay -float 0
defaults write com.apple.dock autohide-time-modifier -float 0.4
# Icon size
defaults write com.apple.dock tilesize -int 36
# Disable magnification
defaults write com.apple.dock magnification -bool false
# Minimize windows into their app icon (not a separate Dock tile)
defaults write com.apple.dock minimize-to-application -bool true
# Don't show "recent applications" section
defaults write com.apple.dock show-recents -bool false
# Position
defaults write com.apple.dock orientation -string left # bottom | left | right
killall Dock
Output: (none — exits 0 on success)
Finder
# Show hidden files
defaults write com.apple.finder AppleShowAllFiles -bool true
# Show every file extension
defaults write NSGlobalDomain AppleShowAllExtensions -bool true
# Show path bar and status bar
defaults write com.apple.finder ShowPathbar -bool true
defaults write com.apple.finder ShowStatusBar -bool true
# Use column view by default
defaults write com.apple.finder FXPreferredViewStyle -string "clmv"
# Default new windows to ~/Downloads
defaults write com.apple.finder NewWindowTarget -string "PfLo"
defaults write com.apple.finder NewWindowTargetPath -string "file:///Users/alice/Downloads/"
# Disable the "are you sure you want to open?" prompt for downloads
defaults write com.apple.LaunchServices LSQuarantine -bool false
# Don't write .DS_Store on network shares
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
# Show ~/Library
chflags nohidden ~/Library
killall Finder
Output: (none — exits 0 on success)
Screencapture
# Save to ~/Pictures/Screenshots
mkdir -p ~/Pictures/Screenshots
defaults write com.apple.screencapture location -string "~/Pictures/Screenshots"
# Filename format
defaults write com.apple.screencapture name -string "screenshot"
# PNG instead of the default — also jpg, gif, pdf, tiff
defaults write com.apple.screencapture type -string "png"
# Strip the drop shadow on window captures
defaults write com.apple.screencapture disable-shadow -bool true
# Hide the floating thumbnail
defaults write com.apple.screencapture show-thumbnail -bool false
killall SystemUIServer
Output: (none — exits 0 on success)
Keyboard
# Fast key repeat (system minimum is 15 for InitialKeyRepeat, 2 for KeyRepeat)
defaults write NSGlobalDomain InitialKeyRepeat -int 15
defaults write NSGlobalDomain KeyRepeat -int 2
# Disable press-and-hold for accented characters (re-enables key-repeat in vim)
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
# Disable smart quotes / dashes in editors
defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false
# Logout/login to apply
Output: (none — exits 0 on success)
Trackpad and mouse
# Enable tap to click
defaults write com.apple.AppleMultitouchTrackpad Clicking -bool true
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
# Disable natural scrolling (Linux/Windows-style)
defaults write NSGlobalDomain com.apple.swipescrolldirection -bool false
# Three-finger drag (older macOS)
defaults write com.apple.AppleMultitouchTrackpad TrackpadThreeFingerDrag -bool true
# Tracking speed
defaults write NSGlobalDomain com.apple.trackpad.scaling -float 1.5
defaults write NSGlobalDomain com.apple.mouse.scaling -float 1.5
Output: (none — exits 0 on success)
Lock screen and screensaver
# Require password immediately after sleep/screensaver
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
# Screensaver settings live per-host
defaults -currentHost write com.apple.screensaver idleTime -int 300
Output: (none — exits 0 on success)
Menu bar and clock
# Show seconds in the clock
defaults write com.apple.menuextra.clock DateFormat -string "EEE MMM d h:mm:ss a"
# Show battery percentage
defaults write com.apple.menuextra.battery ShowPercent -string "YES"
killall SystemUIServer
Output: (none — exits 0 on success)
Safari
# Show full URL in the address bar (instead of just the domain)
defaults write com.apple.Safari ShowFullURLInSmartSearchField -bool true
# Show the develop menu
defaults write com.apple.Safari IncludeDevelopMenu -bool true
defaults write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool true
defaults write com.apple.Safari "com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled" -bool true
# Disable auto-fill of credit cards
defaults write com.apple.Safari AutoFillCreditCardData -bool false
Output: (none — exits 0 on success)
TextEdit
# Default to plain text
defaults write com.apple.TextEdit RichText -int 0
# UTF-8 file encoding
defaults write com.apple.TextEdit PlainTextEncoding -int 4
defaults write com.apple.TextEdit PlainTextEncodingForWrite -int 4
Output: (none — exits 0 on success)
Common pitfalls
- Wrong type silently dropped —
defaults write com.apple.dock autohide truestores the string"true". Always include-bool,-int,-string, etc. Domain ... does not exist— the app has never been launched, so its plist isn't on disk. Launch the app once, quit, then write.- Setting won't stick after restart — modern macOS Mobile Device Management (MDM) or Configuration Profiles can override user defaults. Check
/Library/Managed Preferences/and System Settings → Profiles. -currentHostmatters for some keys — screensaver password-delay, displays, and a handful of others live under~/Library/Preferences/ByHost. Use-currentHostfor both read and write or values won't match.killalldoesn't apply key-repeat rates — those keys require a full logout/login.- Editing the plist file directly with vim breaks it — modern plists are binary. Use
plutil -convert xml1to round-trip, or just usedefaults. defaults readis missing keys that exist —cfprefsdcaches in memory and may not have flushed yet. Rundefaults readagain after a one-second pause, orkillall cfprefsd.- Spaces in values need quoting —
defaults write com.apple.dock orientation -string "bottom left"is fine;defaults write com.apple.dock orientation -string bottom leftis two arguments. - System Settings overrides your write the next time it loads the pane — flip the setting once in the GUI to "commit" the surrounding plist, then re-apply your writes.
defaults importdoesn't merge — it replaces — the entire domain plist is overwritten. Export, edit, and re-import if you only want to change part of a domain.
Real-world recipes
One-shot bootstrap after a fresh install
This is the script most developers reach for after running the Homebrew bootstrap. Drop it into your dotfiles repo as bin/setup-macos.sh, source it once per fresh machine, and you get a Dock, Finder, screenshot setup, and keyboard config that matches your taste — no clicking through System Settings.
#!/usr/bin/env bash
set -euo pipefail
# Close any open System Settings pane to avoid overriding writes
osascript -e 'tell application "System Settings" to quit' || true
# Ask for sudo upfront and keep it alive
sudo -v
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
###############################################################################
# Dock
###############################################################################
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock autohide-delay -float 0
defaults write com.apple.dock autohide-time-modifier -float 0.4
defaults write com.apple.dock tilesize -int 36
defaults write com.apple.dock magnification -bool false
defaults write com.apple.dock show-recents -bool false
defaults write com.apple.dock mineffect -string scale
defaults write com.apple.dock minimize-to-application -bool true
###############################################################################
# Finder
###############################################################################
defaults write com.apple.finder AppleShowAllFiles -bool true
defaults write NSGlobalDomain AppleShowAllExtensions -bool true
defaults write com.apple.finder ShowPathbar -bool true
defaults write com.apple.finder ShowStatusBar -bool true
defaults write com.apple.finder FXPreferredViewStyle -string "clmv"
defaults write com.apple.finder NewWindowTarget -string "PfLo"
defaults write com.apple.finder NewWindowTargetPath -string "file:///Users/alice/Downloads/"
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write com.apple.LaunchServices LSQuarantine -bool false
chflags nohidden ~/Library
###############################################################################
# Screencapture
###############################################################################
mkdir -p ~/Pictures/Screenshots
defaults write com.apple.screencapture location -string "~/Pictures/Screenshots"
defaults write com.apple.screencapture type -string "png"
defaults write com.apple.screencapture disable-shadow -bool true
defaults write com.apple.screencapture show-thumbnail -bool false
###############################################################################
# Keyboard
###############################################################################
defaults write NSGlobalDomain InitialKeyRepeat -int 15
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false
###############################################################################
# Trackpad
###############################################################################
defaults write com.apple.AppleMultitouchTrackpad Clicking -bool true
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
defaults write NSGlobalDomain com.apple.swipescrolldirection -bool false
###############################################################################
# Menu bar
###############################################################################
defaults write com.apple.menuextra.clock DateFormat -string "EEE MMM d h:mm:ss a"
defaults write com.apple.menuextra.battery ShowPercent -string "YES"
###############################################################################
# Lock screen
###############################################################################
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
###############################################################################
# Apply
###############################################################################
for app in Dock Finder SystemUIServer NotificationCenter cfprefsd; do
killall "$app" >/dev/null 2>&1 || true
done
echo "Done. Some settings (key-repeat, accessibility) require logout."
Output:
Done. Some settings (key-repeat, accessibility) require logout.
Capture every change a GUI panel makes
When you're trying to capture exactly what System Settings writes for a feature, this script wraps the diffing technique.
#!/usr/bin/env bash
domain="$1"
[[ -z "$domain" ]] && { echo "usage: $0 <domain>"; exit 1; }
before=$(mktemp)
after=$(mktemp)
defaults read "$domain" > "$before" 2>/dev/null || true
read -rp "Now change the setting in System Settings and press Enter..."
defaults read "$domain" > "$after" 2>/dev/null || true
diff "$before" "$after"
rm -f "$before" "$after"
Output: (none — exits 0 on success)
Usage:
./capture-pref-change.sh com.apple.dock
Output:
Now change the setting in System Settings and press Enter...
3c3
< "show-recents" = 1;
---
> "show-recents" = 0;
Back up every preference plist into git
A common dotfiles pattern: snapshot every customised domain into version control so you can diff future changes against a known baseline.
#!/usr/bin/env bash
set -euo pipefail
dest=~/dotfiles/macos/prefs
mkdir -p "$dest"
domains=(
com.apple.dock
com.apple.finder
com.apple.screencapture
com.apple.menuextra.clock
com.apple.menuextra.battery
com.apple.Terminal
com.googlecode.iterm2
com.microsoft.VSCode
)
for d in "${domains[@]}"; do
defaults export "$d" "$dest/$d.plist"
plutil -convert xml1 "$dest/$d.plist"
done
cd ~/dotfiles && git add macos/prefs && git commit -m "Snapshot macOS prefs $(date +%F)"
Output: (none — exits 0 on success)
Restore preferences on a new machine
The matching restore script — point it at the same directory and every domain is re-imported.
#!/usr/bin/env bash
set -euo pipefail
src=~/dotfiles/macos/prefs
for f in "$src"/*.plist; do
domain=$(basename "$f" .plist)
defaults import "$domain" "$f"
done
for app in Dock Finder SystemUIServer; do
killall "$app" || true
done
Output: (none — exits 0 on success)
Add Spotlight to the menu bar's right side
Reorder the menu-bar extras by writing an ordered array.
defaults write com.apple.systemuiserver "NSStatusItem Visible com.apple.menuextra.spotlight" -bool true
defaults write com.apple.systemuiserver menuExtras -array \
"/System/Library/CoreServices/Menu Extras/Clock.menu" \
"/System/Library/CoreServices/Menu Extras/Battery.menu" \
"/System/Library/CoreServices/Menu Extras/AirPort.menu"
killall SystemUIServer
Output: (none — exits 0 on success)
Read a key that doesn't yet exist with a default
When scripting against a key that may or may not be set yet, defaults read exits non-zero. Combine with || echo for a default value.
autohide=$(defaults read com.apple.dock autohide 2>/dev/null || echo 0)
echo "Dock autohide: $autohide"
Output:
Dock autohide: 1
Toggle dark mode from a script
The global appearance switch is the boolean AppleInterfaceStyle under -g. The pattern is to delete the key for light mode and write Dark for dark mode — the absence of the key is what light mode looks like.
case "$1" in
dark)
defaults write -g AppleInterfaceStyle -string Dark
;;
light)
defaults delete -g AppleInterfaceStyle
;;
toggle)
if defaults read -g AppleInterfaceStyle 2>/dev/null | grep -q Dark; then
defaults delete -g AppleInterfaceStyle
else
defaults write -g AppleInterfaceStyle -string Dark
fi
;;
esac
# Force every app to re-read
osascript -e 'tell application "System Events" to tell appearance preferences to set dark mode to not dark mode' >/dev/null 2>&1 || killall cfprefsd
Output: (none — exits 0 on success)
Pin a specific folder to the Finder sidebar
Editing com.apple.sidebarlists directly is fragile; the canonical approach is mysides from Homebrew, but you can persist a workaround via defaults write com.apple.finder NewWindowTargetPath for the default-open folder.
brew install mysides
mysides add Documents file:///Users/alice/Documents/
mysides add Projects file:///Users/alice/Projects/
mysides list
Output:
Documents -> file:///Users/alice/Documents/
Projects -> file:///Users/alice/Projects/
Find every setting an app exposes
defaults read on a domain after launching the app and tweaking every option is a complete enumeration. Pipe it into a temp file and grep for likely names.
defaults read com.example.app > /tmp/example-prefs.txt
grep -iE 'enabled|interval|format|path' /tmp/example-prefs.txt
Output:
"AutoSyncEnabled" = 1;
"SyncIntervalSeconds" = 300;
"ExportFormat" = "json";
"LogFilePath" = "/Users/alice/Library/Logs/Example/app.log";
Related cheat sheets
- macos-cli — broader terminal reference
- homebrew — installs apps before you tweak their plists
- launchctl — schedule a script that flips a preference every morning
Sources
- ss64 — defaults — community-maintained reference enumerating every verb, type flag, and the upcoming "preferences domains only" deprecation notice.
- Apple — Edit property lists in Terminal — official guidance on
defaultsvsplutilfor plist manipulation. - macos-defaults.com — searchable catalog of curated
defaultstweaks with before/after screenshots. - Wikipedia — defaults (software) — historical context on the user-defaults system and the CFPreferences API it fronts.