XDG Base Directory

From ArchWiki
(Redirected from XDG Base Directory support)
Jump to navigation Jump to search

This article summarizes the XDG Base Directory specification in #Specification and tracks software support in #Support.


Please read the full specification. This section will attempt to break down the essence of what it tries to achieve.

Only XDG_RUNTIME_DIR is set by default through pam_systemd. It is up to the user to explicitly define the other variables according to the specification.

User directories

    • Where user-specific configurations should be written (analogous to /etc).
    • Should default to $HOME/.config.
    • Where user-specific non-essential (cached) data should be written (analogous to /var/cache).
    • Should default to $HOME/.cache.
    • Where user-specific data files should be written (analogous to /usr/share).
    • Should default to $HOME/.local/share.
    • Used for non-essential, user-specific data files such as sockets, named pipes, etc.
    • Not required to have a default value; warnings should be issued if not set or equivalents provided.
    • Must be owned by the user with an access mode of 0700.
    • Filesystem fully featured by standards of OS.
    • Must be on the local filesystem.
    • May be subject to periodic cleanup.
    • Modified every 6 hours or set sticky bit if persistence is desired.
    • Can only exist for the duration of the user's login.
    • Should not store large files as it may be mounted as a tmpfs.

System directories

    • List of directories separated by : (analogous to PATH).
    • Should default to /usr/local/share:/usr/share.
    • List of directories separated by : (analogous to PATH).
    • Should default to /etc/xdg.


This section exists to catalog the growing set of software using the XDG Base Directory Specification introduced in 2003. This is here to demonstrate the viability of this specification by listing commonly found dotfiles and their support status. For those not currently supporting the Base Directory Specification, workarounds will be demonstrated to emulate it instead.

The workarounds will be limited to anything not involving patching the source, executing code stored in environment variables or compile-time options. The rationale for this is that configurations should be portable across systems and having compile-time options prevent that.

Hopefully this will provide a source of information about exactly what certain kinds of dotfiles are and where they come from.


When contributing make sure to use the correct section.

Nothing should require code evaluation (such as vim and VIMINIT), patches or compile-time options to gain support and anything which does must be deemed hardcoded. Additionally if the process is too error prone or difficult, such as Haskell's cabal or Eclipse, they should also be considered as hardcoded.

  • The first column should be either a link to an internal article, a Template:Pkg or a Template:AUR.
  • The second column is for any legacy files and directories the project had (one per line), this is done so people can find them even if they are no longer read.
  • In the third, try to find the commit or version a project switched to XDG Base Directory or any open discussions and include them in the next two columns (two per line).
  • The last column should include any appropriate workarounds or solutions. Please verify that your solution is correct and functional.


Application Legacy Path Supported Since Discussion Notes
ALSA ~/.asoundrc 577df36


[1] $XDG_CONFIG_HOME/alsa/asoundrc
Android Studio ~/.AndroidStudioX.X Android Studio 4.1 $XDG_CONFIG_HOME/Google/AndroidStudioX.X

$XDG_DATA_HOME/Google/AndroidStudioX.X $XDG_CACHE_HOME/Google/AndroidStudioX.X Location overview by Google doesn't mention XDG - paths could be hardcoded instead of using the proper variable, though that is unlikely as Intellij IDEA, which Android Studio is based on, implements it properly as well

antimicroAUR[broken link: package not found] ~/.antimicro edba864 [2] Package moved to antimicroxAUR - this entry needs to be migrated
aria2 ~/.aria2 8bc1d37 [3] $XDG_CONFIG_HOME/aria2/




2.9.0 [4] Uses XDG_CONFIG_HOME/asunder/asunder for ~/.asunder and XDG_CACHE_HOME/asunder/asunder_album_... for the other 3 files. Legacy paths are not removed after migration, they have to be deleted manually.
binwalk ~/.binwalk 2051757 [5] $XDG_CONFIG_HOME/binwalk
Blender ~/.blender 4293f47 [6]
calcurse ~/.calcurse 04162d [7] [8] XDG_CONFIG_HOME/calcurse


If the legacy path ~/.calcurse is present, it will take precedence.

ccache ~/.ccache 4.0 [9] XDG_CACHE_HOME/ccache


citra-gitAUR ~/.citra-emu f7c3193 [10]
clangd ~/.clangd fdf7dcc [11] XDG_CONFIG_HOME/clangd/config.yml


Project specific configuration can be specified in proj/.clangd. Configuration is combined when this is sensible. In case of conflicts, user config has the highest precedence, then inner project, then outer project.

Composer ~/.composer 1.0.0-beta1 [12]
d-feet ~/.d-feet 7f6104b
Dolphin emulator ~/.dolphin-emu a498c68 [13]
dr14_tmeterAUR 7e777ca [14] XDG_CONFIG_HOME/dr14tmeter/
dunst 78b6e2b [15]


8c255fb, [16] Use "$XDG_DATA_HOME"/fonts to store fonts instead.



[17] [18]

freerdp ~/.freerdp edf6e72
Emacs ~/.emacs



Legacy paths have precedence over XDG paths. Emacs will never create XDG_CONFIG_HOME/emacs/. Workaround for 26.3 or older: It's possible to set HOME, but it has unexpected side effects.

Gajim ~/.gajim 3e777ea [20]
gconfAUR ~/.gconf fc28caa [21]


60e0cfe 483505f

[22] [23]

