Tune macOS with system defaults
Most of the macOS settings you would otherwise click through in System Settings are plain preference keys you can write from the command line with defaults write. The macos role applies the ones you list in macos_defaults on every apply, so a fresh Mac comes up tuned the way you like without a manual pass through the settings panes.
This is the same "settings, not files" idea the rest of Dotfiles Pro follows: the role writes only the keys you declare and leaves every other preference alone, so a macOS update keeps its own improved defaults instead of fighting a file you committed years ago. This guide is a recipe book of high-value keys to get you started.
How the role applies defaults
macos_defaults is a list of entries, each a {domain, key, type, value} mapping that the role hands to community.general.osx_defaults:
domainis the preference domain,NSGlobalDomainfor system-wide keys or an app's bundle domain such ascom.apple.finder.keyandvalueare the preference itself.typeis one ofbool,int,float,string, orarray, matching the flag you would pass todefaults write(-bool,-int, and so on).
The list is not a deep-merged dict, so to change a value you redeclare its key in your own macos_defaults, and to stop managing one you drop its entry (the preference keeps whatever value it last had). Because osx_defaults only writes when the stored value differs, re-applying an unchanged list is a no-op.
Apple does not publish a central catalogue of these keys. The community site macos-defaults.com documents the commonly tweaked ones, and the macos role reference covers the small set the role ships by default.
The recipe book
Each group below is a set of entries for one domain or theme. Pick the ones you want and combine their entries under a single macos_defaults list; the complete block at the end collects them all.
Keyboard
| Key | Value | Effect |
|---|---|---|
KeyRepeat | 2 | Faster repeat once a key is held (lower is faster) |
InitialKeyRepeat | 15 | Shorter delay before a held key starts repeating |
ApplePressAndHoldEnabled | false | Repeat the held key instead of showing the accent menu |
AppleKeyboardUIMode | 3 | Full keyboard access, so Tab reaches every control in a dialog |
All four live in NSGlobalDomain.
Finder
| Key | Domain | Value | Effect |
|---|---|---|---|
AppleShowAllExtensions | NSGlobalDomain | true | Always show file extensions, so a .pdf.app can't pose as a document |
ShowPathbar | com.apple.finder | true | Show the path bar at the bottom of every window |
ShowStatusBar | com.apple.finder | true | Show the status bar with item counts and free space |
FXPreferredViewStyle | com.apple.finder | Nlsv | Default new windows to list view (Nlsv) |
_FXShowPosixPathInTitle | com.apple.finder | true | Put the full POSIX path in the window title |
Screenshots
| Key | Value | Effect |
|---|---|---|
type | png | Pin the format (PNG is the default; use jpg for smaller files) |
disable-shadow | true | Drop the window shadow from window screenshots |
Both live in com.apple.screencapture. To also change where screenshots land, add a location key whose value is an existing absolute directory, such as a Screenshots folder in your home directory.
Dock
| Key | Value | Effect |
|---|---|---|
tilesize | 48 | Icon size in points |
autohide | true | Hide the Dock until you push the pointer at it |
autohide-delay | 0 | Show it with no delay (this key is a float) |
show-recents | false | Don't append recently used apps |
mru-spaces | false | Stop reordering Spaces by most recent use |
All live in com.apple.dock and need a killall Dock to repaint. These tune how the Dock behaves rather than which apps it holds.
Save and print panels
| Key | Value | Effect |
|---|---|---|
NSNavPanelExpandedStateForSaveMode | true | Open the Save sheet expanded |
NSNavPanelExpandedStateForSaveMode2 | true | Same, for the newer sheet variant |
PMPrintingExpandedStateForPrint | true | Open the Print sheet expanded |
PMPrintingExpandedStateForPrint2 | true | Same, for the newer sheet variant |
All live in NSGlobalDomain. Apps read both the old and new key, so set each pair together.
Security
| Key | Value | Effect |
|---|---|---|
askForPassword | 1 | Require the password after sleep or screensaver |
askForPasswordDelay | 0 | Require it immediately, with no grace period |
Both live in com.apple.screensaver.
Put it together
A starting macos_defaults with every recipe above:
macos_defaults:
# Keyboard: fast key repeat, repeat held keys instead of the accent menu,
# and full keyboard access in dialogs
- { domain: NSGlobalDomain, key: KeyRepeat, type: int, value: 2 }
- { domain: NSGlobalDomain, key: InitialKeyRepeat, type: int, value: 15 }
- { domain: NSGlobalDomain, key: ApplePressAndHoldEnabled, type: bool, value: false }
- { domain: NSGlobalDomain, key: AppleKeyboardUIMode, type: int, value: 3 }
# Finder: show every extension, the path and status bars, and default to list view
- { domain: NSGlobalDomain, key: AppleShowAllExtensions, type: bool, value: true }
- { domain: com.apple.finder, key: ShowPathbar, type: bool, value: true }
- { domain: com.apple.finder, key: ShowStatusBar, type: bool, value: true }
- { domain: com.apple.finder, key: FXPreferredViewStyle, type: string, value: Nlsv }
- { domain: com.apple.finder, key: _FXShowPosixPathInTitle, type: bool, value: true }
# Screenshots: save as PNG without the drop shadow
- { domain: com.apple.screencapture, key: type, type: string, value: png }
- { domain: com.apple.screencapture, key: disable-shadow, type: bool, value: true }
# Dock: smaller icons, auto-hide with no delay, and don't reshuffle Spaces
- { domain: com.apple.dock, key: tilesize, type: int, value: 48 }
- { domain: com.apple.dock, key: autohide, type: bool, value: true }
- { domain: com.apple.dock, key: autohide-delay, type: float, value: 0 }
- { domain: com.apple.dock, key: show-recents, type: bool, value: false }
- { domain: com.apple.dock, key: mru-spaces, type: bool, value: false }
# Save and print panels: always expanded
- { domain: NSGlobalDomain, key: NSNavPanelExpandedStateForSaveMode, type: bool, value: true }
- { domain: NSGlobalDomain, key: NSNavPanelExpandedStateForSaveMode2, type: bool, value: true }
- { domain: NSGlobalDomain, key: PMPrintingExpandedStateForPrint, type: bool, value: true }
- { domain: NSGlobalDomain, key: PMPrintingExpandedStateForPrint2, type: bool, value: true }
# Security: require the password immediately after sleep or screensaver
- { domain: com.apple.screensaver, key: askForPassword, type: int, value: 1 }
- { domain: com.apple.screensaver, key: askForPasswordDelay, type: int, value: 0 }Find more keys
To capture a setting you changed by hand, read it back before you commit it, so you store the exact domain, key, and type:
# Read the current value of a key before you manage it
defaults read com.apple.dock tilesize
# Dump every key a domain stores, to discover what an app exposes
defaults read com.apple.finder
# List every preference domain on the machine
defaults domains
# Some keys only take effect once the owning app restarts
killall Finder
killall Dock
killall SystemUIServerA few things to keep in mind:
- Many keys take effect only after the owning app restarts or you log back in. The role writes the preference but does not restart apps for you, so run
killall Finder/killall Dock(or just log out and back in) to see the change. - Match the
typeto what the app expects. Writing astringwhere the app reads aboolleaves the setting ignored, with no error. - Key names drift between macOS releases, and a handful sit behind System Integrity Protection or a privacy permission that
defaults writecannot set. Verify on the version you run rather than trusting an old gist.
Apply just the defaults
The defaults run under the config tag, so once the role is in your playbook you can re-apply preferences without reinstalling packages:
dotpro tags config # re-apply configuration only, no package installs
ansible-playbook playbook.yaml --tags config --diff # or preview every config change first--diff previews each key the run would change, which is the safe way to try a new recipe before you keep it.
Next steps
- macOS role the full reference, including the Dock and Mac App Store
- Configuration per-host vars, so one Mac can carry a different recipe
- One repo for Windows, Ubuntu, and macOS keep these macOS keys beside your Linux setup in a single repo
- Alternatives how this compares to pushing settings through MDM