Flyctl should follow the XDG Base Directory Specification

https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

The $HOME/.fly directory should be moved to the appropriate directory under the XDG Base Directory Specification. $XDG_CONFIG_HOME/fly is probably appropriate. If t

3 Likes

I think we’re interested in being respectful of stuff like this, but no system I have has XDG_CONFIG_HOME set, including my Linux dev system. Can you say more about which users would be helped out by us adding the corner-case code for this?

Like, obviously, we’re not going to write Fly state to /etc/xdg on macOS.

If XDG_CONFIG_HOME is unset, the spec says apps will have to assume a default (~/.config).

Also, on MacOS, ~/Library/Preferences/fly would be a better place for this over ~/.fly.

1 Like

Here’s a go library that figures out the correct directory with sensible defaults for Windows, Linux, OSX, and Plan 9: GitHub - adrg/xdg: Go implementation of the XDG Base Directory Specification and XDG user directories

It’s not really corner-case code right? A lot of the apps that I use daily follow the spec now. gcloud follows the spec correctly. If you open up ~/.config on your dev machine, you’ll see which apps follow this spec too.

1 Like

Gotcha. It’s worth thinking about! Thanks for bringing it up.

1 Like

I just want to confirm that it would be really great if flyctl would honor the XDG system path variables, especially XDG_CONFIG_HOME so my home directory wouldn’t get cluttered. I just tried to tidy up and move all config stuff to $HOME/.config which I defined in XDG_CONFIG_HOME to be the new path for config files. Unfortunately, flyctl is one of the offenders that don’t seem honor user settings. :frowning:

Hi! It’d be nice for the XDG spec to be thought about and respected, falling back to $HOME only when necessary.

Here’s what my XDG env vars look like:

export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" 
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" 
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" 
export XDG_LIB_HOME="${XDG_LIB_HOME:-$HOME/.local/lib}" 
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"

There are different locations for different types of data, and one small example reason for co-locating this type of data is when you want to clear out your cache from services: it’s all in one place.

A good resource for support with common tools: XDG Base Directory - ArchWiki

@thomas For reference, here is what a successful open source discussion and result looks like for XDG on a widely used CLI looks like: Adhere to XDG Base Desktop Specification · Issue #2574 · pnpm/pnpm · GitHub

I’ll repost the same comment I originally made there, as it’s universally applicable.

Here is the corresponding issue for Yarn: yarnpkg/yarn#2334
And npm: npm/npm#6675
And poetry: python-poetry/poetry#1239

I’ve noticed many projects follow this pattern:

  1. Hard-code os.UserHomeDir() (or equivalent).
  2. Project becomes popular.
  3. Support XDG issue is opened.
  4. Issue stays open for n-years (pretty much the same back and forth happens in each project between users and maintainers).
  5. Users beg for workarounds to keep their homedir pollution under control.
  6. If users are lucky XDG support is eventually added.

While we wait for for step 4 to run it’s course, I recommend (plead :pray:t2: ) swapping out all the hard-coded os.UserHomeDir() calls today for something like env.FLY_HOME || os.UserHomeDir(). Then at least the users can implement their workarounds now while the maintainers decide if XDG is right for them. :smile:

1 Like

no system I have has XDG_CONFIG_HOME set, including my Linux dev system

@thomas That’s as expected — that env var won’t be set unless you’ve set it. It provides a means to customize the XDG spec’s defaults.

If there’s support from maintainers for this, I’d be happy to take the time to implement it.

The XDG base directory spec is pretty widely supported at this point.

The core of the change would be in flyctl/flyctl/flyctl.go:

func initConfigDir() error {
        homeDir, err := os.UserHomeDir()
        if err != nil {
                return err
        }


        dir := filepath.Join(homeDir, ".fly")


        if !helpers.DirectoryExists(dir) {
                if err := os.MkdirAll(dir, 0o700); err != nil {
                        return err
                }
        }


        configDir = dir


        return nil
}