Git ~/.gitconfig 0d94427 XDG_CONFIG_HOME/git/config
gops 71c4255
GStreamer ~/.gstreamer-0.10 4e36f93 [24]
helm ~/.helm 3.0.0
htop ~/.htoprc 93233a6
httpie ~/.httpie 5af0874 [25]
i3 ~/.i3 7c130fb
i3status ~/.i3status.conf c3f7fc4
Inkscape ~/.inkscape 0.47 [26]
iwd / iwctl ~/.iwctl_history d3e00d7f
intellij-idea-community-edition / intellij-idea-ultimate-editionAUR ~/.IntelliJIdeaXXXX.X 2020.1 [27] $XDG_CONFIG_HOME/Jetbrains/IntelliJIdeaXXXX.X

$XDG_DATA_HOME/Jetbrains/IntelliJIdeaXXXX.X $XDG_CACHE_HOME/Jetbrains/IntelliJIdeaXXXX.X

josm ~/.josm 11162 [28]
latexmk (in texlive-core) ~/.latexmkrc
lftp ~/.lftp 21dc400 [29]
lgogdownloaderAUR ~/.gogdownloader d430af6 [30]

a6f56f7 25bd2ee

NSS ~/.pki 3.42 [32]
Streamlink ~/.livestreamerrc ea80591 [33]
llpp 3ab86f0 Currently llpp places the configuration directly under XDG_CONFIG_HOME instead of creating a directory.
mc ~/.mc

1b99570 0b71156 ce401d7

Mercurial ~/.hgrc

3540200 4.2

msmtp ~/.msmtprc

af2f409 v1.6.7+

mesa 87ab26b XDG_CACHE_HOME/mesa
milkytracker ~/.milkytracker_config eb487c5 [35]
mozc ~/.mozc 91cc1e1 [36]
mpd ~/.mpdconf 87b7328
mpv ~/.mpv cb250d4 [37]
mutt ~/.mutt b17cd67 [38]
mypaint ~/.mypaint cf723b7


c16e79b [39]
ncmpcpp ~/.ncmpcpp

38d9f81 27cd86e

[40] [41]

ncmpcpp_directory should be set to avoid an error.log file in ~/.ncmpcpp.



[42] [43]

newsbeuter ~/.newsbeuter 3c57824 [44] It is required to create both directories [45]:

$ mkdir -p "$XDG_DATA_HOME"/newsbeuter "$XDG_CONFIG_HOME"/newsbeuter

node-gyp ~/.node-gyp 2b5ce52a [46] Only available on master as of 2018-12-04.


56a1cc2 [47]
nteract-binAUR 4593e72 [48] [49] does not recognize workarounds for ipython/jupyter
OfflineIMAP ~/.offlineimaprc 5150de5 [50]
opentyrianAUR ~/.opentyrian 8d45ff2 [51]
pandoc ~/.pandoc/ 0bed0ab [52]
PCManFM ~/.thumbnails 1.3.2
pcsx2 ~/.pcsx2

87f1e8f a9020c6 3b22f0f 0a012ae

[53] [54]
Pry ~/.pryrc

a0be0cc7 15e1fc92 e9d1be0e

python-pip ~/.pip 6.0 [56]
powershellAUR 6.0
ppsspp ~/.ppsspp 132fe47 [57]
procps-ng ~/.toprc af53e17

[58] [59]

pacman ~/.makepkg.conf 80eca94 [60]
panda3dAUR ~/.panda3d 2b537d2


59a8618 87ae830 9ab510a 4c195bc

quodlibet ~/.quodlibet 3.10.0 [62]

fd8686e 66d704b 51cff01

[63] Some optional bar widgets can create files and directories in non-compliant paths, but most often these are still configurable.
rclone ~/.rclone.conf 9d36258 [64]
rrAUR ~/.rr 02e7d41 [65]
RSpec ~/.rspec 5e395e2 [66]
rTorrent ~/.rtorrent.rc 6a8d332
RuboCop ~/.rubocop.yml 6fe5956 [67]


958ec35 [68]
skypeforlinux-stable-binAUR ~/.Skype 8.0
snes9x ~/.snes9x 93b5f11 [69] By default, the configuration file is left blank with intention that the user will fill it at their will (through the gui or manually).
spectrwm ~/.spectrwm a30bbb [70]
sublime-text-devAUR Cache is placed in $XDG_CONFIG_HOME/sublime-text-3/Cache instead of expected $XDG_CACHE_HOME/sublime-text-3.


3e4591d bd8c427 f57fc71

sway ~/.sway/config 614393c [71]
teeworlds ~/.teeworlds [72]
tig ~/.tigrc, ~/.tig_history 2.2 [73] ~/.local/share/tig directory must exist, writes to ~/.tig_history otherwise.
tmux ~/.tmux.conf 3.1 [74] 3.1 introduced ~/.config/tmux/tmux.conf and in 3.2 $XDG_CONFIG_HOME/tmux/tmux.conf was added
tmuxp ~/.tmuxp 1.5.0 [75] Fixed in 1.5.2
tmuxinatorAUR ~/.tmuxinator 2636923 [76]
Transmission ~/.transmission b71a298
util-linux 570b321
Uzbl c6fd63a [77]
VirtualBox ~/.VirtualBox 4.3 [78]
vis ~/.vis

68a25c7 d138908

VLC ~/.vlcrc 16f32e1 [80]
warsow ~/.warsow-2.x 98ece3f [81]
Wireshark ~/.wireshark b0b53fa
xsettingsd-gitAUR ~/.xsettingsd b4999f5
xmonad ~/.xmonad 40fc10b

[82] [83]

