Am I XDG Yet?

What

Historically, this serves as a reminder of how to make $HOME (mostly) clutter-free, to manage dotfiles easier.

Nowadays I use this index to track the XDG support status of programs that I use, hence the title.

TLDR

Show, don’t tell:

# Use the XDG Base Directory Specification
# TLDR: https://xdgbasedirectoryspecification.com/
# Spec: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_STATE_HOME="$HOME/.local/state"
export XDG_CACHE_HOME="$HOME/.cache"

Most solutions are available in XDG Base Directory entry on Arch Wiki. You can also use xdg-ninja for the initial setup.

Who

Many softwares live long enough to arrogantly ignore XDG and get away with it. A recent example is xdg-basedir enhancement on Bugzilla, which finally got closed in Firefox 147, 21 years later.

  • ADB & Android Studio (would look for ADB_VENDOR_KEYS as well, but ~/.android would ALWAYS get generated…)
  • Bash
  • Cargo (CARGO_HOME means config + data, silly idea)
  • Chromium (fixed in 146)
    • endless CEF/Electron/NW.js/QtWebEngine projects…
  • Firefox (fixed in 147 and ESR 153)
  • Lean (same as Cargo)
  • MAME
  • .NET (old solution and runtime discussion)
  • nim, nimble
  • Ollama (just models, config & ssh key are not supported)
  • Python (PYTHON_HISTORY works for Python 3.13+)
  • Ren’Py (RENPY_PATH_TO_SAVES works on Ren’Py 7.5+ games)
  • R
  • Vim (fully supported since 9.2.0019. Simply add source $VIMRUNTIME/xdg.vim in your vimrc.)
  • VSCode and VSCodium (--extensions-dir is not enough as .vscode-oss/argv.json is still needed)
  • Zsh (via $ZDOTDIR)

How

Python

⚠️ Warning

OUTDATED! For Python 3.13+, simply set PYTHON_HISTORY should suffice.

  1. Add these in $HOME/.profile(.bashrc or .zshrc works too):

    export PYTHONPYCACHEPREFIX="$XDG_CACHE_HOME"/python
    export PYTHONUSERBASE="$XDG_DATA_HOME"/python
    export PYTHONSTARTUP="$XDG_CONFIG_HOME"/python/pythonrc
    
  2. Create "$XDG_CONFIG_HOME"/python/pythonrc:

    import readline
    readline.write_history_file = lambda *args: None
    
  3. Source $HOME/.profile by exec zsh, done.

R

While R is configurable, my setup makes it a bit hard to follow XDG base dir spec:

  • R is installed via mise-r, aka. asdf-r, and located in a weird place
$ which R
~/.local/share/mise/shims/R
$ mise which Rscript
~/.local/share/mise/installs/r/latest/bin/Rscript
  • I use arf as R console, installed via mise GitHub backend
  • I have custom libPaths to avoid unnecessary reinstall between minor/patch updates.
  • Makevars set to cache/speedup library compilation
arf

R 4.6.1> R.home()
[1] "~/.local/share/mise/installs/r/4.6.1/lib64/R"

R 4.6.1> .libPaths()
[1] "~/.local/share/R/library"
[2] "~/.local/share/mise/installs/r/4.6.1/lib64/R/library"

R 4.6.1> tools::makevars_user()
[1] "~/.config/R/Makevars"

Of course, it’s still possible and quite easy.

.profile (you can also set in shell rc):

# R
# https://cran.r-project.org/doc/manuals/r-devel/R-exts.html#Package-subdirectories
export R_PROFILE_USER="$XDG_CONFIG_HOME/R/profile"
export R_MAKEVARS_USER="$XDG_CONFIG_HOME/R/Makevars"
export R_HISTFILE="$XDG_STATE_HOME/R/history"

$XDG_CONFIG_HOME/R/profile:

.libPaths(c("~/.local/share/R/library", .libPaths()))

The only annoyance is I can’t simply set R_HOME_USER due to .libPaths() located in another place. Anyway, it still works better than outdated r-base package in many distros.

Why

To have a simple life like this:

$ ls -1
projects/

$ ls -a1
.cache/
.config/
.local/
.profile
.ssh/
projects/

OCD Gospel!

Vinfall's Geekademy

Sine īrā et studiō