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.

#macos#customization#prefsupdated 05-26-2026

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.

bash
which defaults
defaults help | head -5

Output:

text
/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.

bash
# 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.

bash
defaults [-currentHost | -host <hostname>] <verb> [<domain>] [<key>] [<value-with-type-flag>]

Output: (none — exits 0 on success)

Essential options

Verb / flagMeaning
readPrint one key, every key in a domain, or every domain
read-typePrint the type (boolean/integer/float/string/array/dict/data) of a key
writeSet or overwrite a key
deleteRemove a key or an entire domain
renameRename a key within a domain
domainsList every known domain
find <text>Substring search across all domains for keys, values, and domain names
import / exportBulk move a plist file in or out of the database
-g / NSGlobalDomainApply to system-wide defaults that every app inherits
-currentHostScope to this specific host (per-machine prefs, e.g. screen-saver password delay)
-bool true|falseBoolean value type
-int NInteger value type
-float N.NFloat 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 vAdd 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).

bash
# 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:

text
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:

bash
plutil -p ~/Library/Preferences/com.apple.dock.plist | head -20
plutil -convert xml1 -o - ~/Library/Preferences/com.apple.dock.plist | head -20

Output:

text
{
  "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.

bash
# 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:

text
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.

bash
defaults read com.apple.finder | grep -i sidebar
defaults read | grep -i 'screencapture'

Output:

text
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.

bash
# 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:

bash
defaults read-type com.apple.dock autohide
defaults read-type com.apple.dock tilesize
defaults read-type com.apple.finder NewWindowTargetPath

Output:

text
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.

bash
# 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 domainkillall targetNotes
com.apple.dockDockIncludes Mission Control gestures
com.apple.finderFinderHidden-file visibility, default sort order
com.apple.controlcenter / menu barSystemUIServerBattery percentage, Wi-Fi icon, sound icon
com.apple.screencaptureSystemUIServerScreenshot format, save location
com.apple.notificationcenteruiNotificationCenterBanner position, do-not-disturb
com.apple.universalaccesslogoutAccessibility tweaks
NSGlobalDomain key-repeatlogoutInitialKeyRepeat, 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.

bash
# 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.

bash
defaults find autohide
defaults find screencapture
defaults find DSDontWrite
defaults find AppleHighlightColor

Output (defaults find autohide):

text
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.

bash
# 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
<?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.

bash
# 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:

text
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:

bash
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

bash
# 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

bash
# 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

bash
# 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

bash
# 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

bash
# 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

bash
# 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)

bash
# 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

bash
# 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

bash
# 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

  1. Wrong type silently droppeddefaults write com.apple.dock autohide true stores the string "true". Always include -bool, -int, -string, etc.
  2. Domain ... does not exist — the app has never been launched, so its plist isn't on disk. Launch the app once, quit, then write.
  3. 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.
  4. -currentHost matters for some keys — screensaver password-delay, displays, and a handful of others live under ~/Library/Preferences/ByHost. Use -currentHost for both read and write or values won't match.
  5. killall doesn't apply key-repeat rates — those keys require a full logout/login.
  6. Editing the plist file directly with vim breaks it — modern plists are binary. Use plutil -convert xml1 to round-trip, or just use defaults.
  7. defaults read is missing keys that existcfprefsd caches in memory and may not have flushed yet. Run defaults read again after a one-second pause, or killall cfprefsd.
  8. Spaces in values need quotingdefaults write com.apple.dock orientation -string "bottom left" is fine; defaults write com.apple.dock orientation -string bottom left is two arguments.
  9. 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.
  10. defaults import doesn'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.

bash
#!/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:

text
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.

bash
#!/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:

bash
./capture-pref-change.sh com.apple.dock

Output:

text
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.

bash
#!/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.

bash
#!/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.

bash
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.

bash
autohide=$(defaults read com.apple.dock autohide 2>/dev/null || echo 0)
echo "Dock autohide: $autohide"

Output:

text
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.

bash
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.

bash
brew install mysides
mysides add Documents file:///Users/alice/Documents/
mysides add Projects  file:///Users/alice/Projects/
mysides list

Output:

text
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.

bash
defaults read com.example.app > /tmp/example-prefs.txt
grep -iE 'enabled|interval|format|path' /tmp/example-prefs.txt

Output:

text
"AutoSyncEnabled" = 1;
"SyncIntervalSeconds" = 300;
"ExportFormat" = "json";
"LogFilePath" = "/Users/alice/Library/Logs/Example/app.log";
  • 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 defaults vs plutil for plist manipulation.
  • macos-defaults.com — searchable catalog of curated defaults tweaks with before/after screenshots.
  • Wikipedia — defaults (software) — historical context on the user-defaults system and the CFPreferences API it fronts.