Alternatively the environments XMONAD_CONFIG_HOME, XMONAD_DATA_HOME, and XMONAD_CACHE_HOME are also available.
xsel ~/.xsel.log ee7b481 [84]


Application Legacy Path Supported Since Discussion Notes
abook ~/.abook $ abook --config "$XDG_CONFIG_HOME"/abook/abookrc --datafile "$XDG_DATA_HOME"/abook/addressbook
anacondaAUR ~/.conda/.condarc
[85] $ export CONDARC="$XDG_CONFIG_HOME/conda/condarc"
ack ~/.ackrc [86] $ export ACKRC="$XDG_CONFIG_HOME/ack/ackrc"


[87] [88] $ anki -b "$XDG_DATA_HOME"/Anki
aspell ~/.aspell.conf [89] $ export ASPELL_CONF="per-conf $XDG_CONFIG_HOME/aspell/aspell.conf; personal $XDG_CONFIG_HOME/aspell/en.pws; repl $XDG_CONFIG_HOME/aspell/en.prepl"
Atom ~/.atom [90] $ export ATOM_HOME="$XDG_DATA_HOME"/atom
aws-cli ~/.aws 1.7.45 [91]

$ export AWS_CONFIG_FILE="$XDG_CONFIG_HOME"/aws/config

bash-completion ~/.bash_completion $ export BASH_COMPLETION_USER_FILE="$XDG_CONFIG_HOME"/bash-completion/bash_completion


2.3.0 [92] Discussion in upstream bug states that bazaar will use ~/.config/bazaar if it exists. The logfile ~/.bzr.log might still be written.


[93] $ export BUCHHALTUNG="$XDG_CONFIG_HOME"/buchhaltung
Ruby#Bundler ~/.bundle [94] [95] $ export BUNDLE_USER_CONFIG="$XDG_CONFIG_HOME"/bundle BUNDLE_USER_CACHE="$XDG_CACHE_HOME"/bundle BUNDLE_USER_PLUGIN="$XDG_DATA_HOME"/bundle
Rust#Cargo ~/.cargo [96] [97] [98] [99] $ export CARGO_HOME="$XDG_DATA_HOME"/cargo
chez-schemeAUR ~/.chezscheme_history $ petite --eehistory "$XDG_DATA_HOME"/chezscheme/history
Chromium ~/.chromium



[100] [101] [102]

cinelerra ~/.bcast5 [103] $ export CIN_CONFIG="$XDG_CONFIG_HOME"/bcast5
conky ~/.conkyrc 00481ee [104] $ conky --config="$XDG_CONFIG_HOME"/conky/conkyrc
claws-mail ~/.claws-mail [105] $ claws-mail --alternate-config-dir "$XDG_DATA_HOME"/claws-mail
coreutils ~/.dircolors $ eval $(dircolors "$XDG_CONFIG_HOME"/dircolors)
crawl ~/.crawl The trailing slash is required:

$ export CRAWL_DIR="$XDG_DATA_HOME"/crawl/

clusterssh ~/.clusterssh/ $ alias cssh="cssh --config-file '$XDG_CONFIG_HOME/clusterssh/config'"

Despite this, clusterssh will still create ~/.clusterssh/.

dict ~/.dictrc $ dict -c "$XDG_CONFIG_HOME"/dict/dictrc
Docker ~/.docker $ export DOCKER_CONFIG="$XDG_CONFIG_HOME"/docker
docker-machine ~/.docker/machine $ export MACHINE_STORAGE_PATH="$XDG_DATA_HOME"/docker-machine
DOSBox ~/.dosbox/dosbox-0.74-2.conf [106] $ dosbox -conf "$XDG_CONFIG_HOME"/dosbox/dosbox.conf
Electrum Bitcoin Wallet ~/.electrum c121230 $ export ELECTRUMDIR="$XDG_DATA_HOME/electrum"
ELinks ~/.elinks $ export ELINKS_CONFDIR="$XDG_CONFIG_HOME"/elinks
elixir ~/.mix afaf889 [107] [108] Elixir do not fully conform to XDG specs, it will use XDG only if the environment variables are present, otherwise it will by default use legacy path.





$ export EM_CONFIG="$XDG_CONFIG_HOME"/emscripten/config
$ export EM_CACHE="$XDG_CACHE_HOME"/emscripten/cache
$ export EM_PORTS="$XDG_DATA_HOME"/emscripten/cache
$ emcc --em-config "$XDG_CONFIG_HOME"/emscripten/config --em-cache "$XDG_CACHE_HOME"/emscripten/cache

freecad ~/.FreeCAD [111] $ freecad -u "$XDG_CONFIG_HOME"/FreeCAD/user.cfg -s "$XDG_CONFIG_HOME"/FreeCAD/system.cfg

Despite these options, freecad will still create the file .FreeCAD/cookie as the web module has it hard coded

GDB ~/.gdbinit $ gdb -nh -x "$XDG_CONFIG_HOME"/gdb/init
get_iplayerAUR ~/.get_iplayer $ export GETIPLAYERUSERPREFS="$XDG_DATA_HOME"/get_iplayer
getmail ~/.getmail/getmailrc $ getmail --rcfile="$XDG_CONFIG_HOME/getmail/getmailrc" --getmaildir="$XDG_DATA_HOME/getmail"
glivAUR ~/.glivrc $ gliv --glivrc="$XDG_CONFIG_HOME"/gliv/glivrc
GNURadio ~/.gnuradio [112]
GnuPG ~/.gnupg [113] [114]

