A small, dependency-free Python CLI to snapshot and restore macOS preferences managed via the defaults system.
The idea is simple:
- Maintain a curated list of preferences you care about in
macOS-config-template.json. - Run
--storeto capture the current machine values into a config JSON. - Run
--restorelater to apply that snapshot back (including deleting keys that were absent at capture time).
This is meant for:
- setting up a new Mac the same way every time
- keeping multiple machines consistent
- experimenting with changes and being able to revert
Does:
- Reads and writes macOS preferences via
defaults. - Supports user-scoped and currentHost-scoped domains.
- Captures types using
defaults export(plists) and stores the values as JSON. - On restore, if a key was missing when captured, it is deleted (true revert-to-absent).
Does not:
- Change settings that are not controlled by
defaults. - Run privileged operations (
sudo), modify system files, or run destructive cleanup commands.
macos-config-manager.py- CLI entry pointmacOS-config-template.json- the maintained template (what to track)macOS-my-config.json- suggested local snapshot name (ignored by git)completions/- optional static shell completion scripts
- macOS
- Python 3
No third-party Python packages are required.
- Make the script executable
chmod +x macos-config-manager.py- Create a snapshot (store current values)
./macos-config-manager.py --store --template macOS-config-template.json --output macOS-my-config.json --forceAt this point you can treat macOS-my-config.json as:
- a backup of your current state
- a desired-state file you can edit and re-apply
- Preview a restore (prints commands only)
./macos-config-manager.py --restore --input macOS-my-config.json --dry-run- Restore for real
./macos-config-manager.py --restore --input macOS-my-config.json- Restore and restart common affected apps/services
./macos-config-manager.py --restore --input macOS-my-config.json --restart-appsThe template defines what to track. Each entry is identified by:
domain- the preference domain, e.g.com.apple.finderorNSGlobalDomainname- the preference key, e.g.ShowStatusBarscope-userorcurrentHosttype-bool,int,float,string,array,dict(orinfer)comment- human-readable description of what the setting controls
Example:
{
"domain": "com.apple.menuextra.battery",
"name": "ShowPercent",
"scope": "user",
"type": "string",
"comment": "Battery menu extra: show battery percentage"
}When you run --store, each template entry becomes a stored entry with:
present- whether the key existed at capture timevalue- the captured value (ornullif absent)
On --restore:
present: truewrites the stored value back.present: falsedeletes the key.
This is intentional: it lets you accurately revert to "the setting did not exist" rather than guessing a default.
--store uses defaults export and parses the plist, so it can preserve types.
bool,int,float,stringround-trip cleanly.arrayanddictare supported, with the practical limitation that restore only supports scalar array items and scalar dict values (bool/int/float/string).
Static completion scripts are provided in completions/.
Zsh (project-local):
Add to ~/.zshrc:
fpath=(/path/to/this/repo/completions $fpath)
autoload -U compinit && compinitBash:
Add to ~/.bashrc (or ~/.bash_profile on macOS bash setups):
source /path/to/this/repo/completions/macos-config-manager.bashNote: completion triggers for the command name (e.g. macos-config-manager.py on PATH). If you run it as ./macos-config-manager.py, completion may not trigger unless you add an alias.
defaultschanges are real system changes; prefer--dry-runfirst.- Some preferences may take effect only after restarting the relevant app.
--restart-appsis best-effort; it useskillalland ignores missing/legacy process names.- Always review and curate
macOS-config-template.jsonbefore using it broadly.
Edit macOS-config-template.json directly.
To add a new key, add a new object to options:
{
"domain": "com.apple.finder",
"name": "ShowPathbar",
"scope": "user",
"type": "bool",
"comment": "Finder: show path bar"
}Then re-run --store to capture the current value.
The initial list of macOS preferences was inspired by:
- https://gist.github.com/sickcodes/912973b2153b0738ff97621cde4c2bb5#file-macos-md
- https://github.com/sickcodes
This repository refactors that idea into a template-driven snapshot/restore tool.
This project is licensed under the MIT License.