Tracking where settings are stored on macOS Jun 28 2019

In this post, I'll explain how to figure out where macOS stores specific preferences and how to modify them using the command line tool defaults. Knowing where the preferences are stored and how to manage them programmatically allows us to create scripts that will help us automate the setup of one or many computers. I think you'll find it useful.

I was sharing some code through Slack when I noticed that all my straight quotes (') were replaced by smart quotes (’). I felt cheated, I remember this happening in other apps before, but I've stopped myself in the past from fixing it because I don't want to run after any premature-optimization or automation. The simple solution is to go to Settings > Keyboard > Text and deselect the "Use smart quotes and dashes" checkbox. But how and where do macOS stores user's preferences?

The macOS defaults system

User preferences are stored in the defaults system of macOS. The users' defaults are structured by domains, and each application generally corresponds to one domain. The domain name is typically written in reverse internet domain style, for example, if I had an app called "timer" a likely domain name would be com.rderik.timer and under that domain, you'll find a plist with the user preferences.

What are plist files?

A properties file (plist) contains settings or preferences, these files are in XML format, they follow Apple's core Foundation DTD. For more Information check Apple's property list files documentation.

I knew I was looking for one plist where the defaults were being stored, so I used the command fs_usage to obtain a list of the file system activity. Using the following command:

1
$ sudo fs_usage -f filesys | grep plist

That will throw lots of lines to your screen, you could redirect it to a file and then study the file for possible candidates or try to be observant and see which file appears every time you change the setting. For me, the one that appeared every time I changed the setting was:

1
0:01:27  lstat64           /Users/rderik/Library/Preferences/.GlobalPreferences.plist

Most of the time the defaults would be located in the following directories:

1
2
3
4
5
~/Library/Preferences/com.domain.app.plist
~/Library/SyncedPreferences/com.domain.app.plist
# If the app is sandboxed
~/Library/Containers/com.domain.app/Data/Library/Preferences/com.domain.app.plist
~/Library/Containers/com.domain.app/Data/Library/SyncedPreferences/com.domain.app.plist

Now I had the plist file, I only needed to check the value I need to modify. But how do we edit a plist file? We could simply use any editor and open it (vim for example), but that is error prone and not recommended. You could use the command plist, and that would be correct if we were editing any plist file, but this time we are going to use the defaults command to interact with the defaults file.

Using defaults

First, we are going to read the whole domain and see what is stored there:

1
$ defaults read ~/Library/Preferences/.GlobalPreferences.plist

And you should have obtained a list of all your preferences, I found two promising variables:

1
2
    NSAutomaticDashSubstitutionEnabled = 1;
    NSAutomaticQuoteSubstitutionEnabled = 1;

Every time I switched the preference, these two values changed, the name has given them away, but I wanted to be sure. Now we can use the defaults command to modify them instead of clicking on System Preferences. Let's use the following commands:

1
2
$ defaults write ~/Library/Preferences/.GlobalPreferences.plist NSAutomaticDashSubstitutionEnabled -bool false
$ defaults write ~/Library/Preferences/.GlobalPreferences.plist NSAutomaticQuoteSubstitutionEnabled -bool false

And now I tried again to use straight quotes (') on Slack, and it worked! No automatic change.

What have we learned?

We learned that we can use fs_usage to listen for system calls and filesystem activity, this can be helpful to find other configurations written by any other programs and information on what system calls are being triggered. I would recommend having a look at the man page for the fs_usage command. Also, we saw how using the defaults command we have access to settings that might not be available on a graphical interface, again I would recommend checking the man page for more information.

We accessed the files directly, but if we know the domain that the application belongs to, we could access it only using the defaults command. For example, to access any global configuration you'll normally find them in the NSGlobalDomain domain, so instead of going directly to the file we could have used the following command and obtain the same result:

1
$ defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false

The defaults command gives us access to a lot of information. For example, you can see a list of all the available domains:

1
$ defaults domains

From that list you can explore the ones you find intriguing, you might find some interesting information.

1
$ defaults read NSGlobalDomain

Final thoughts

I think you can see how useful this method of setting preferences is, you now can create a script that will have all the preferences you require and use it to set any new computer or maybe if you are in charge of setting up all the machines at work now you have a way to automate it.

I hope this was useful, let me know if you have any questions or comments.

Related topics/notes of interest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Disable smart quotes
defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false

# Disable smart dashes
defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false

# Show hidden files on finder
defaults write com.apple.finder AppleShowAllFiles -bool true

# Thanks to @geerlingguy for this:
# Trackpad: map bottom right corner to right-click 
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadCornerSecondaryClick -int 2
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadRightClick -bool true
defaults -currentHost write NSGlobalDomain com.apple.trackpad.trackpadCornerClickBehavior -int 1
defaults -currentHost write NSGlobalDomain com.apple.trackpad.enableSecondaryClick -bool true

# Disable `.DS_Store` files when using Network drives
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true

# Don't show the list of users, ask for username and password on the login screen
# This doesn't work if you are using FileVault 2, FileVault only allows the list of users
# I spent too much time trying to figure it out. It is currently impossible to change it if you 
# are using FileVault
defaults write /Library/Preference/com.apple.loginwindow SHOWFULLNAME -bool true

** If you want to check what else I'm currently doing, be sure to follow me on twitter @rderik or subscribe to the newsletter. If you want to send me a direct message, you can send it to derik@rderik.com.