$ export GNUPGHOME="$XDG_DATA_HOME"/gnupg
$ gpg2 --homedir "$XDG_DATA_HOME"/gnupg

Note that this currently does not work out-of-the-box using systemd user units and socket-based activation, since the socket directory changes based on the hash of $GNUPGHOME. You can get the new socket directory using gpgconf --dry-run --create-socketdir, and have to modify the systemd user units to listen on the correct sockets accordingly.

Go ~/go [115]

$ export GOPATH="$XDG_DATA_HOME"/go

Google Earth ~/.googleearth Some paths can be changed with the KMLPath and CachePath options in ~/.config/Google/GoogleEarthPlus.conf
gopass ~/.password-store Override settings in ~/.config/gopass/config.yml:
path: gpgcli-gitcli-fs+file:///home/<userid>/.config/password-store
gpodder ~/gPodder GPODDER_DOWNLOAD_DIR sets the download folder. GPODDER_HOME - where config and database files are stored, downloads also if GPODDER_DOWNLOAD_DIR is not set.
GQ LDAP client



$ export GQRC="$XDG_CONFIG_HOME"/gqrc
$ export GQSTATE="$XDG_DATA_HOME"/gq/gq-state
$ mkdir -p "$(dirname "$GQSTATE")"

Gradle ~/.gradle [116] $ export GRADLE_USER_HOME="$XDG_DATA_HOME"/gradle
GTK 1 ~/.gtkrc $ export GTK_RC_FILES="$XDG_CONFIG_HOME"/gtk-1.0/gtkrc
GTK 2 ~/.gtkrc-2.0 $ export GTK2_RC_FILES="$XDG_CONFIG_HOME"/gtk-2.0/gtkrc
hledger ~/.hledger.journal [117] $ export LEDGER_FILE="$XDG_DATA_HOME"/hledger.journal
imapfilterAUR ~/.imapfilter $ export IMAPFILTER_HOME="$XDG_CONFIG_HOME/imapfilter"
ipython/jupyter ~/.ipython won't fix,won't fix

$ export IPYTHONDIR="$XDG_CONFIG_HOME"/jupyter

irb ~/.irbrc
$ export IRBRC="$XDG_CONFIG_HOME"/irb/irbrc
IRB.conf[:SAVE_HISTORY] ||= 1000
IRB.conf[:HISTORY_FILE] ||= File.join(ENV["XDG_DATA_HOME"], "irb", "history")
irssi ~/.irssi [118] $ irssi --config="$XDG_CONFIG_HOME"/irssi/config --home="$XDG_DATA_HOME"/irssi
isync ~/.mbsyncrc $ mbsync -c "$XDG_CONFIG_HOME"/isync/mbsyncrc
Java#OpenJDK ~/.java/.userPrefs [119] $ export _JAVA_OPTIONS=-Djava.util.prefs.userRoot="$XDG_CONFIG_HOME"/java
k9s ~/.k9s 0.20.4 [120] $ export K9SCONFIG="$XDG_CONFIG_HOME"/k9s
KDE ~/.kde [121] $ export KDEHOME="$XDG_CONFIG_HOME"/kde
keychain ~/.keychain [122] [123] $ keychain --absolute --dir "$XDG_RUNTIME_DIR"/keychain
ledger ~/.ledgerrc, ~/.pricedb [124] $ ledger --init-file "$XDG_CONFIG_HOME"/ledgerrc
less ~/.lesshst

$ mkdir -p "$XDG_CACHE_HOME"/less
$ export LESSKEY="$XDG_CONFIG_HOME"/less/lesskey
$ export LESSHISTFILE="$XDG_CACHE_HOME"/less/history

$ export LESSHISTFILE=- can be used to disable this feature.

Leiningen ~/.lein


$ export LEIN_HOME="$XDG_DATA_HOME"/lein

to change the m2 repo location used by leiningen look here: Leiningen#m2_repo_location

libdvdcss ~/.dvdcss [125] $ export DVDCSS_CACHE="$XDG_DATA_HOME"/dvdcss
libice ~/.ICEauthority [126] $ export ICEAUTHORITY="$XDG_CACHE_HOME"/ICEauthority

Make sure XDG_CACHE_HOME is set beforehand to directory user running Xorg has write access to.

Do not use XDG_RUNTIME_DIR as it is available after login. Display managers that launch Xorg (like GDM) will repeatedly fail otherwise.

librewolfAUR ~/.mozilla


$ mkdir $XDG_DATA_HOME/librewolf && mv librewolf.AppImage $XDG_DATA_HOME/librewolf
$ $XDG_DATA_HOME/librewolf/librewolf.AppImage --appimage-portable-home
$ sudo ln -s $XDG_DATA_HOME/librewolf/librewolf.AppImage /usr/local/bin/librewolf

This is not a perfect solution - you will have to create symlinks to your downloads and other XDG directories to get the browser to use them properly. However, it is workable. Of course, you could do this in any directory, not just $XDG_DATA_HOME



$ export XCOMPOSEFILE="$XDG_CONFIG_HOME"/X11/xcompose
$ export XCOMPOSECACHE="$XDG_CACHE_HOME"/X11/xcompose

ltrace ~/.ltrace.conf $ ltrace -F "$XDG_CONFIG_HOME"/ltrace/ltrace.conf
maven ~/.m2 [127] $ mvn -gs "$XDG_CONFIG_HOME"/maven/settings.xml and set <localRepository> as appropriate in settings.xml
Mathematica ~/.Mathematica $ export MATHEMATICA_USERBASE="$XDG_CONFIG_HOME"/mathematica
maxima ~/.maxima $ export MAXIMA_USERDIR="$XDG_CONFIG_HOME"/maxima
mednafen ~/.mednafen $ export MEDNAFEN_HOME="$XDG_CONFIG_HOME"/mednafen
mitmproxy ~/.mitmproxy

