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.
TLDR
- For TLDR, see Use the XDG Base Directory Specification!
- For specs, see XDG Base Directory Specification
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"
List
Most are available in XDG Base Directory on Arch Wiki already.
Partially/Fully Supported
- Bash
- Calcurse
- Cargo (
CARGO_HOMEmeans config + data, silly idea) - Git
- GnuPG
- Lean (same as Cargo)
- Newsboat
- nim, nimble
- notmuch
- npm
- nuget
- Ollama (just models, config & ssh key are not supported)
- R
- wget
- xsel
Hardcoded
Many softwares live long enough to arrogantly ignore XDG Base Directory Specification and get away with it.
Exempli gratia, Firefox has a bug report regarding Support for the XDG Base Directory Specification which only got fixed in Firefox 147, 21 years later.
The list contains only a small fraction of blessed packages that might show some respect to the spec soon™.
- ADB & Android Studio (would look for
ADB_VENDOR_KEYSas well, but~/.androidwould ALWAYS get generated…) - Chromium (fixed in 146)
- endless CEF/Electron/QtWebEngine projects…
- Firefox (fixed in 147 and ESR 153)
- thus Thunderbird and Zotero
- MAME
- .NET (old solution and runtime discussion)
- Python (
PYTHON_HISTORYworks for Python 3.13+) - Ren’Py (
RENPY_PATH_TO_SAVESworks on Ren’Py 7.5+ games) - Vim (fully supported since 9.2.0019. Simply add
source $VIMRUNTIME/xdg.vimin your vimrc.) VSCode and VSCodium (--extensions-diris not enough as.vscode-oss/argv.jsonis still needed)- w3m
- Zsh (via
$ZDOTDIR)
Workaround
Python
OUTDATED! Since Python 3.13, simply set PYTHON_HISTORY should suffice.
Common methods to disable Python history are pretty hacky:
- I don’t like
chownorchattrsolution as.python_historyis still present. - Removing
~/.python_historyby creating~/.pythonrcis just funny.
Quoted from a comment regarding this solution :
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:
Add these in
$HOME/.profile(.bashrcor.zshrcworks too):export PYTHONPYCACHEPREFIX="$XDG_CACHE_HOME"/python export PYTHONUSERBASE="$XDG_DATA_HOME"/python export PYTHONSTARTUP="$XDG_CONFIG_HOME"/python/pythonrcCreate
"$XDG_CONFIG_HOME"/python/pythonrc:import readline readline.write_history_file = lambda *args: NoneSource
$HOME/.profilebyexec 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
- I use arf as R console, which is installed via mise GitHub backend
- I have custom
libPathsto avoid unnecessary reinstall between minor/patch version updates. Makevarsset 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, at least it works better than outdated r-base package in many distros.
Show-off
$ ls -a1
.bashrc
.cache/
.config/
.gitignore
.local/
.profile
.ssh/
.zshenv
downloads/
music -> my-music-dir
projects/
It’s possible to move symlinks and things like .bashrc elsewhere as well. If done properly, $HOME could become:
$ ls -1
projects/
$ ls -a1
.cache/
.config/
.local/
.profile
.ssh/
projects/
OCD Gospel!
