Keep $HOME clean with XDG Base Directories
Left to themselves, programs scatter ~/.thisrc and ~/.thatdir across your home directory. The XDG Base Directory Specification is the convention that fixes this: a small set of environment variables that tell well-behaved tools to keep their config, data, state, and cache in predictable, categorized directories instead of at the top of $HOME.
Dotfiles Pro sets those variables to their defaults for you, and this guide shows how to push individual tools the rest of the way.
What XDG defines
Four user-level roots, each with a default:
| Variable | Default | Holds |
|---|---|---|
XDG_CONFIG_HOME | ~/.config | config files |
XDG_DATA_HOME | ~/.local/share | data files |
XDG_STATE_HOME | ~/.local/state | logs, history, state |
XDG_CACHE_HOME | ~/.cache | disposable cache |
There is also XDG_RUNTIME_DIR (per-session sockets and pipes) and the system search paths XDG_CONFIG_DIRS / XDG_DATA_DIRS. Those are owned by the system, so you set the four user roots above and leave the rest alone.
Dotfiles Pro sets the defaults
The unix role sets the four roots in its shared unix_env environment, which it renders to ~/.profile.d/env.sh, each defaulted only when the session has not already set it:
# XDG Base Directory locations, defaulted to the spec values when the session has
# not already set them. User roots only; XDG_RUNTIME_DIR is owned by the system.
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"The ${VAR:-default} form respects a value your login session already provides, and XDG_RUNTIME_DIR is left untouched on purpose, since systemd owns it and a hand-set value breaks sockets, Wayland, and audio. Drop the four XDG_* keys from unix_env to opt out.
On its own this exports the defaults, which is the safe baseline. The win comes from pointing tools at these roots, next.
Move a tool to XDG
Tools fall into three groups:
Native. Many already read
XDG_CONFIG_HOMEand place themselves under~/.configwith no action from you (git, for one).Opt-in. Some go XDG only if you set an env var they look for. Point those at an XDG path in a
~/.profile.d/file, linked with thedotfilesrole so every shell sees it:bash# Tools that move out of $HOME only when you point them at an XDG location. Put # these in a ~/.profile.d file (link it with the dotfiles role) so every shell sees # them. Confirm each one against `xdg-ninja` on your machine first. export LESSHISTFILE="$XDG_STATE_HOME/less/history" export WGETRC="$XDG_CONFIG_HOME/wgetrc" export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker" export NODE_REPL_HISTORY="$XDG_STATE_HOME/node_repl_history" export GNUPGHOME="$XDG_DATA_HOME/gnupg"Hardcoded. A few simply write
~/.fooand cannot be moved. Leave them.
To find which of your tools are offenders and which knob each one needs, run xdg-ninja; it scans $HOME and prints the fix for each program it recognizes. Codify the ones worth moving as the env vars above, and your next apply carries them to every machine.
Moving an existing config
Setting one of these variables changes where a tool looks, so a config already sitting at ~/.foo is ignored until you move it to the new XDG path. On a fresh machine there is nothing to move; on an existing one, relocate the file once.
It already lines up with the roles
Using the defaults is safe because the built-in roles already write under these roots: ~/.config/git, ~/.config/starship.toml, ~/.config/gcloud, and the dotpro state under ~/.local/state. Exporting the defaults simply makes explicit what the roles already assume.
Two things to keep in mind:
~/.kubeis not an XDG path. kubectl predates the spec and keeps its config there; the roles drive it throughKUBECONFIG, so XDG does not touch it.- Relocating a root is advanced. If you point
XDG_CONFIG_HOMEsomewhere other than~/.config, the roles whose destination is configurable can follow (starship_config_path,git_configs_path,kubernetes_kubeseal_config_path, andCLOUDSDK_CONFIGfor gcloud), but a couple of hardcoded~/.configpaths will not. Keep the defaults unless you are ready to relocate those in lockstep.
Next steps
- unix role the shell framework and the
unix_envenvironment that exports these - dotfiles role link your own
~/.profile.d/env files into place - Configuration keep per-host variations in
host_vars