$ alias mitmproxy="mitmproxy --set confdir=$XDG_CONFIG_HOME/mitmproxy"
$ alias mitmweb="mitmweb --set confdir=$XDG_CONFIG_HOME/mitmproxy"

MOC ~/.moc

$ mocp -M "$XDG_CONFIG_HOME"/moc
$ mocp -O MOCDir="$XDG_CONFIG_HOME"/moc

monero ~/.bitmonero $ monerod --data-dir "$XDG_DATA_HOME"/bitmonero
most ~/.mostrc $ export MOST_INITFILE="$XDG_CONFIG_HOME"/mostrc
MPlayer ~/.mplayer $ export MPLAYER_HOME="$XDG_CONFIG_HOME"/mplayer


$ export MYSQL_HISTFILE="$XDG_DATA_HOME"/mysql_history

~/.my.cnf only supported for mysql-server, not mysql-client [128]

~/.mylogin.cnf unsupported

ncurses ~/.terminfo Precludes system path searching:

$ export TERMINFO="$XDG_DATA_HOME"/terminfo
$ export TERMINFO_DIRS="$XDG_DATA_HOME"/terminfo:/usr/share/terminfo

ncmpc ~/.ncmpc ncmpc -f "$XDG_CONFIG_HOME"/ncmpc/config
Netbeans ~/.netbeans [129] $ netbeans --userdir "${XDG_CONFIG_HOME}"/netbeans
Node.js ~/.node_repl_history $ export NODE_REPL_HISTORY="$XDG_DATA_HOME"/node_repl_history [130]
notmuch ~/.notmuch-config [131]

$ export NOTMUCH_CONFIG="$XDG_CONFIG_HOME"/notmuch/notmuchrc
$ export NMBGIT="$XDG_DATA_HOME"/notmuch/nmbug




prefix is unnecessary (and unsupported) if Node.js is installed by nvmAUR.

nuget ~/.nuget/packages [133] $ export NUGET_PACKAGES="$XDG_CACHE_HOME"/NuGetPackages
NVIDIA ~/.nv Uses XDG_CACHE_HOME if set, otherwise improperly falls back to ~/.nv instead of ~/.cache.
nvidia-settings ~/.nvidia-settings-rc $ nvidia-settings --config="$XDG_CONFIG_HOME"/nvidia/settings
nvmAUR ~/.nvm $ export NVM_DIR="$XDG_DATA_HOME"/nvm


$ export OCTAVE_HISTFILE="$XDG_CACHE_HOME/octave-hsts"
$ export OCTAVE_SITE_INITFILE="$XDG_CONFIG_HOME/octave/octaverc"

source /usr/share/octave/site/m/startup/octaverc;
pkg prefix ~/.local/share/octave/packages ~/.local/share/octave/packages;
pkg local_list /home/<your username>/.local/share/octave/octave_packages;

The local_list option must be given an absolute path.

openscad ~/.OpenSCAD 7c3077b0f [134] Does not fully honour XDG Base Directory Specification, see [135]

Currently it hard-codes ~/.local/share.

OpenSSL ~/.rnd Seeding file .rnd's location can be set with RANDFILE environment variable per FAQ.
parallel ~/.parallel 20170422 $ export PARALLEL_HOME="$XDG_CONFIG_HOME"/parallel
pass ~/.password-store $ export PASSWORD_STORE_DIR="$XDG_DATA_HOME"/pass
Pidgin ~/.purple [136] $ pidgin --config="$XDG_DATA_HOME"/purple


9.2 [137] [138]

$ export PSQLRC="$XDG_CONFIG_HOME/pg/psqlrc"
$ export PSQL_HISTORY="$XDG_CACHE_HOME/pg/psql_history"
$ export PGPASSFILE="$XDG_CONFIG_HOME/pg/pgpass"
$ export PGSERVICEFILE="$XDG_CONFIG_HOME/pg/pg_service.conf"

It is required to create both directories: $ mkdir "$XDG_CONFIG_HOME/pg" && mkdir "$XDG_CACHE_HOME/pg"

PulseAudio ~/.esd_auth Very likely generated by the module-esound-protocol-unix.so module. It can be configured to use a different location but it makes much more sense to just comment out this module in /etc/pulse/default.pa or "$XDG_CONFIG_HOME"/pulse/default.pa.
python-azure-cliAUR ~/.azure $ export AZURE_CONFIG_DIR=$XDG_DATA_HOME/azure
python-gripAUR ~/.grip $ export GRIPHOME="$XDG_CONFIG_HOME/grip"
python-setuptools ~/.python-eggs $ export PYTHON_EGG_CACHE="$XDG_CACHE_HOME"/python-eggs
python-pylint ~/.pylint.d won't fix $ export PYLINTHOME="$XDG_CACHE_HOME"/pylint
racket ~/.racketrc


[139] $ export PLTUSERHOME="$XDG_DATA_HOME"/racket
readline ~/.inputrc $ export INPUTRC="$XDG_CONFIG_HOME"/readline/inputrc


$ export REDISCLI_HISTFILE="$XDG_DATA_HOME"/redis/rediscli_history

$ export REDISCLI_RCFILE="$XDG_CONFIG_HOME"/redis/redisclirc

