If you’ve ever done something like ls -la ~, then you must have noticed that your home directory is a mess of hidden files. This annoys the inner perfectionist in me, as I never have more than a few files in any folder. Everything is a nice tree structure.

To solve this problem, the XDG basedir specification exists. It is a collection guidelines that more or less specify where files should be. From a users perspective, files are one of the following:

  • Configuration files, which go into $HOME/.config. These files are essential to the user, but also possibly specific to the current system.
  • Cache files, which go into $HOME/.cache. These files are non-essential and should probably not be in back-ups.
  • Data files, which go into $HOME/.local/share. These files are just user data.
  • Runtime files, which are sort of a personal tempdir. Their location is not specified, but your system should fill it in in the XDG_RUNTIME_DIR environment variables. If it is not set, I default it to /tmp/$UID.

All these locations can be overwritten (which has its uses) but I’m already content with this. I then set out to clean up my home dir to this spec. With a combination of the Arch wiki and a bit of Googling, I managed to clean up most of it. This includes some interesting hacks, so bare with me.

The easy ones

Most modern applications already support the XDG basedir specification, and you can just move the legacy configuration to the new location. In my case, this included:

  • git (move ~/.gitconfig to ~/.config/git/config)
  • transmission (move ~/.transmission to ~/.config/transmission)
  • wireshark (move .wireshark to ~/.config/wireshark)
  • inkscape (move ~/.inkscape to ~/.config/inkscape)
  • latexmk (move ~/.latexmkrc to ~/.config/latexmk/latexmkrc)

The harder ones

After moving the files for the supported applications, we still have quite a few left. For these, I used a variety of environment variables and aliases to try to move the remaining files out of there.

tmux allows for specifying an alternate config file as a parameter with the -f flag. The alias tmux="tmux -f ~/.config/tmux/tmux.conf" allows to make this a little nicer. It also takes an enviroment variable TMUX_TEMPDIR, which dictates where the session storage should be. It defaults to /tmp, but I have it set to $XDG_RUNTIME_DIR/tmux. Note that it should exist as tmux won’t create it.

sqlite is similar, but not quite. In addition to a configuration file (the .sqliterc) it also considers an init file which is run before executing anything. We can use this init file as an alternative sqliterc, but it is an additional file and the original will still be sourced. My alias is sqlite3='sqlite3 -init "~/.config/sqlite3/sqliterc"'.

composer is a nice example for how your application can support the XDG basedir specification without having it as default. Normally, it stores everything in ~/.composer, but you can override this using environment variables. I use

export COMPOSER_HOME=~/.config/composer
export COMPOSER_CACHE_DIR=~/.cache/composer

wine needs a place to store its emulated windows storage, which can be overwritten with the environment variable WINEPREFIX. I have mine set to ~/.local/share/wine.

The weechat IRC client stores a lot into ~/.weechat, but has no separation between logs, config, and other data. You can however specify an alternative directory in the WEECHAT_HOME variable. I have mine set to ~/.config/weechat, but an argument could be made for ~/.local/share/weechat as well. I use it for config mainly so I prefer the former.

ipython and Jupyter notebooks store their history in ~/.ipython. You can move this with the environment variables IPYTHONDIR and JUPYTER_CONFIG_DIR. I have mine set to ~/.local/share/jupyter.

GIMP’s configuration is located in (in my case) ~/.gimp2.8, but you can relocate it using the GIMP2_DIRECTORY environment variable. Mine is set to ~/.config/gimp.

Github’s atom editor has no separation between data, config, or cache, but it does accept an ATOM_HOME environment variable. I have mine in ~/.config/atom.

I probably don’t use NodeJS the way it was intended to be used (don’t like Javascript that much, surprise?) but some tools I use are installed with npm. It uses an .npmrc file for its configuration, but you can override that with the NPM_CONFIG_USERCONFIG variable. After doing that, we can use our new config file to improve the storage of the location a little. My ~/.config/npm/npmrc is shown below. You probably need to update your path to correct for the moved binary directory.


Vagrant stores the data for its virtual machines in ~/.vagrant but you can change that using the VAGRANT_HOME directive. I prefer ~/.local/share/vagrant.

Rust’s package manager cargo uses ~/.cargo for its data but it contains mostly sources for the packages, so it is only cache. I override it with CARGO_HOME="~/.cache/cargo".

OpenSSL maintains its random state on disk, to use up less randomness from the system. It keeps it in ~/.rnd but you can move it with the RANDFILE environment. I moved it to $XDG_RUNTIME_DIR/rnd, since I don’t need/want to persist this random state between reboots.

The impossible ones

Not everything can be done nicely. The specification itself acknowledges that some legacy directories and files will always exist because too many programs depend on them. These are most notably ~/.ssh, ~/.pki, and ~/.gpg. Other programs have rejected the specification for one reason or another, and cannot be easily moved.

vim has no (non-invasive) solution to move its dotdir, but you can move your ~/.vimrc to ~/.vim/vimrc, which saves at least one directory entry.

zsh won’t have its files moved completely either, but you can specify the ZDOTDIR variable which changes where the rest of the configuration is located. You can use your zshenv to set it, which saves all but one entry in your home dir.

There are others, for which I have no reasonable solution at all, so if anyone has suggestions, I’m all ears. These are:

  • Audacity (.audacity-data)
  • Ruby/Bundler/Gem (.bundle, .gem)
  • Any IDEA IDE
  • CUPS
  • LightDM (stores selected desktop file in .dmrc)
  • Java (stores fonts in ~/.java/fonts)
  • Maven (stores local repository in .m2)
  • Firefox/Thunderbird (stores data in .mozilla and .thunderbird)
  • Netbeans
  • GNU parallels (mostly stores its temporaries in .parallel)
  • Nautilus (stores thumbnails in ~/.thumbnails)

Closing thoughts

I think I have spent a little too much time on this, but as it stands, I am happy with the results. Moving cache files to my actual cache directory has greatly reduced the size of my back-ups, and it is more neat in general.