XDG Config Directories

Because littering ~ with dotfiles is so 1990s. ParseArger can generate XDG Base Directory compliant configuration handling for your scripts. Works on Linux, macOS, and even Windows (if you're into that).

What is XDG?

The XDG Base Directory Specification defines where your app should store its config, data, and cache. No more ~/.myapp, ~/.myapprc, ~/.myapp.conf chaos.

DirectoryPurposeDefault
XDG_CONFIG_HOMEUser configuration~/.config
XDG_DATA_HOMEUser data files~/.local/share
XDG_CACHE_HOMENon-essential cache~/.cache

Basic Usage

Add XDG support to your script with the --xdg option:

>
parseArger generate \
  --xdg "myapp" \
  --help-message "My awesome app" \
  --output ./myapp.sh

Or use the annotation in an existing script:

# @parseArger-xdg "myapp" --config --data --cache

This generates helper functions and automatically initializes your config directories when the script runs. Your users' home directories will thank you.

Options

  • --xdg <app-name>: Enable XDG support with the given app name. This name becomes your subdirectory in the XDG paths.
    parseArger generate --xdg "myapp"

    Creates: ~/.config/myapp/, ~/.local/share/myapp/

  • --xdg-config / --no-xdg-config: Enable/disable config directory support. On by default.
    parseArger generate --xdg "myapp" --no-xdg-config
  • --xdg-data / --no-xdg-data: Enable/disable data directory support. On by default.
    parseArger generate --xdg "myapp" --no-xdg-data
  • --xdg-cache / --no-xdg-cache: Enable/disable cache directory support. Off by default.
    parseArger generate --xdg "myapp" --xdg-cache
  • --xdg-config-file <name>: Name of the config file. Default is config.
    parseArger generate --xdg "myapp" --xdg-config-file "settings.conf"

Generated Functions

Your script gets a bunch of helper functions. Use them. They're nice.

Directory Functions

  • xdg_init(): Initializes all XDG paths. Called automatically after argument parsing.
  • xdg_config_dir(): Returns the config directory path.
    config_path=$(xdg_config_dir)
    echo "Config is at: $config_path"
  • xdg_data_dir(): Returns the data directory path.
  • xdg_cache_dir(): Returns the cache directory path.
  • xdg_ensure_config_dir(): Creates the config directory if it doesn't exist.
  • xdg_ensure_data_dir(): Creates the data directory if it doesn't exist.
  • xdg_ensure_cache_dir(): Creates the cache directory if it doesn't exist.

Config File Functions

Because you probably want to actually store and read config values:

  • xdg_config_file(): Returns the full path to the config file.
  • xdg_load_config(): Sources the config file. Returns 0 if loaded, 1 if file doesn't exist.
    if xdg_load_config; then
      echo "Loaded config, API_KEY is: $API_KEY"
    else
      echo "No config file yet"
    fi
  • xdg_save_config VAR VALUE: Save a variable to the config file.
    xdg_save_config "API_KEY" "sk-12345"
    xdg_save_config "DEBUG=true"  # Also works
  • xdg_get_config VAR: Get a value without sourcing the whole file.
    api_key=$(xdg_get_config "API_KEY")
    if [ -n "$api_key" ]; then
      echo "Found key: $api_key"
    fi
  • xdg_remove_config VAR: Remove a variable from the config file.
    xdg_remove_config "OLD_SETTING"

Full Example

Here's a complete script that uses XDG config:

>
parseArger generate \
  --xdg "myapp" \
  --xdg-config-file "settings" \
  --opt 'api-key "API key for the service"' \
  --flag 'save "Save the key for future use"' \
  --help-message "My API Client" \
  --output ./api-client.sh

Then add your business logic at the end:

# Your code after # @parseArger-end

# Try to load saved config
xdg_load_config

# Use provided key or fall back to saved one
api_key="${_arg_api_key:-$API_KEY}"

if [ -z "$api_key" ]; then
  die "No API key provided. Use --api-key or save one with --save"
fi

# Save for next time if requested
if [ "$_arg_save" == "on" ]; then
  xdg_save_config "API_KEY" "$api_key"
  echo "API key saved to $(xdg_config_file)"
fi

# Do the actual work
echo "Making API call with key: ${api_key:0:8}..."
# curl -H "Authorization: Bearer $api_key" ...

Cross-Platform Magic

The generated code detects your platform and does the right thing:

PlatformConfig DefaultData Default
Linux~/.config/app~/.local/share/app
macOS~/.config/app~/.local/share/app
Windows (Git Bash)%APPDATA%/app%LOCALAPPDATA%/app

Generated Variables

Behind the scenes, these variables are available in your script:

  • $_xdg_app_name - Your app name
  • $_xdg_config_file - Config filename
  • $_xdg_config_home - Full path to config dir
  • $_xdg_data_home - Full path to data dir
  • $_xdg_cache_home - Full path to cache dir