rlwrap ~/.*_history [140] $ export RLWRAP_HOME="$XDG_DATA_HOME"/rlwrap
Ruby#RubyGems ~/.gem

$ export GEM_HOME="$XDG_DATA_HOME"/gem

Make sure to remove gem: --user-install from /etc/gemrc

Rust#Rustup ~/.rustup [141] $ export RUSTUP_HOME="$XDG_DATA_HOME"/rustup
sbt ~/.sbt


[142] $ sbt -ivy "$XDG_DATA_HOME"/ivy2 -sbt-dir "$XDG_DATA_HOME"/sbt (beware [143])
SageMath ~/.sage $ export DOT_SAGE="$XDG_CONFIG_HOME"/sage
GNU Screen ~/.screenrc $ export SCREENRC="$XDG_CONFIG_HOME"/screen/screenrc
simplescreenrecorder ~/.ssr/ 0.4.3 [144]


Will use $XDG_CONFIG_HOME/simplescreenrecorder/ ONLY if it already was created otherwise defaults to ~/.ssr

$ mv ~/.ssr "$XDG_CONFIG_HOME"/simplescreenrecorder



[146] [147] Move the ~/.spacemacs file.

$ export SPACEMACSDIR="$XDG_CONFIG_HOME"/spacemacs
$ mv ~/.spacemacs "$SPACEMACSDIR"/init.el

Other files need to be configured like Emacs.

Haskell#Stack ~/.stack [148] $ export STACK_ROOT="$XDG_DATA_HOME"/stack
subversion ~/.subversion [149] [150][151] $ svn --config-dir "$XDG_CONFIG_HOME"/subversion


$ export TASKDATA="$XDG_DATA_HOME"/task
$ export TASKRC="$XDG_CONFIG_HOME"/task/taskrc

Local TeX Live TeXmf tree, TeXmf caches and config ~/texmf, ~/.texlive/texmf-var, ~/.texlive/texmf-config

$ export TEXMFVAR=$XDG_CACHE_HOME/texlive/texmf-var
$ export TEXMFCONFIG=$XDG_CONFIG_HOME/texlive/texmf-config

tiptopAUR ~/.tiptoprc This will still expect the .tiptoprc file.

$ tiptop -W "$XDG_CONFIG_HOME"/tiptop

uncrustify ~/.uncrustify.cfg $ export UNCRUSTIFY_CONFIG="$XDG_CONFIG_HOME"/uncrustify/uncrustify.cfg
Unison ~/.unison $ export UNISON="$XDG_DATA_HOME"/unison
units ~/.units_history $ units --history "$XDG_CACHE_HOME"/units_history
urxvtd ~/.urxvt/urxvtd-hostname $ export RXVT_SOCKET="$XDG_RUNTIME_DIR"/urxvtd



$ export VAGRANT_HOME="$XDG_DATA_HOME"/vagrant
$ export VAGRANT_ALIAS_FILE="$XDG_DATA_HOME"/vagrant/aliases

virtualenv ~/.virtualenvs $ export WORKON_HOME="$XDG_DATA_HOME/virtualenvs"
Visual Studio Code ~/.vscode-oss/argv.json [153] You can use $ export VSCODE_PORTABLE="$XDG_DATA_HOME"/vscode, which is not documented and might break unexpectedly


$ export WAKATIME_HOME="$XDG_CONFIG_HOME/wakatime"

The directory needs to be created manually:
$ mkdir "$XDG_CONFIG_HOME/wakatime"

WeeChat ~/.weechat [154] [155]

$ export WEECHAT_HOME="$XDG_CONFIG_HOME"/weechat
$ weechat -d "$XDG_CONFIG_HOME"/weechat



$ export WGETRC="$XDG_CONFIG_HOME/wgetrc"
and add the following as an alias for wget:
$ wget --hsts-file="$XDG_CACHE_HOME/wget-hsts"
or set the hsts-file variable with an absolute path as wgetrc does not support environment variables:
$ echo hsts-file \= "$XDG_CACHE_HOME"/wget-hsts >> "$XDG_CONFIG_HOME/wgetrc"

wine ~/.wine [156] Winetricks uses XDG-alike location below for WINEPREFIX management:

$ mkdir -p "$XDG_DATA_HOME"/wineprefixes
$ export WINEPREFIX="$XDG_DATA_HOME"/wineprefixes/default

xbindkeys ~/.xbindkeysrc $ xbindkeys -f "$XDG_CONFIG_HOME"/xbindkeys/config
xorg-xauth ~/.Xauthority $ export XAUTHORITY="$XDG_RUNTIME_DIR"/Xauthority

Note that LightDM does not allow you to change this variable. If you change it nonetheless, you will not be able to login. Use startx instead or configure LightDM. According to [157] SLiM has ~/.Xauthority hardcoded.




$ export XINITRC="$XDG_CONFIG_HOME"/X11/xinitrc
$ export XSERVERRC="$XDG_CONFIG_HOME"/X11/xserverrc

Note that these variables are respected by xinit, but not by startx. Instead, specify the filename as an argument:

$ startx "$XDG_CONFIG_HOME/X11/xinitrc" -- "$XDG_CONFIG_HOME/X11/xserverrc" vt1



Ultimately you should be using Xresources and since these resources are loaded via xrdb you can specify a path such as $ xrdb -load ~/.config/X11/xresources.


These can be added as part of your Xorg init script (~/.xinitrc) or Xsession start script (which will often be based on /etc/X11/Xsession).

