A tool for managing macOS defaults declaratively via YAML files.
brew install dsully/tap/macos-defaults
cargo install --git https://github.com/dsully/macos-defaults
# To stdout:
macos-defaults dump -d com.apple.Dock
# To a file:
macos-defaults dump -d com.apple.Dock dock.yaml
# Global domain
macos-defaults dump -g
# From a single YAML file:
macos-defaults apply dock.yaml
# From a directory with YAML files & debug logging:
macos-defaults apply -vvv ~/.config/macos-defaults/
macos-defaults completions [bash|fish|zsh] > ~/.config/fish/completions/macos-defaults.fish
See macos-defaults --help
for more details.
---
# This will be printed to stdout.
description: Contacts
# Use the currentHost hardware UUID to find the correct plist file.
# https://apple.stackexchange.com/questions/353528/what-is-currenthost-for-in-defaults
current_host: false
# Send a SIGTERM to one or more processes if any defaults were changed.
kill: ["Contacts", "cfprefsd"]
# A nested map of plist domains to key/value pairs to set.
data:
# Show first name
# 1 = before last name
# 2 = after last name
NSGlobalDomain:
NSPersonNameDefaultDisplayNameOrder: 1
# Sort by
com.apple.AddressBook:
ABNameSortingFormat: "sortingFirstName sortingLastName"
# vCard format
# false = 3.0
# true = 2.1
ABUse21vCardFormat: false
# Enable private me vCard
ABPrivateVCardFieldsEnabled: false
# Export notes in vCards
ABIncludeNotesInVCard: true
# Export photos in vCards
ABIncludePhotosInVCard: true
---
# Multiple yaml docs in single file.
description: Dock
kill: ["Dock"]
data:
# Automatically hide and show the Dock
com.apple.dock:
autohide: true
You may also use full paths to .plist
files instead of domain names. This is the only way to set values in /Library/Preferences/.
By default, the YAML will be merged against existing domains.
For example, the following config will leave any other keys on DesktopViewSettings:IconViewSettings
untouched:
data:
com.apple.finder:
DesktopViewSettings:
IconViewSettings:
labelOnBottom: false # item info on right
iconSize: 80.0
This can be overridden by adding the key "!"
to a dict, which will delete any keys which are not specified. For example, the following config will delete all properties on the com.apple.finder domain except for DesktopViewSettings, and likewise, all properties on IconViewSettings
except those specified.
data:
com.apple.finder:
"!": {} # overwrite!
DesktopViewSettings:
IconViewSettings:
"!": {} # overwrite!
labelOnBottom: false # item info on right
iconSize: 80.0
This feature has the potential to erase important settings, so exercise caution. Running macos-defaults apply
creates a backup of each modified plist at, for example, ~/Library/Preferences/com.apple.finder.plist.prev
.
If an array contains the element "..."
, it will be replaced by the contents of the existing array. Arrays are treated like sets, so elements which already exist will not be added.
For example, the following config:
data:
org.my.test:
aDict:
};
anArray: ["foo", "...", "bar"]
- Prepend
"foo"
toaDict:anArray
, if it doesn't already contain"foo"
. - Append
"bar"
toaDict:anArray
, if it doesn't already contain"bar"
.
See my dotfiles repository.
YAML is not a format I prefer, but out of common formats it unfortunately had the most properties I wanted.
-
JSON doesn't have comments and is overly verbose (JSONC/JSON5 is not common)
-
XML: No.
-
INI is too limited.
-
TOML is overly verbose and is surprisingly not that easy to work with in Rust. Deeply nested maps are poorly handled.
-
KDL is nice, but document oriented & needs struct annotations. Derive is implemented in the 3rd party Knuffle crate.
-
RON is Rust specific, so editor support isn't there.
-
KCL, CUE, HCL, too high level & not appropriate for the task.
So YAML it is.
This tool was heavily inspired by and uses code from up-rs