Keep $HOME Clean via XDG Base Directory

Foreword

I came across Dotfile madness (2019) on Hacker News today, and found How I Keep My Home Directory Clean & XDG Base Directory on Arch Wiki.

This serves as a reminder of how to make $HOME (mostly) clutter-free, thus making Manage Dotfiles Using Bare Git Repo easier.

Update on 2024-07-26: you can also use xdg-ninja for the initial setup, but many things of the post still apply.

XDG Base Directory

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"

Sterilization

Most are available in XDG Base Directory on Arch Wiki already.

Partially/Fully Supported

  • Bash
  • Calcurse
  • Cargo (CARGO_HOME means config + data, silly idea)
  • Git
  • GnuPG
  • Less
  • Newsboat
  • notmuch
  • npm & pnpm
  • nuget
  • nvm
  • rlwrap (.*_history: bash, ssh, trans, zsh)
  • translate-shell
  • wget
  • xsel
  • radian
  • R
  • Ollama (just models, config & ssh key are not supported)

Hardcoded

Many softwares live long enough to arrogantly ignore XDG Base Directory Specification and get away with it. Exempli gratia, Firefox has a 20-year-old bug report regarding Support for the Freedesktop.org XDG Base Directory Specification , and it’s updated just a few weeks ago as of writingupdating!

The list contains only a small fraction of blessed packages that might show some respect to the spec soon™️.

Workaround

Python

🚨 Warning

OUTDATED! Since Python 3.13, simply set PYTHON_HISTORY should suffice.

Common methods to disable Python history are pretty hacky:

  • I don’t like chown or chattr solution as .python_history is still present.
  • Removing ~/.python_history by creating ~/.pythonrc is just funny.

Quoted from a comment regarding this solution :

💬 Quote

So I get to replace one turd in my home directory with another

I combine the answers of How can I disable the new history feature in Python 3.4? and enhance it by doing the following:

  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.

Vim

Follow the instruction on Arch Wiki, and move the original files respectively:

$XDG_CONFIG_HOME/vim
├── colors
└── vimrc

$XDG_DATA_HOME/vim
└── spell
    ├── en.utf-8.add
    └── ...

R

While R is configurable, my workflow 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 radian
~/.local/share/mise/shims/radian
  • I use radian as R console, and it’s installed via mise pipx backend with pipx.uvx=true (so actually installed via uv tool)
  • I have custom libPaths to avoid unnecessary reinstall between minor/patch version updates.
  • Makevars set to cache/speedup library compilation
radian

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

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

r$> 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, at least it works better than outdated r-base package in many distros.

Show-off

$ ls -a1
.bashrc
.cache/
.config/
.dotfiles/
.gitignore
.local/
.profile
.ssh/
.zshenv
bin/
downloads/
music -> my-music-dir
projects/

It’s possible to move .bashrc, .dotfiles and those symlinks elsewhere as well. I just don’t bother to do it. If done properly, $HOME could become:

$ ls -1
bin/
projects/

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

OCD Gospel!

Vinfall's Geekademy

Sine īrā et studiō