Depending on where you have configured your $XDG_CACHE_HOME, you made need to expand the paths yourself.

# xsession start script

Unlike most other examples in this table, actual x11 init scripts will vary a lot between installations.



[159] $ export _Z_DATA="$XDG_DATA_HOME/z"


2d454b5 [160] [161] $ alias yarn="yarn --use-yarnrc $XDG_CONFIG_HOME/yarn/config"


Application Legacy Path Discussion Notes
adb & Android Studio ~/.android/ [162]
Ansible ~/.ansible [163] [164]
AMule ~/.aMule
anthy ~/.anthy [165]
Apache Directory Studio ~/.ApacheDirectoryStudio
ARandR ~/.screenlayout


won't fix [166]
arduino-cli ~.arduino15/ [167] $ mv ~/.arduino15 $XDG_CONFIG_HOME/arduino15

$ alias arduino-cli='arduino-cli --config-file $XDG_CONFIG_HOME/arduino15/arduino-cli.yaml'

Audacity ~/.audacity-data/ [168]
Avidemux ~/.avidemux6


won't fix $ mkdir -p "$XDG_DATA_HOME"/bash

$ export HISTFILE="$XDG_DATA_HOME"/bash/history A specified bashrc can be sourced from /etc/bash.bashrc.

Specify --init-file <file> as an alternative to ~/.bashrc for interactive shells.

Berkshelf ~/.berkshelf/
cabal ~/.cabal/ [169] See discussion for potential workarounds. It is not very easy or straightforward but may be possible to emulate Base Directory compliance.
chattyAUR ~/.chatty/ [170]
cmake ~/.cmake/ Used for the user package registry ~/.cmake/packages/<package>, detailed in cmake-packages(7) § User Package Registry and the Package registry wiki page. Looks like it's hardcoded, for example in cmFindPackageCommand.cxx.
Cinnamon ~/.cinnamon/ [171]
conanAUR ~/.conan/ [172]
cryptomatorAUR ~/.Cryptomator [173]
CUPS ~/.cups/ won't fix
darcs ~/.darcs/ [174]
dbus ~/.dbus/ [175] Consider using dbus-broker, as it does not create or use this directory.
devede ~/.devedeng Hardcoded here
Dia ~/.dia/
dotnet-sdk ~/.dotnet/ [176]
dropbox ~/.dropbox/
Eclipse ~/.eclipse/ [177] Option -Dosgi.configuration.area=@user.home/.config/.. overrides but must be added to "$ECLIPSE_HOME"/eclipse.ini" rather than command line which means you must have write access to $ECLIPSE_HOME. (Arch Linux hard-codes $ECLIPSE_HOME in /usr/bin/eclipse)
Fetchmail ~/.fetchmailrc
Firefox ~/.mozilla/ [178] [179]
Flatpak ~/.var/ [180] [181] won't fix
fltk ~/.fltk/ [182]
freesweep ~/.sweeprc [183]
gftp ~/.gftp/ [184] Following the XDG spec is planned for gftp.
GHC ~/.ghc [185]
ghidra [186]
GoldenDict ~/.goldendict/ [187]
gramps ~/.gramps/ [188]
groovy ~/.groovy/
grsync ~/.grsync/ [189]
google-cloud-sdkAUR ~/.gsutil/ [190]
gtk-recordMyDesktop ~/.gtk-recordmydesktop
kiteAUR ~/.kite/ [191]
Kubernetes ~/.kube/ [192][193]
hplip ~/.hplip/ [194]
idris ~/.idris [195]
Java OpenJDK ~/.java/fonts [196] $ export _JAVA_OPTIONS=-Djava.util.prefs.userRoot="$XDG_CONFIG_HOME"/java
Java OpenJFX ~/.java/webview
jgmenu ~/.jgmenu-lockfile [197] [198]


[199] [200] The trailing :$JULIA_DEPOT_PATH is necessary. See [201]


kotlin ~/.kotlinc_history
Linux PAM ~/.pam_environment [202] Hardcoded in modules/pam_env/pam_env.c




History can be moved by using rlwrap mathomatic -r with the RLWRAP_HOME environment set appropriately.
Minecraft ~/.minecraft/ won't fix
Minetest ~/.minetest/ won't fix [203]
minicom ~/.minirc.dfl Upstream has a TODO entry for supporting configuration files under ~/.config/minicom. [204]
Mono ~/.mono/


