Changing preferences isn’t so simple

It seems so simple: you discover that a hidden preference setting is controlled by a particular property list (.plist file), so why not go in and change it with a text editor? Or you want to reset an app’s preferences, so just trash its preferences file? Sadly, although those may work occasionally, in general they’re doomed to frustrate, as all the time macOS is working in secret to obstruct you.

The Defaults Server

The reason that directly manipulating preferences files is so frustratingly unsuccessful is that macOS manages them using a service, cfprefsd, the Defaults Server, which will always work against your direct actions. It’s far better instead to work with cfprefsd, using the command tool defaults.

There are occasional exceptions to this. Some apps manage their own preference settings rather than leaving them to cfprefsd. For a developer, it’s tempting, but only creates more work. So all Apple apps and the great majority of those from third-parties should be approached through official channels: change their Preferences, or use defaults. If you want a GUI app which has an impeccable track-record, look at Thomas Tempelmann’s free Prefs Editor, which works through the defaults command. There are several other apps like MacPilot that edit general preference settings, those of the Finder and other common apps.

plist03

Another good reason for working with cfprefsd rather than trying to beat it into submission is that it knows where all the preferences files are. By the time you’ve migrated across a few Macs and versions of Apple’s Mail app, your Home folder’s Library probably contains several different property list files containing the settings for different versions. Can you find which is the active one? Use defaults and it should save you that trouble and confusion.

The Finder is an excellent example of an app whose preferences should only ever be manipulated using the right tools. Because it’s running all the time, cfprefsd is sure to defeat you if you try to do anything direct.

defaults

To change preference settings using defaults, there are three bits of information you need:

  • The ID of the app, such as com.apple.Finder. For many, this is obvious, or can be checked using a tool such as Taccy. In most cases, if you can’t find out you can specify the name of the app instead of its ID using the option -app AppName, where AppName is the regular app name as shown, without the .app extension.
  • If you want to set or change a setting, the key for that individual setting.
  • If you want to set or change a setting, the value to pass for that key.

The latter two aren’t something you can readily guess. Commonly-used settings are often given in articles on the internet. Beware that older keys and values may have changed in more recent versions of that app, though. One way to confirm the current keys and values is to dump the app’s settings into a property list using a command like
defaults read com.vendor.appname > ~/Documents/appnamePrefs.plist
where com.vendor.appname is the app ID and the file path specifies a new file into which to dump them. This is a task that Prefs Editor does for you, in effect.

Changing or setting some preferences can be straightforward. For example, the Finder has a key in its preferences which determines the folder to open in a new Finder window, named NewWindowTargetPath. To inspect its current value, enter the command
defaults read com.apple.Finder NewWindowTargetPath
which should return the path as a URL string, such as
file:///Volumes/External1/Documents/0newDownloads/

To change that, enter a command such as
defaults write com.apple.Finder NewWindowTargetPath 'file:///Volumes/External1/Documents'
which changes that setting to open the folder specified by that URL. As you’re passing the URL as a string, to be saved as the value for the NewWindowTargetPath key, you put it in single quotes. If you then try opening a new window in the Finder, you’ll be frustrated to see that nothing has changed. To bring that change into effect, you need to restart the Finder from the Force Quit dialog, which makes it load its preferences again when it starts up.

This works fine when the key you’re setting appears at the top level of the dictionary in the property list, and when the value is a string. defaults does have options which you can use to set values of other types, include integers and floating point numbers. But it gets complicated when you want to change the value for a key which is embedded in another dictionary within the property list, or the value is something more complicated such as data.

If you merely want to reset part or all of an app’s preferences, then defaults is more straightforward. Removing a single setting runs like
defaults delete com.apple.Finder NewWindowTargetPath
When you restart or open that app next, that setting should be returned to its default so that you can get its value straight again. The equivalent of putting the whole preferences file into the Trash is even simpler, with
defaults delete com.apple.Finder

Before you do that, though, you might like to make notes on any important or tricky settings which you wish to restore once the app’s using its default settings again.

Problem preferences

There are two common problems that seem to occur with preference files: they can become corrupt, or acquire the wrong permissions. Deleting the file using defaults should address both of those, as the replacement written by the app shouldn’t be corrupted, and should have the correct permissions again. However, having to delete the whole file to fix it isn’t an ideal solution. Some apps let you reset your preferences to their ‘factory’ defaults, but unless that’s preceded by deleting the existing property list, it can leave the problem unfixed. I’m not aware of any app that offers to delete its preferences and create a new property list.

Preference domains and ByHost

Sometimes, even using defaults carefully can’t unstick a preference setting. What you probably never even dreamed is that preferences have an overriding hierarchy, and what may have happened is that the preference you tried to set was already being overridden by a Property List with a higher priority. If you can discover how to undo that, then you should still be able to change the setting that’s been driving you crazy.

Apple explains this in another of its invaluable documents which it has ‘retired’ without replacement: Preferences Programming Topics for Core Foundation. Preference Domains, one of the least understood parts of the whole system, are detailed here. In practice, this means there may be another Property List in ~/Library/Preferences/ByHost which is overriding that in ~/Library/Preferences. The property lists in that ByHost folder are named differently, such as com.apple.loginwindow.[UUID].plist. The UUID used corresponds to that of your Mac’s Hardware UUID, which can be found at the top level of System Information. You’ll probably find a load of old files there, whose UUIDs correspond to earlier Macs from which that Mac has copied across during Migration.

At its most long-winded, the defaults command can read something like
defaults -currentHost read -domain com.name.product keyname
where com.name.product is the app ID and keyname is the name of the key in its settings. Instead of specifying the -currentHost, you can omit that, or specify a -host hostname. Try this with a couple of global settings using -globalDomain and you’ll see what a difference it can make.

For example, on my Mac
defaults -currentHost read -globalDomain com.apple.trackpad.enableSecondaryClick
returns 1, as Trackpad Secondary Click is enabled, but
defaults read -globalDomain com.apple.trackpad.enableSecondaryClick
returns a missing key, value pair. This is because that global setting is stored in a preference file in the ByHosts folder, in this case the hidden .GlobalPreferences.[UUID].plist.

Conversely,
defaults -currentHost read -globalDomain NSQuitAlwaysKeepsWindows
returns a missing key, value pair, whereas
defaults read -globalDomain NSQuitAlwaysKeepsWindows
returns 1, as set in my General pane and stored in the hidden .GlobalPreferences.plist in my normal ~/Library/Preferences folder.

When you include -currentHost in a defaults command, it should make that setting in one of those property lists in the ByHosts folder, and won’t then be altered by commands which omit -currentHost, as those settings override those in the normal ~/Library/Preferences folder.

When you come across a setting which appears to be stuck, your first task is to identify its domain and the name of the key for that setting. One extensive listing of these is generated by writing all current settings to a text file using a command such as
defaults read > currentDefaults.text
and
defaults -currentHost read > currentDefaultsByHost.text

The first gives you megabytes of different settings across regular preferences, and the second is a much shorter listing of those specified in the files in the ByHost folder which override them. Be very careful how you store those dumps, as those settings contain all sorts of personal and sensitive information including software serial numbers.

Summary

  • Don’t trash preference files; instead use commands like defaults delete com.vendor.appname or defaults delete -app AppName as they’re far more likely to work.
  • To set or change preferences, use the Preferences/Settings feature in an app, the defaults command, or an app that works through cfprefsd, like Prefs Editor or MacPilot.
  • Even then preference domains can get the better of you.