macOS dotfiles should not go in ~/Library/Application Support
53 points by hibachrach
53 points by hibachrach
This is missing a messy point in favor of AppSupport: its hard to support changing XDG_CONFIG_HOME
. macOS has no concept of a “login shell”, so you can’t override XDG env vars within your login scripts like ~/.zprofile
for apps that aren’t launched via a shell (including shell scripts launched directly via shebang, not in an interactive shell env, which is the major gotcha here).
For CLI apps this isn’t an issue since you’re executing them from a terminal context which likely loaded a non-login interactive profile script (~/.zshrc
). And any child processes are inheriting that environment. But due to historical… mistakes… all terminals on macOS also load login scripts for all non-login terminals too. Read this for some history on how messed up this is (no other platform behaves this way!): https://ghostty.org/docs/help/macos-login-shells
For GUI apps, this is an issue because GUI apps are launched via PID 1 which has not loaded any login scripts and has a bare environment. So you have to use launchd to manage the env vars: https://stackoverflow.com/a/588442
I build a terminal, which is kind of a hybrid GUI/CLI app: we have a GUI obviously, but lots of people also launch terminals via the CLI. And users of terminals tend to be highly technical so they’re more aware of XDG and want to use it. But they’re also so technical they often MOVE their XDG folders for reasons. But also a lot of people don’t care about this and I’ve found that “normie” macOS technical users do expect configs in ~/Library
. This is the perfect storm of nightmare. So we support both. Yay! (gouches eyes)
None of the above is hypothetical, we’ve had dozens of bug reports or Q&A posts on this topic on all sides…
I don’t think any of this refutes this post. I think its all very messy. But this is a point that I haven’t found documented anywhere and I discovered organically through my own app and it is common enough that I felt the need to share this and hopefully get it indexed or something.
I thought about this a lot when putting together Dotfiles matter!, my little webzone dedicated to encouraging application developers to support ~/.config
(with limited success - a lot of responses are from developers who believe their program is more important than other programs example) and decided to just go with Application Support. Recently I saw a macOS user talk about how they symlink ~/.config
to the Application Support directory, which seems harmless, and avoids the issue with login shells.
(edit: this was meant to be a standalone comment and not a reply to the venerable mitchellh)
a lot of responses are from developers who believe their program is more important than other programs
Would love a future desktop OS update that sandboxes these types of files somewhere and makes it impossible to put them elsewhere. No program is more important than others.
If the argument is “it’s hard to change XDG_CONFIG_HOME
”, I’d counter that by saying you can’t change ~/Library/Application Support
, so using XDG_CONFIG_HOME
on macOS is strictly more configurable no matter how hard it is.
But also, CLI tools on macOS are almost exclusively run via terminal emulators, which load login scripts and therefore make it easy to configure that. Any CLI tool that is run behind-the-scenes by GUI apps or the system, rather than from a terminal emulator, is almost certainly a tool that does not have user config and therefore won’t be using ~/.config
anyway. Any GUI app that does want to run CLI tools that have user config are almost certainly going to want to do by either manually loading env vars from a login shell, or by wrapping the invocation of the CLI tool with a login shell, but apps that need this are extremely rare.
Your app is a terminal, which is an app. It does have a CLI interface, but that’s a CLI interface to an app. CLI interfaces like this are the sole exception to the expectation to use XDG, a CLI interface to an app should be sharing config/data with the app and therefore use whatever the app does. Another example here is xcodebuild
, which is a CLI interface to Xcode and therefore shares any caches or other data with Xcode.app.
The fourth category here is GUI interfaces for CLI tools, so things like MacVim.app, or gitk
, and these do the opposite of the last category, they do whatever the CLI tool does.
I am sympathetic to the argument that a tool on macOS could respect any config in ~/Library/Application Support
even if they prefer to use the XDG location, though I generally only see this strategy used by tools that started with ~/Library/Application Support
and later switched to XDG after user pressure, and I don’t think it makes much sense to do otherwise. As a general rule, CLI tools on macOS should follow XDG, especially if they do so on other unix-like systems, and any tool that diverges from this should have a really good argument for why (and that should generally be that it’s a CLI interface/companion to a GUI app).
If the argument is “it’s hard to change XDG_CONFIG_HOME”, I’d counter that by saying you can’t change ~/Library/Application Support, so using XDG_CONFIG_HOME on macOS is strictly more configurable no matter how hard it is.
I don’t know if that’s true (I’m not arguing it, I just don’t know if its true), I only know that there have been multiple bugs related to macOS and moving XDG_CONFIG_HOME
and no one has ever complained to me about the path to Application Support. I suspect XDG users expect to be able to move it, and AppSupport people don’t. But that’s a problem.
We started with XDG and added Application Support under user pressure, so we did the opposite of what you noted. There were a diverse set of use cases, ranging from macOS exclusive users who wanted to keep all configuration in one spot, to people who back that folder up, to people who use it as a way to do Mac-specific config for cross-platform work.
I don’t know, I don’t use it. But there was enough demand that I said “sure, why not” and ever since then the complaints have ceased. Ghostty has supported XDG since beginning so that’s always been there, but I still periodically (most recently last week in Discord!) get the “Ghostty isn’t respecting my XDG dir” bug report, with the answer being “the app can’t reasonably load your login shell config in the startup path, use launchd.” I’d say on average I’ve gotten this once a month or so.
And to be clear, I’m not arguing for either direction. I just wanted to point out another point of complexity in the decision making process. I’m not at all advocating for either direction, I think its too nuanced to say.
One bit of nuance with your app is that it’s a GUI app, but configuration is done by editing a file rather than using an in-app settings screen. Users aren’t normally expected to ever interact with the ~/Library/Application Support
folder themselves. I can see the argument for “I want it in Application Support because I back up that folder”, but to that I’d say “you should also back up ~/.config”.
Coincidentally was triaging GitHub issues/discussions and it happened again today lol. I swear I wasn’t looking for this, I was just going in order of oldest-to-newest unresolved discussions. https://github.com/ghostty-org/ghostty/discussions/5135#discussioncomment-14228291 It is the cache dir and not the config dir, but yeah.
lead us, mitchell (づ ᴗ _ᴗ)づ♡
if you tell us we are all wrong and should use - ~/.config
as openbsd kids are lost - we’ll follow (ㅅ´ ˘ `)
This reads as an overindexing on ‘standard’. Standards like the XDG Base Directory Specification are standardizing behavior across Linux, which needs it because it has no natural authority to describe how the userspace is supposed to feel. It is supposed to coordinate application files, command-line and windowed application alike, across Linux DEs; treating it as a standardization of command-line tools across OSes is a misconception. (It’s especially offensive when this is argued/executed on Windows - the whole point of the specification’s design is to hide these folders, but they never bother setting the hidden flag!)
Your program should probably not disagree with Bash and Vim and Git about where configuration files are supposed to go!
Notably, that is not where Bash and Vim and Git put anything. They don’t put their files in the XDG dirs and (I believe) they do not respect the XDG vars (except Vim as of last year). If you expect config files in a folder specifically named ~/.config
, it is not because you looked at what Git did. macOS, and its default tools, don’t put anything in ~/.config
that I know of.
Standards like the XDG Base Directory Specification are standardizing behavior across Linux, which needs it because it has no natural authority to describe how the userspace is supposed to feel.
Well, from specifications.freedesktop.org:
Freedesktop.org is a project to work on interoperability and shared base technology for free-software desktop environments for the X Window System (X11) and Wayland on Linux and other Unix-like operating systems.
So it’s “Unix-like operating systems”, not only Linux (and quite frankly, none of these *nix programs check their environment to see if they’re running on a BSD or a Solaris or something and put stuff in ~
instead of ~/.config
if they are, this has simply become the de facto standard across all Unices, it doesn’t really matter whether freedesktop.org are intending it for the benefit of Linux; we can all benefit).
As far as I’m concerned, the UNIX layer of macOS is no less native than the Aqua layer; see my comment above about that.
Notably, that is not where Bash and Vim and Git put anything. They don’t put their files in the XDG dirs and (I believe) they do not respect the XDG vars (except Vim as of last year).
True, but they put them in ~
; even on macOS, they don’t put them in ~/Library/Application Support
.
If you expect config files in a folder specifically named
~/.config
, it is not because you looked at what Git did.
I think you put too much stock in the exact examples. The author probably should have checked, but the steelman of their point is that *nix tools on macOS don’t generally change config locations, so this is surprising. As they say, “because that’s what almost every other program does”.
macOS, and its default tools, don’t put anything in
~/.config
that I know of.
macOS doesn’t patch its userland to put things in ~/Library/Application Support
, so all its “default tools” that are part of the *nix environment work the same as they do outside of macOS.
macOS is its own unique OS. It has some POSIX-compatible underpinnings below the graphical/desktop level, but it completely diverged from there. Putting macOS in the same group as X11-lineage desktops is almost like calling Windows a VAX-like OS.
The old low-level parts don’t make macOS follow the rest of the Unix philosophy. Apple today seems to actively dislike the Unix philosophy. They’ve replaced or abstracted away everything they could with their own alternatives. If you think systemd is a not a Unix way of doing things — it’s already a heavily Unixified XML-less alternative of Apple’s launchd
, which inspired it. The rest of macOS is only more anti-Unix.
You see ~
as the familiar Unix thing, but ~/Library
doesn’t correspond to any standard Unix concept. Apple tells you to use URL.applicationSupportDirectory
. It’s a subclass of an NSURL
object you get from an API call. This is like taking XDG’s string paths in env vars, and trying to do the exact opposite in every way.
Putting macOS in the same group as X11-lineage desktops is almost like calling Windows a VAX-like OS.
I didn’t put it in the same group as X11-lineage desktops. That doesn’t make it not a UNIX.
The old low-level parts don’t make macOS follow the rest of the Unix philosophy.
ls
doesn’t even follow the UNIX philosophy.
You see
~
as the familiar Unix thing, but~/Library
doesn’t correspond to any standard Unix concept.
They’re both familiar to me. I’m a happy user of macOS, and prefer the Mac way of doing things oftentimes. I also am a happy user of UNIX APIs and userland, on macOS and off macOS.
If I wanted my software to do things “the Mac way” — the UNIX way is a Mac way, but let’s assume it’s somehow secondary even post-OS X — I could install a graphical Aqua software package any time I want. If I install a UNIX package, particularly a command line one, and it writes to ~/Library/Application Support
, that’s a near-dealbreaker for me, and I’d be immediately searching for alternatives.
Apple tells you to use
URL.applicationSupportDirectory
.
Where does Apple “tell you” to use URL.applicationSupportDirectory
for all macOS software?
Apple themselves maintain their own forks of many UNIX software packages that it bundles w/ macOS, and none of them use URL.applicationSupportDirectory
or some low-level alternative that points to ~/Library/Application Support/$BUNDLE_ID
.
I realised while responding to another user that the text I quoted from specifications.freedesktop.org specifies X and Wayland, so I now realise what you mean by placing macOS in the same group as X11-lineage desktops.
However, I’ll quote what I said in that comment when I realised:
Considering it’s agnostic between X and Wayland, I’d think that command line UNIX apps on macOS also count, since it’s a Unix-like OS running a Unix-like package under a Unix-like shell.
There’s simply no reason to behave as a Unix app following Unix ways of doing things (i.e. text-based config file, running under a UNIX shell, using UNIX APIs w/ the odd Mac-specific non-Cocoa API, etc.) in everything but where you store your config and data. If I’m installing a Unix app from the Unix ecosystem, I want a Unix app.
~/Library
is — clearly, from Apple’s documentation — not intended for Unix packages, and not used by the Unix packages bundled by default with macOS, so simply use the usual directories that are used on other Unices.
Your point overall is taken, but just to nitpick one of your examples: Git has supported dropping config into ~/.config/git/
, even on macOS, for many years now.
https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration
This doesn’t detract from your comment, but note that even now, git doesn’t seem to respect XDG_CONFIG_HOME; it seems to just hard code ~/.config/git/config as an alternate config file path, if that changelog is to be believed. So it still doesn’t respect any XDG config location specification.
Took a few seconds from my day to confirm Git respects XDG_CONFIG_HOME: https://github.com/git/git/blob/1fa68948c3d76328236cac73d2adf33c905bd8e3/path.h#L204
command-line tools do not have any app-specific data because they are not apps
Great little rhetorical game but command line applications are applications, also known as apps. Programmers have been calling apps apps since as early as 1981 (and I’m pretty sure I’ve seen old UNIX documents or notes or videos or something calling applications apps). This entire blog post is rhetorical cope and the only good argument is the argument from consistency, which I think is weak, because the consistency means doing it wrong on macOS. Apple has features like Time Machine which I think does backups, and may handle backing up application data differently to cache. You can imagine any number of Apple-specific tooling that has the right to trash ~/.config
if it has to, because Apple doesn’t acknowledge the directory. Let’s focus on supporting platforms as the platform developers intend, and users can choose the platform they like the UX of most.
Your argument is based on assumption that macOS cares about Unix, and you end up trying to impose foreign concepts on it, using foreign terminology as a justification. From perspective of a macOS user this is super frustrating — I keep seeing people who can’t believe that macOS isn’t merely a BSD with a pretty theme and a working webcam driver.
The reality is that macOS doesn’t care about Unix, its conventions, nor its terminology. “App” in Apple’s world has a very specific well-defined meaning. There’s literally a bundle type using an .app
extension (with “com.apple.application-bundle” UTI). A bundle type basically a file type, except that macOS bundles are not files. UTI is a MIME type of Apple’s world.
macOS apps are distinct from what Apple calls “Unix Executable File” (“public.unix-executable” UTI). Bare executables don’t integrate with any of the GUI for apps, and usually just launch the Terminal app.
Apps must have an Info.plist
, which defines a BundleIdentifier
, which is then used to access other app-specific functionality, including NSUserDefaults
subsystem that is used instead of dotfiles.
There’s a lot of macOS-specific functionality attached to what Apple calls “apps”, and Apple is very consistent about it.
Your argument is based on assumption that macOS cares about Unix
Given that macOS is certified UNIX and none of the other platforms under discussion are, I’m not sure how you’d make that claim.
Because:
Apple doesn’t recommend the Unix® APIs to developers. They have their preferred non-Unix replacements/alternatives for almost everything, and it’s not just Swift. Even for low-level C APIs they have their own CoreFoundation, which is more inspired by classic MacOS than POSIX.
Apple cares way more about intellectual property liability than Unix. When GNU switched to GPL3, Apple just left all GNU software without updates since 2007. SCO Group used to make a lot of fart noises about Unix® rip-offs, and it was likely easier for Apple to get a legit Unix® certificate than to give SCO any ideas.
Apple used to care about technology outside of App Store. They’ve had Xserve servers (with Apache!). They’ve had half-assed optional limited X11 support until 2012. They even had their own JVM and supported Java as a first-class language for Cocoa! But now they care about Java as much as they care about Unix. It’s all either already discontinued or barely alive. See also how much Apple cares about OpenGL and OpenCL.
Apple needs to keep the parts of the OS that POSIX.1-2001 touches in a working condition anyway, but that doesn’t mean they need to care about anything in the broad world of unix-likes. XDG, LSB are outside of UNIX 03. Apple doesn’t do package management like unix-likes. macOS never shared anything desktop-related with the rest of Linux-likes. X11/Wayland are completely alien to macOS, which is based on PDF’s graphics model and a completely custom GUI stack. GTK and Qt always sucked on macOS. There’s no dbus. There’s nothing at all from freedesktop. There’s way more XML in macOS than any “Unix”.
Great little rhetorical game but command line applications are applications, also known as apps. Programmers have been calling apps apps since as early as 1981 (and I’m pretty sure I’ve seen old UNIX documents or notes or videos or something calling applications apps).
Why did you just completely ignore this whole block?:
A couple screens down, the same page says that /bin “[c]ontains essential command-line binaries”, so we can be sure the authors aren’t conflating apps and command-line tools.
[…]
The next paragraph makes it very clear that
~/Library/Application Support
is for apps only:By convention, all of these items should be put in a subdirectory whose name matches the bundle identifier of the app. For example, if your app is named
MyApp
and has the bundle identifiercom.example.MyApp
, you would put your app’s user-specific data files and resources in the~/Library/Application Support/com.example.MyApp/
directory. Your app is responsible for creating this directory as needed.Command-line tools do not have a bundle identifier, including many command-line tools shipped with macOS by Apple (such as
ls
orvim
). And even though Apple feels very comfortable shipping command-line tools that behave in a subtly different manner from their equivalents on other modern Unix-descendent operating systems, the macOS variants of bash, zsh, git, and vim all look for their configuration files in the same place:~/.config
[ed: well,~
, but the point stands]. Unless your tool is installed in/Applications
, there’s no reason for its configuration to live in~/Library/Application Support
.
How other people use “apps” is irrelevant if Apple’s documentation makes a distinction between apps and command line binaries. Take your own advice:
Let’s focus on supporting platforms as the platform developers intend,
Trying to ignore the distinction that Apple makes between “apps” and “command line binaries” in their documentation is itself a rhetorical game and goes against your claimed goal of “supporting platforms as [their] developers intend”.
You can only do that if you interpret their documentation in the manner they intend, yet you ignored the part where the author went to great pains to make it obvious the documentation intends these guidelines for non-CLI apps.
consistency means doing it wrong on macOS. Apple has features like Time Machine which I think does backups, and may handle backing up application data differently to cache.
No, it doesn’t mean doing it wrong.
The foundational UNIX layer of macOS is as native as the higher Aqua layer. UNIX software should behave as on any other UNIX platform on macOS. You can make a case that X apps are less native because Aqua is meant to supplant it and X is only there for compatibility purposes, but there’s no non-graphical layer to macOS that isn’t just UNIX.
So, while calling out Time Machine is a good point to bring up, it doesn’t have any bearing on whether it’s wrong or not for CLI apps, which all run on a UNIX layer on macOS, to behave in a way consistent with other UNIX CLI apps, and moreover, consistent with all other macOS CLI apps — which are the same thing, macOS CLI apps are UNIX CLI apps except that they might use non-graphical but macOS-exclusive APIs — including those bundled by default in macOS.
At that point, if Apple’s Time Machine doesn’t handle $XDG_CACHE_DIR
, that could be either argued to be a bug in Time Machine, or out of scope, since $XDG_CACHE_DIR
can be overridden by the user in an rc file on a per-shell basis, which Time Machine can’t always handle, and may even differ on different shells, therefore it’s up to the tech-savvy command line user to simply add $XDG_CACHE_DIR
to Time Machine’s exclusion list.
Even if not handled, the worst that could happen here is caches being backed up.
Honestly, if Apple set $XDG_CACHE_DIR
tomorrow to default to ~/Library/Caches
, or a subdirectory, I wouldn’t even be mad.
But I think for them to set $XDG_CONFIG_DIR
to ~/Library/Application Support
or ~/Library/Preferences
or something wouldn’t really add much, if any, benefit and would be annoying for people who manage their dotfiles cross-platform, for example, or even macOS-exclusive dotfiles in many cases, since now macOS version would affect things, even if it’s just upgrading their dotfiles and never having to touch their old ones again.
I guess it would at least make all XDG-compliant apps be consistent.
You can imagine any number of Apple-specific tooling that has the right to trash
~/.config
if it has to, because Apple doesn’t acknowledge the directory.
You can imagine any number of absurd scenarios. Apple acknowledges the user’s home directory. It’s theirs. What the hell are you talking about? Do you really think Apple might have tools that trash files in a subfolder within the home folder that it doesn’t explicitly recognise?
If anything, since, as you said, Apple doesn’t recognise it, it’d simply inherit the rules for ~
itself, i.e. be treated the same as any other file that belongs to the user (belongs in the sense of it being a file within their home directory; that’s clearly user data that you have no right to touch).
users can choose the platform they like the UX of most.
I like the UX of a UNIX foundation with an Aqua graphical layer.
And quite frankly, I’m not beholden to a single platform that I like the UX of the most, I can use multiple platforms as I please.
In this case, I like my UNIX apps to behave the same on macOS as they do on other platforms I use them on so I can version control them and easily share my config across platforms. I’m not version-controlling my ~/Library/Application Support
folder.
I understand there are parts of macOS that supplant equivalents on UNIX, like launchd
which is often used for both Aqua and non-Aqua apps, and cron
only remains for compatibility and UNIX or POSIX compliance or whatever, but that’s not equivalent to this case.
For one, launchd
is literally the init process, so of course it’s applicable to all types of macOS software, which is why Apple themselves use it for both Aqua and non-Aqua software. ~/Library/Application Support
is not used by Apple for non-Aqua software, which means it’s non-native to use it, and is certainly not in line with the platform guidelines.
Secondly, it’s literally documented that launchd
subsumes cron
in the manpage (as UNIXy as it gets):
(Darwin note: Although cron(8) and crontab(5) are officially supported under Darwin, their functionality has been absorbed into launchd(8), which provides a more flexible way of automatically executing commands. See launchd.plist(5) for more information.)
Moreover, cron
has limitations which make it unsuitable for many cases, even for UNIXy software, and given its replacement launchd
is at a foundational layer of the system, it makes sense to use it when available, even for non-Aqua software, it’s simply suitable for both types of software and cron
is often unsuitable even for non-Aqua software.
With ~/Library/Application Support
, the unsuitability goes the other way around; using it over simply sticking with standard XDG directories makes it, for example, a pain to version control (more than it already is with all the software that sticks things in ~
instead of XDG directories) so as to be able to easily sync configuration cross-platform.
And that’s not such a big deal with Aqua software anyway, which is often configured using the GUI instead of text-based human-readable config DSLs. They’re two completely different configuration philosophies, and mixing them causes real issues.
It’s entirely possible we could have lived in a universe where ~/Library/Application Support
is intended for both and accommodates for that, but we don’t.
Mmm, “app” has a different connotation in macOS, I agree with the OP, CLI tools like docker
or whatever aren’t really apps in the macOS sense.
You can imagine any number of Apple-specific tooling that has the right to trash ~/.config if it has to, because Apple doesn’t acknowledge the directory.
This specific speculation on your part demonstrates a pretty fundamental unfamiliarity with the macOS environment and its constraints. It leave me wondering the source of your apparent confidence in speaking authoritatively about macOS best practices.
I had the same reaction reading the “apps” argument, but the author goes on to make a pretty convincing case that Apple really did mean GUI apps when they used the word.
And this comes from the far earlier convention of listing applications of a product in the Business to Business marketing world. Someone selling a computer might say it has a blazing fast 2 mhz processor and 512 bytes of RAM but the potential buyer would retort “Okay, but what are the applications?”
I would counter this with “one of my pet peeves is when CLI tools don’t have the ability to tell you where your config file is”. I don’t really care what directory it’s in, I just care that I can find it. If I can do nvim $(some-tool config path)
I’m happy.
It’s truly the worst when distros change config file paths and every distro uses a different path. There are weirdly many tools where the question “where does this tool look for its config files?” has no simple answer and depends on the distro (and maybe even distro version).
agree with you, with a note, I use linux distros time from time and it’s so good to find all configs under XDG_CONFIG_HOME folder. I don’t think it was the case several years ago
I agree it’s a wrong place for it, but also macOS is not a freedesktop.org distro. XDG is trying to map foreign concepts from Linux/BSD desktops to macOS. macOS doesn’t have good answers for them, because it’s so different that some of the questions don’t even make sense.
It’s hard to explain to people used to generic “unix” platforms just how weird and deep the mismatch is. macOS has some POSIX compatibility, bits of NeXTStep, and even a Unix® certification from 2003, but it’s as much Apple’s Mac OS, doing Apple’s own things, Apple’s way (sometimes ignoring other OSes conventions so hard it feels like Apple is doing that out of spite).
macOS is app-centric and API-centric. XDG comes from the everything-is-a-file world and asks for directories for things that are API calls on macOS. There isn’t a directory for API calls. This is like asking where do you store your fork()
calls? Is XDG_FORKS_DIR
is /proc/self/
or /dev/mem/
?
macOS has NSUserDefaults
APIs for storing settings, but dotfiles don’t go where NSUserDefaults
stores its plist
s. These APIs aren’t suitable for command-line applications, because in Apple’s lala-land standalone command-line applications aren’t a thing either (they’re all supposed to live inside app bundles).
macOS is not a freedesktop.org distro.
What does it mean to be a freedesktop.org distro? specifications.freedesktop.org says:
macOS has some POSIX compatibility, bits of NeXTStep, and even a Unix® certification from 2003
They renew their certification every release, although apparently, the version of the SUS they adhere to is from 2004 (and requires disabling SIP and a bunch of other stuff).
Either way, it’s a Unix-like, and Linux itself, the canonical target platform for freedesktop.org, also diverges from strict UNIX.
Freedesktop.org is a project to work on interoperability and shared base technology for free-software desktop environments for the X Window System (X11) and Wayland on Linux and other Unix-like operating systems.
Considering it’s agnostic between X and Wayland, I’d think that command line UNIX apps on macOS also count, since it’s a Unix-like OS running a Unix-like package under a Unix-like shell.
There’s simply no reason to behave as a Unix app following Unix ways of doing things (i.e. text-based config file, running under a UNIX shell, using UNIX APIs w/ the odd Mac-specific non-Cocoa API, etc.) in everything but where you store your config and data. If I’m installing a Unix app from the Unix ecosystem, I want a Unix app.
~/Library
is — clearly, from Apple’s documentation — not intended for Unix packages, and not used by the Unix packages bundled by default with macOS, so simply use the usual directories that are used on other Unices.
macOS is app-centric and API-centric. XDG comes from the everything-is-a-file world and asks for directories for things that are API calls on macOS. There isn’t a directory for API calls. This is like asking where do you store your
fork()
calls? IsXDG_FORKS_DIR
is/proc/self/
or/dev/mem/
?
Which XDG base directories are API calls instead of directories? People are talking about the XDG Base Directory Specification.
UNIX packages on macOS have always stored their data and config in the same directories as off macOS. That’s always been native macOS behaviour that fits in with the rest of the command line macOS ecosystem. The natural progression is to adopt the XDG BD Spec, and many have, and they continue to not distinguish between macOS vs. other Unices. Great!
Now, we have this new crop of apps trying too hard to be native, and ironically ending up with non-native behaviour that users of that ecosystem simply don’t expect, and AFAICT, for the most part, don’t want.
These APIs aren’t suitable for command-line applications, because in Apple’s lala-land standalone command-line applications aren’t a thing either (they’re all supposed to live inside app bundles).
macOS comes with a ton of Mac-specific command-line applications that don’t live inside app bundles. Do you actually use macOS?
Which XDG base directories are API calls instead of directories?
XDG_CONFIG_HOME
/XDG_CONFIG_DIRS
make no sense on macOS, because applications are not supposed to be writing arbitrary “user-specific configuration files”. macOS rejects the idea of users editing text-based configuration files anywhere for any purpose. There is user-specific configuration, but conceptually it’s a database of objects managed through APIs. The canonical “path” to the config is not a filesystem path, but a Bundle Identifier used to open the database, and a key path used to query it (there’s defaults
command to access the database).
In many ways macOS is as different from Unix OSes as Windows. Windows registry has the same problem — it has paths, it has per-user config, but it’s not a filesystem directory. It doesn’t make sense to point XDG_CONFIG_HOME
to the directory where Windows stores the registry.
On macOS there is no valid location for dotfiles, because configuration is not supposed to be stored in dotfiles.
I agree that ~/Library/Application Support
is a wrong dir for config. I just want to highlight that the problem is deeper. It’s not which directory is right, but that macOS is not working the way XDG assumes, and XDG is a foreign standard for a different family of operating systems.
You can port Unix tools to macOS, and make them use Unix conventions in the way that Unix users expect, but that’s not making things macOS-native, it’s emulating Unix-native things on macOS.
macOS comes with a ton of Mac-specific command-line applications that don’t live inside app bundles
It’s not that simple. macOS has a mix of CLI tools with various levels of integration with Apple’s way of doing things. There are some classic Unix commands that just have to be there (some kept up to date, some bitrotting). Mac-specific utils (like tmutil
) often connect to user’s session and reuse bundles of other system applications or XPC services (this is sometimes visible when you try to run the “CLI” tools via SSH, and find that they don’t work without osascript
trick, because they can’t connect to user’s session). Apple-made dev tools are usually tied (in a convoluted way) to Xcode’s bundle or SDK root. Some non-Apple utils are customized to use Apple’s APIs like Keychain.
There are thousands of utilities built over decades, so there are exceptions to everything, but to me generally Apple uses their non-Unix APIs, defaults subsystem, XPC services, and bundles/frameworks when they have a choice. They leave tools like git
in its pure Unix form w/dotfiles when the tools have already been established outside of Apple’s ecosystem.
Do you actually use macOS?
It’s been my primary desktop and dev target since Panther.
~
seems fine by me. I don’t see why macOS should follow XDG any more than Debian should adopt ~/Library/Application Support
. (after all, what’s the leading UNIX desktop?) The “app” distinction makes me shrug: running $ emacs
or Emacs.app
should hardly load different files. I don’t mind using ~
for, I don’t know, legacy apps, but if Emacs were developed today with Mac in mind, I’d lean towards ~/Library
.
I see where they’re coming from, but… I’m unconvinced.
I commented on this ~6 months ago:
I version control my dotfiles, and I have a pet peeve of some cross-platform(!) *nixy terminal software that decides to use folders in
~/Library
for macOS, in a misguided attempt to be more ‘native’ to the platform or something.macOS is a certified UNIX, and a comfortable UNIX environment at that, there’s no need for a *nixy terminal program that uses all of macOS’ *nixy affordances and almost entirely works on its UNIX compatibility to try to be more native on macOS by putting its configuration somewhere I have to symlink them.
It’d be more native to just stick with the *nix conventions entirely instead of half-*nix–half-Aqua conventions. The UNIX side is just as much (modern) macOS as the Aqua side, even if it’s not the (especially) unique part about macOS. In fact, the Maccy parts are built on the UNIX foundation, the UNIXy stuff isn’t some separate compatibility layer on top of a Maccy foundation.
As for configuring XDG directories to be under
~/Library
as a user, I’ve considered it before, but I think it’s better to maintain a separation between *nixy configuration which tends to have edited by hand, version controlled, and have their own config DSLs or use some simple config language, and configuration of macOS Aqua apps, which are machine-generated and -edited plist (i.e. XML [ed: or binary]) files that aren’t version controlled.I just checked and I have an
mpv.plist
andio.mpv.plist
in~/Library/Preferences
(I’m guessing one formpv
run from a terminal and the other for the mpv macOS application bundle). I was curious if the GUI mpv bundle had created anmpv
directory in~/Library/Application Support
, like a lot of apps do for themselves, and it hadn’t, but if it had, and I’d setXDG_CONFIG_DIR="$HOME/Library/Application Support"
, the$XDG_CONFIG_DIR/mpv
directory would have been an interesting conflict between the GUI bundle.
What a coincidence: I ran into this with nushell a few days ago and found it baffling. The docs appear to discuss ways of overriding or changing the values of $nu.default-config-dir
but to be honest I cannot tell from that doc how to actually do it. I like to version my dotfiles in a repo and I use a little script to symlink them where they’re actually supposed to go. I suppose the simple thing is to symlink into ~/Library/Application Support
instead of ~/.config
, but why on earth would you make something so weird and difficult?
This is also a pet peeve of mine, mostly because I have contorted my system to more closely resemble Linux than macOS (fun fact: did you know that DBus can be run over launchd?). I think a reasonable compromise is to use XDG_CONFIG_HOME
if defined and otherwise fall back to ~/Library
—this of course makes usage of XDG environment variables annoying with GUI apps (which are typically not launched from the shell), but if a user is willing to write a wrapper executable that sets XDG_CONFIG_HOME
, clearly that user does not want to use ~/Library
.
I think a reasonable compromise is to use
XDG_CONFIG_HOME
if defined and otherwise fall back to~/Library
I think that’s what some of those libraries for figuring out config directories do. Personally, I think being consistent with other Unix apps should be the default.
As I said in another comment:
There’s simply no reason to behave as a Unix app following Unix ways of doing things (i.e. text-based config file, running under a UNIX shell, using UNIX APIs w/ the odd Mac-specific non-Cocoa API, etc.) in everything but where you store your config and data. If I’m installing a Unix app from the Unix ecosystem, I want a Unix app.
~/Library
is — clearly, from Apple’s documentation — not intended for Unix packages, and not used by the Unix packages bundled by default with macOS, so simply use the usual directories that are used on other Unices.
I dislike the macos AppSupport folders, but I would expect to find config there for many apps, whether a CLI or GUI app, unless I specifically opt in to configuring the apps to use XDG folders.
I’ve thought about this in the past a bit too after seeing a bunch of discussion on the various rust crates that access these directories and seeing them generally agree to not use XDG on macOS / Windows.
I came to the conclusion that the fix for this is to add a new environment variable that is used as a flag for this purpose to the XDG spec. I don’t think the presence of XDG_CONFIG_HOME or similar is enough to trigger this behavior change. I think it has to be explicit.
This feels right. I agree with the take that macOS users expect command line programs to use command line standard folders. It’s not like all the usual daemons had their configs moved out of /etc. A curious exception is launchd, but something about its configs being plists squares it for me.
The bigger point is that not only do you not know where the user’s OS puts config, you shouldn’t know. In Go you just ask the xdg
package to get your config path, and it will tell you. That will be the Right Thing for this particular system, and it’s not for you to have opinions about it or to make different decisions.
I don’t really think it’s possible to fix it in mac unless apple or some guru comes up with a good suggestion
I am using homebrew simply because there are a lot of tools that support brew install X
and all sort of troubleshooting details around it. I have friends who use macports
which is supposed to be better but in fact makes it harder to support software on macos, you need brew,macport, bash script and tons of other instructions on how to setup your tool on macos, a disaster to maintain.
The point I am leading to, I don’t really know where my configs are, it’s a mess. Homebrew moved everything under /opt/homebrew recently and it was a big shock to macos users. Now I don’t have to add sudo every time I used brew, what a relief! Put it under ~/Library
and I’ll never find it there because I go into that folder only to delete mess when I am out of space, apps write all sort of things under it.
Steve wanted us to forget about disk and folders and here we are, it’s such a mess I don’t really care anymore.