[205] This Stack Overflow thread suggests a partial workaround using command-line switch --norc.
Nestopia UE ~/.nestopia/ won't fix
~/.netrc Like ~/.ssh, many programs expect this file to be here. These include projects like curl (CURLOPT_NETRC_FILE), ftp (NETRC), s-nail (NETRC), etc. While some of them offer alternative configurable locations, many do not such as w3m, wget and lftp.
nmcli ~/.nmcli-history Hardcoded to g_get_home_dir()[206] [207]
Networkmanager-openvpn ~/.cert/nm-openvpn [208]
OpenSSH ~/.ssh won't fix Assumed to be present by many ssh daemons and clients such as DropBear and OpenSSH.
palemoon ~/.moonchild productions [209]
parsec-binAUR ~/.parsec
pcsxrAUR ~/.pcsxr A -cfg flag exists, but can only be set relative to ~/.pcsxr.
perf ~/.debug Hardcoded in tools/perf/util/config.c:29.
perl ~/.cpan Perl5's CPAN expects ~/.cpan.
various shells and display managers ~/.profile
PuTTY ~/.putty/ [210]
python ~/.python_history [211] [212] All history from interactive sessions is saved to ~/.python_history by default since version 3.4. This can still be customized the same way as in older versions (see this example), including to use a custom path or disable history saving.
python-poetry ~/.poetry [213] POETRY_HOME can be used but it does not separate data and config.
python-tensorflow ~/.keras [214] The issues is for tf.keras module
qmmp ~/.qmmp [215]
Qt Designer ~/.designer
RedNotebook ~/.rednotebook
Remarkable ~/.remarkable
renderdocAUR ~/.renderdoc won't fix
Ren'Py ~/.renpy won't fix
repo ~/.repoconfig [216]
SANE ~/.sane/ scanimage creates a .cal file there
sbcl ~/.sbclrc
(require :asdf)
(setf sb-ext:*userinit-pathname-function*
      (lambda () (uiop:xdg-config-home #P"sbcl/sbclrc")))

Note that this requires root privileges and will change the location of ~/.sbclrc for all users. This can be mitigated by checking for an existing ~/.sbclrc inside the lambda form.

scribus ~/.scribus
SeaMonkey ~/.mozilla/ [217]
Snap ~/snap/ [218]


SpamAssassin ~/.spamassassin


[220] $ export SQLITE_HISTORY=$XDG_DATA_HOME/sqlite_history

$ sqlite3 -init "$XDG_CONFIG_HOME"/sqlite3/sqliterc



[221] Many game engines (Unity 3D, Unreal) follow the specification, but then individual game publishers hardcode the paths in Steam Auto-Cloud causing game-saves to sync to the wrong directory.
TeamSpeak ~/.ts3client $ export TS3_CONFIG_DIR="$XDG_CONFIG_HOME/ts3client"
terraform ~/.terraform.d/ [222]
texinfo ~/.infokey $ info --init-file "$XDG_CONFIG_HOME/infokey"
TeXmacs ~/.TeXmacs
Thunderbird ~/.thunderbird/ [223]
TigerVNC ~/.vnc
tllocalmgr ~/.texlive
valeAUR ~/.vale.ini won't fix $ vale --config "$XDG_CONFIG_HOME/vale/config.ini"


[224] Since 7.3.1178 vim will search for ~/.vim/vimrc if ~/.vimrc is not found.
set runtimepath^=$XDG_CONFIG_HOME/vim
set runtimepath+=$XDG_DATA_HOME/vim
set runtimepath+=$XDG_CONFIG_HOME/vim/after

set packpath^=$XDG_DATA_HOME/vim,$XDG_CONFIG_HOME/vim
set packpath+=$XDG_CONFIG_HOME/vim/after,$XDG_DATA_HOME/vim/after

let g:netrw_home = $XDG_DATA_HOME."/vim"
call mkdir($XDG_DATA_HOME."/vim/spell", 'p')
set viewdir=$XDG_DATA_HOME/vim/view | call mkdir(&viewdir, 'p')

set backupdir=$XDG_CACHE_HOME/vim/backup | call mkdir(&backupdir, 'p')
set directory=$XDG_CACHE_HOME/vim/swap   | call mkdir(&directory, 'p')
set undodir=$XDG_CACHE_HOME/vim/undo     | call mkdir(&undodir,   'p')

if !has('nvim') | set viminfofile=$XDG_CACHE_HOME/vim/viminfo | endif
export VIMINIT='source "$XDG_CONFIG_HOME/vim/vimrc"'

VIMINIT environment variable will also affect Neovim. If separate configs for Vim and Neovim are desired then the following will be a better choice:

export VIMINIT='if !has('nvim') | source "$XDG_CONFIG_HOME/vim/vimrc" | endif'
vimperator ~/.vimperatorrc [225] $ export VIMPERATOR_INIT=":source $XDG_CONFIG_HOME/vimperator/vimperatorrc"


visidataAUR ~/.visidata [226]
w3m ~/.w3m [227] [228]
wpa_cli ~/.wpa_cli_history
x2goclient ~/.x2goclient alias x2goclient="x2goclient --home=$HOME/.config"
xdg-utils ~/.gnome [229] [230] [231] For some reason the script xdg-desktop-menu hard-codes gnome_user_dir="$HOME/.gnome/apps". This is used by chromium among others. Bug discussion has moved to gitlab and PR with fix exists, however it is not merged yet.
xombrero[dead link 2020-02-26] ~/.xombrero [232][dead link 2020-02-26]
xournalpp ~/.xournalpp [233] XDG will be honored in the next version [234]
xpdf ~/.xpdfrc
YARD ~/.yard [235] Would accept Pull Request if anyone want to implement it.
zenmap nmap ~/.zenmap [236] [237]
zoomAUR ~/.zoom
zoteroAUR ~/.zotero ~/Zotero [238]


[239] Consider exporting ZDOTDIR=$HOME/.config/zsh in ~/.zshenv (this is hardcoded due to the bootstrap problem). You could also add this to /etc/zsh/zshenv and avoid the need for any dotfiles in your HOME. Doing this however requires root privilege which may not be viable and is system-wide.

$ export HISTFILE="$XDG_DATA_HOME"/zsh/history

$ compinit -d $XDG_CACHE_HOME/zsh/zcompdump-$ZSH_VERSION [240] /!\ The folder needs to exist


C99: Cloudef's simple implementation.
Officially in directory since ab9d0810ce.
Java, Kotlin, Clojure, Scala, ...
Builtin support via GLib.Environment.
See get_user_cache_dir, get_user_data_dir, get_user_config_dir, etc.

See also