The dotcrap file

Posted on December 31, 2018  -  7 min read

I decided to take a look at a problem that I’ve had for a while, and have just learned to ignore. It was one of those problems that one can generally live with, but it started to grate, and I had some time over the holidays so I devised a solution.

❌ The Problem

I hate clutter, especially hidden files (aka dotfiles) in my home directory (~).

I recently conducted a very scientific study via a Twitter poll, and (while I definitely lowballed my poll choices), it showed that most people (at least the primarily tech-y people in my Twitter feed) have well over 20 dotfiles in their home directory. Based on the replies I got, the average was a little over 80 dotfiles or dot directories.

✅ The Solution

A file that I can source in my shell that moves/clears all the crap out of my home directory. With this file, I now have 10 dotfiles or dot directories in my home directory. And shouldn’t have any more as long as my dotcrap file remains up to date. (If this issue can be resolved then I can drop two of those for docker/kubernetes config directories)

🤔 Tell me more

I like to tinker and configure things in my “dev environment”. This leads to many late nights of excitedly tweaking colours or making my terminal show me what WiFi network I’m connected to, or whether my bluetooth headphones are connected.

This leads to a lot of files, scattered around (usually) my home directory. I really don’t like this, for a few reasons:

  1. Portability - If I can keep track of where all of my setting files are, and especially whether I’ve edited them, I can shove them all in a git repo, and then track changes over time. This is totally possible with scattered files, but it’s certainly much more challenging.

  2. Reproducibility and backups - If I can convince every tool that I use that their configuration should live in ~/.config (for example), then backing up all my configuration files is simply a tar -zcf config.tar.gz ~.config away, and I know I can always return to that configuration state, and this becomes very challenging with scattered files.

  3. Aesthetics - I’m configuring with things anyway, I’d like my ~ directory to look pleasant, and this is impossible with scattered files.

🎨 Prior Art

For those of you who’ve used *nix systems and taken a look around some of the hidden files and directories in the ~ directory, you may have seen ~/.config, or maybe even ~/.local. (Or you may even know what’s coming!)

Feel free to look, I’ll wait.

Welcome back.

These two directories are often used as defaults for the XDG Base Directory Spec, created in 2003 over at freedesktop.org.

💻 Example XDG Base Directory environment variables

export XDG_CONFIG_HOME="$HOME"/.config
export XDG_CACHE_HOME="$HOME"/.local/cache
export XDG_DATA_HOME="$HOME"/.local/share
export XDG_RUNTIME_DIR="$HOME"/.local/tmp
export XDG_DOWNLOAD_DIR="$HOME"/tmp

You may be confused as to why the specification and variables contain “XDG”, instead of freedesktop, but this is because it was formerly known as “X Desktop Group”, so the name for the specification hasn’t changed, and many tools now use xdg as part of their name, but rest assured, it’s all freedesktop.org behind the scenes.

While not a formal standard (as freedesktop are not a formal standards body), this specification is remarkably widely followed in the *nix community, and if you set up some environment variables to point to the appropriate directories, you can see files being created in your $XDG_CONFIG_HOME directory among others.

Brilliant, right? The problem was pointed out in 2003, and everyone figured that it was better than no standard, and now everyone uses it, right?

Nope. That would be far too convenient.

There were essentially three types of responses to this specification:

  1. Some tools decided that they couldn’t move their config files, as they are (somewhat) low level tools, and lots of other tools have hardcoded their configuration locations, e.g. .cups (the Common UNIX Printing System), or .ssh (Secure SHell). This is a bit frustrating, but to be honest, if those broke inside another tool because a config file couldn’t be read, I’d probably be more annoyed than the annoyance of seeing them in the output of ls -a ~.

  2. Some tools used it “silently”, so if the environment variables were set according to the specification, then they’d put configs/caches/data etc in the appropriate user specified space. Aka they followed the specification, if they found the environment variables, they used them.

  3. Some tools, when confronted with the problem of supporting this not-really-a-standard, decided to allow moving the configuration file, but only via a custom environment variable that would allow people who were relying on location configuration for another program to search only for that environment variable. Which has its pros and cons.

It’s this third type of tool that we need to do some extra work for.

Enter, dotcrap

💩 The dotcrap file

So we now know what we have to do to clean up the ~ directory. We figure out what applications we are using, and move configs and caches and so on out, (most) often by setting an environment variable specific to the application, or perhaps by aliasing the command to a command with specific configuration or cache file options.

For a few tools we may need to write to extra files, but I’ll keep them out of the “source it and you’re done” file, so as not to clobber existing changes to those files.

For this project, I thankfully only need a few things:

  • A list of software with special environment variables to set to move their config or cache files
  • A list of software where using a separate config or cache file is taken care of with a cli flag/option.

I’ll need to do a few more things to make it work, but generally this is all we need to start.

Thankfully, the Arch Linux Wiki has an excellent page with this exact data!

This means it’s fairly straightforward to start running through the wiki page and following the instructions for each tool I’m interested in moving files out of my ~ directory.

For example:

if _has bundle; then
  # Move bundle config out of ~/.bundle
  export BUNDLE_USER_CONFIG="$XDG_CONFIG_HOME"/bundle
  export BUNDLE_USER_CACHE="$XDG_CACHE_HOME"/bundle
  export BUNDLE_USER_PLUGIN="$XDG_DATA_HOME"/bundle
fi

My _has function is a little tip I picked up somewhere on the internet, now lost to the sands of time, but it looks like this:

_has() {
  command -v $1>/dev/null 2>&1
}

😴 tl;dr

If you put all of that together, you too can make your own dotcrap file!

Or, if you’re lazy, you can use mine.

github.com/lewiscowper/dotcrap

PRs are accepted to add tools that you use. Perhaps I’ll use them in the future and would appreciate my configuration being kept out of my home directory.

Thanks for reading, if you got this far, and if you didn’t and just scrolled down to the bottom to check for a tl;dr. Well, you’re in the right place. Clone the repo and source the file, then you too can live free of dotfiles cluttering your home directory.