# \[ANN\] BaseDirs.jl (was XDG)

**URL:** <https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953>\
**Category:** Package Announcements\
**Created:** [March 12, 2023, 5:23am UTC](https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953 "2023-03-12T05:23:19Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [March 12, 2023, 5:23am UTC](https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953/1 "2023-03-12T05:23:20Z")

</div>

After much indecision regarding the package name, `BaseDirs` is finally registered! 🥳

See the [Pre-ANN/RFC thread](https://discourse.julialang.org/t/pre-ann-rfc-xdg-jl-a-cross-platform-implementation-of-the-xdg-directory-spec/94027) for a recap on what the package is, but the TLDR; is it provides a cross-platform way of finding the appropriate place to look for/put files, because `.julia` is not a panacea.

This is a very small and lightweight package (with zero dependencies), using Julia 1.9-rc1 it takes ~25ms to load on my machine.

If you work on a package that asks any questions like “where should I put some cache files?”, “where can I find system fonts?”, “what’s a good place to save a document?” or similar, I’d recommend giving this package a look.

For more info, see the (somewhat detailed) docs: [https://tecosaur.github.io/BaseDirs.jl](https://tecosaur.github.io/BaseDirs.jl)

* * *

To finish off, here’s some example usage of the package:

```julia
julia> using BaseDirs

julia> BaseDirs.CONFIG_HOME[]
"/home/tec/.config"

julia> BaseDirs.User.config()
"/home/tec/.config"

julia> BaseDirs.User.config("sub", "dir/")
"/home/tec/.config/sub/dir/"

julia> BaseDirs.User.config(BaseDirs.Project("mything"), "config.conf", create=true)
"/home/tec/.config/mything/config.conf"

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [March 12, 2023, 7:33am UTC](https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953/2 "2023-03-12T07:33:15Z")

</div>

> [@tecosaur](#):
>
> where should I put some cache files

See [GitHub - JuliaPackaging/Scratch.jl: Scratch spaces for all your persistent mutable data needs](https://github.com/JuliaPackaging/Scratch.jl) that features automatic garbage collection and optional versioning.

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [March 12, 2023, 7:47am UTC](https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953/3 "2023-03-12T07:47:57Z")

</div>

From a glance, since `Scratch.jl` seems to want to make interacting with cache files easier, I’d suggest that `Scratch.jl` itself may want to consider using `BaseDirs` to put the cache files in the platform-appropriate location.

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [May 17, 2025, 3:56pm UTC](https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953/4 "2025-05-17T15:56:50Z")

</div>

Version 1.3 has just been released, and includes a few nice improvements:

- The accessor functions `BaseDirs.User.cache`, `BaseDirs.User.runtime` and, `BaseDirs.User.state` have been copied into the top-level module since they don’t conflict with any system directories.
- A `BaseDirs.Project` can now be constructed from a module, and modules can be passed as the first argument of an accessor function.
- Together these first two changes let you simplify `BaseDirs.User.cache(BaseDirs.Project("MyModule"), ...)` to `BaseDirs.cache(MyModule, ...)`
- Warnings when a BaseDirs result is illegally baked into precompilation are now raised
- TTFX has been further improved, I’m now seeing 3.5ms on my machine

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [June 21, 2026, 12:24pm UTC](https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953/5 "2026-06-21T12:24:12Z")

</div>

It’s funny, this is exactly the sort of package you’d think could have a v1.0 release and be done/complete, but there’s a long tail of subtle bugfixes/polish/tweaks to be made. Along these lines, I’d like to announce:

### Version 1.4 of BaseDirs

#### Future breaking changes

- `Project` has been renamed to the more apt `App` (with a depwarn’d alias for backward compat until v2.0)

#### Linux improvements

- On systemd sandbox `DynamicUser` runtime, state, cache, and configuration sandbox paths are now recognised and honoured. We use the (rather generically named) systemd env vars only when the current process’ cgroup ends with `.service`. If multiple directories are listed, we just use the first.
- We support the recently enabled XDG projects directory (`User.projects`)
- We now read the system default dirs (`/etc/xdg/user-dirs.defaults`) before applying the user’s dir customisations
- Fixed an inversion of the per-user desktop directory config check

#### Other improvements

- `App` (ex. `Project`) is now fully concrete (fixed oversight)
- Reduced allocations when doing ASCII path-folding
- Windows now defaults to `~/bin` when there is no user bin-like directory on PATH
- More consistent handling of XDG dir env vars on non-unix systems (obey if set)
- `App(::Module)` now uses `moduleroot` to ensure that nested submodules resolve to the correct package name when using `App(@ __MODULE__ )`
- A whole bunch of docstring typo fixes
- TTFX is all the way down to \<1ms on Julia 1.13-rc1

I also looked into JuliaC support for this release. It turns out that BaseDirs works a treat with JuliaC as-is …except for the precompilation warning code. As soon as there’s a way to exclude that code from compilation, BaseDirs will “just work” with JuliaC (I imagine this could be useful for anybody wanting to create a well-behaved cross-platform executable — using the system state/cache dirs becomes particularly important when you can’t assume `~/.julia` exists).

---

<div class="post-metadata">

**Author:** ![klafyvel](https://avatars.discourse-cdn.com/v4/letter/k/a587f6/32.png) [@klafyvel](https://discourse.julialang.org/u/klafyvel)\
**Post date:** [June 21, 2026, 2:26pm UTC](https://discourse.julialang.org/t/ann-basedirs-jl-was-xdg/95953/6 "2026-06-21T14:26:58Z")

</div>

Thanks for the work on that package, it’s one of these tools that I keep using without even thinking about it anymore!
