Source profileQuality 96/100

Jamie-BitFlight/claude_skills/plugins/xdg-base-directory/skills/xdg-base-directory/SKILL.md

xdg-base-directory

When an application needs to store config, data, cache, or state files. When designing where user-specific files should live. When code writes to ~/.appname or hardcoded home paths. When implementing cross-platform file storage with platformdirs.

Source repository stars
64
Declared platforms
0
Static risk flags
0
Last source update
2026-08-28
Source checked
2026-08-28

Decision brief

What it does: where it fits

Implement standardized directory paths for configuration, data, cache, and state files following the XDG Base Directory Specification.

Best for

  • Creating CLI tools or applications that store user-specific files
  • Implementing configuration file management for Linux/Unix applications
  • Building cross-platform Python applications requiring standardized directory paths

Not for

  • 1. Using /.appname (Legacy Pattern)
  • 2. Ignoring Environment Variables

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/Jamie-BitFlight/claude_skills --skill "plugins/xdg-base-directory/skills/xdg-base-directory"
Safe inspection promptEditorial

Inspect the Agent Skill "xdg-base-directory" from https://github.com/Jamie-BitFlight/claude_skills/blob/a00194f25fec502d3d659b7d610369614967251e/plugins/xdg-base-directory/skills/xdg-base-directory/SKILL.md at commit a00194f25fec502d3d659b7d610369614967251e. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Python Implementation Patterns

    Use for applications targeting only Linux/Unix systems or requiring no dependencies.

    Use for applications targeting only Linux/Unix systems or requiring no dependencies.Create a dedicated paths module for your application:For applications targeting Linux, macOS, and Windows, use the platformdirs library:
  2. 02

    Stdlib-Only Implementation

    Use for applications targeting only Linux/Unix systems or requiring no dependencies.

    Use for applications targeting only Linux/Unix systems or requiring no dependencies.
  3. 03

    Cross-Platform Implementation with platformdirs

    For applications targeting Linux, macOS, and Windows, use the platformdirs library:

    For applications targeting Linux, macOS, and Windows, use the platformdirs library:python """Cross-platform path management using platformdirs."""from platformdirs import userconfigdir, userdatadir, usercachedir, userstatedir from pathlib import Path
  4. 04

    Implementation Guides

    ArchWiki: XDG Base Directory - Comprehensive implementation guide (accessed 2025-01-15)

    ArchWiki: XDG Base Directory - Comprehensive implementation guide (accessed 2025-01-15)platformdirs Python Library - Cross-platform Python implementation (accessed 2025-01-15)- ArchWiki: XDG Base Directory - Comprehensive implementation guide (accessed 2025-01-15) - platformdirs Python Library - Cross-platform Python implementation (accessed 2025-01-15)
  5. 05

    When to Use This Skill

    Creating CLI tools or applications that store user-specific files

    Creating CLI tools or applications that store user-specific filesImplementing configuration file management for Linux/Unix applicationsBuilding cross-platform Python applications requiring standardized directory paths

Permission review

Static risk signals and limitations

No configured static risk pattern was detected

This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score96/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars64SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
Jamie-BitFlight/claude_skills
Skill path
plugins/xdg-base-directory/skills/xdg-base-directory/SKILL.md
Commit
a00194f25fec502d3d659b7d610369614967251e
License
MIT
Collected
2026-08-28
Default branch
main
View the original SKILL.md

XDG Base Directory Specification

Implement standardized directory paths for configuration, data, cache, and state files following the XDG Base Directory Specification.

When to Use This Skill

Use this skill when:

  • Creating CLI tools or applications that store user-specific files
  • Implementing configuration file management for Linux/Unix applications
  • Building cross-platform Python applications requiring standardized directory paths
  • Migrating legacy applications from ~/.appname to XDG-compliant paths
  • Designing file storage architecture for Python packages
  • Implementing proper environment variable handling for user directories
  • Writing applications that respect user-configured directory preferences
  • Testing applications with custom XDG directory overrides

Core Specification Rules

The XDG Base Directory Specification (version 0.8, May 2021) defines these critical requirements:

1. All Paths Must Be Absolute

Environment variable values MUST be absolute paths. Relative paths are invalid and MUST be ignored.

def validate_xdg_path(path_str: str | None) -> Path | None:
    """Validate XDG path is absolute per specification."""
    if not path_str:
        return None
    path = Path(path_str)
    if not path.is_absolute():
        return None  # Ignore relative paths per spec
    return path

2. Empty Variables Use Defaults

When an environment variable is unset or empty, use the specification-defined default value.

3. Priority Order for Search Paths

  • User-specific directories ($XDG_CONFIG_HOME, $XDG_DATA_HOME) take precedence
  • System directories ($XDG_CONFIG_DIRS, $XDG_DATA_DIRS) searched in order
  • First match wins

4. Colon Separator for Search Paths

$XDG_DATA_DIRS and $XDG_CONFIG_DIRS use colon (:) as path separator, similar to $PATH.

Environment Variables

User-Specific Directories (Single Path)

VariablePurposeDefaultUse For
$XDG_CONFIG_HOMEUser configuration files$HOME/.configSettings, preferences, user configs
$XDG_DATA_HOMEUser data files$HOME/.local/shareDatabases, generated content, persistent data
$XDG_STATE_HOMEUser state files$HOME/.local/stateLogs, history, undo buffers, recent files
$XDG_CACHE_HOMEUser cache files$HOME/.cacheTemporary data, downloaded files, build artifacts
$XDG_RUNTIME_DIRUser runtime filesSystem-set (/run/user/$UID)Sockets, pipes, lock files, IPC

System-Wide Directories (Search Paths)

VariablePurposeDefault
$XDG_DATA_DIRSSystem data search path/usr/local/share/:/usr/share/
$XDG_CONFIG_DIRSSystem config search path/etc/xdg

User Executables (Convention, Not XDG)

PathPurpose
$HOME/.local/binUser-specific executable files

Note: Distributions should ensure $HOME/.local/bin appears in $PATH.

Directory Selection Guide

Choose the appropriate directory based on data characteristics:

Use $XDG_CONFIG_HOME for:

  • Application settings and preferences
  • User-specific configuration files
  • TOML/YAML/JSON configuration
  • Example: ~/.config/myapp/config.toml

Use $XDG_DATA_HOME for:

  • Persistent application data
  • User-generated content
  • Downloaded models or assets
  • Database files
  • Example: ~/.local/share/myapp/models/model.gguf

Use $XDG_STATE_HOME for:

  • Action history (command history, undo buffers)
  • Application state that can be regenerated
  • Recently used files lists
  • Log files specific to user actions
  • Example: ~/.local/state/myapp/history.log

Use $XDG_CACHE_HOME for:

  • Temporary files safe to delete
  • Downloaded data that can be re-fetched
  • Build artifacts and compiled files
  • Thumbnail caches
  • Example: ~/.cache/myapp/downloads/

Use $XDG_RUNTIME_DIR for:

  • Unix domain sockets
  • Named pipes (FIFOs)
  • Lock files
  • Temporary IPC files
  • Warning: Often tmpfs-mounted with size limits; avoid large files
  • Warning: Cleaned on logout; do not store persistent data
  • Example: /run/user/1000/myapp/socket

Python Implementation Patterns

Stdlib-Only Implementation

Use for applications targeting only Linux/Unix systems or requiring no dependencies.

"""XDG Base Directory compliant path management using stdlib only."""

from pathlib import Path
import os


def get_config_home() -> Path:
    """Get XDG_CONFIG_HOME path.

    Returns user-specific configuration directory.
    Falls back to $HOME/.config if XDG_CONFIG_HOME unset or relative.
    """
    xdg = os.environ.get("XDG_CONFIG_HOME")
    if xdg and Path(xdg).is_absolute():
        return Path(xdg)
    return Path.home() / ".config"


def get_data_home() -> Path:
    """Get XDG_DATA_HOME path.

    Returns user-specific data directory.
    Falls back to $HOME/.local/share if XDG_DATA_HOME unset or relative.
    """
    xdg = os.environ.get("XDG_DATA_HOME")
    if xdg and Path(xdg).is_absolute():
        return Path(xdg)
    return Path.home() / ".local" / "share"


def get_state_home() -> Path:
    """Get XDG_STATE_HOME path.

    Returns user-specific state directory.
    Falls back to $HOME/.local/state if XDG_STATE_HOME unset or relative.
    """
    xdg = os.environ.get("XDG_STATE_HOME")
    if xdg and Path(xdg).is_absolute():
        return Path(xdg)
    return Path.home() / ".local" / "state"


def get_cache_home() -> Path:
    """Get XDG_CACHE_HOME path.

    Returns user-specific cache directory.
    Falls back to $HOME/.cache if XDG_CACHE_HOME unset or relative.
    """
    xdg = os.environ.get("XDG_CACHE_HOME")
    if xdg and Path(xdg).is_absolute():
        return Path(xdg)
    return Path.home() / ".cache"


def get_runtime_dir() -> Path | None:
    """Get XDG_RUNTIME_DIR path.

    Returns user-specific runtime directory, or None if not set.
    This variable has no default - it must be set by the system.
    """
    xdg = os.environ.get("XDG_RUNTIME_DIR")
    if xdg and Path(xdg).is_absolute():
        return Path(xdg)
    return None


def get_config_dirs() -> list[Path]:
    """Get XDG_CONFIG_DIRS as list of paths.

    Returns preference-ordered list of system configuration directories.
    Falls back to [Path('/etc/xdg')] if XDG_CONFIG_DIRS unset.
    """
    xdg = os.environ.get("XDG_CONFIG_DIRS")
    if xdg:
        paths = [Path(p) for p in xdg.split(":") if p and Path(p).is_absolute()]
        if paths:
            return paths
    return [Path("/etc/xdg")]


def get_data_dirs() -> list[Path]:
    """Get XDG_DATA_DIRS as list of paths.

    Returns preference-ordered list of system data directories.
    Falls back to [Path('/usr/local/share'), Path('/usr/share')] if unset.
    """
    xdg = os.environ.get("XDG_DATA_DIRS")
    if xdg:
        paths = [Path(p) for p in xdg.split(":") if p and Path(p).is_absolute()]
        if paths:
            return paths
    return [Path("/usr/local/share"), Path("/usr/share")]

Application-Specific Path Module

Create a dedicated paths module for your application:

"""Path management for myapp following XDG specification."""

from pathlib import Path
import os

APP_NAME = "myapp"


def get_config_dir() -> Path:
    """Get myapp config directory."""
    xdg = os.environ.get("XDG_CONFIG_HOME")
    base = Path(xdg) if xdg and Path(xdg).is_absolute() else Path.home() / ".config"
    return base / APP_NAME


def get_config_file() -> Path:
    """Get myapp config file path."""
    return get_config_dir() / "config.toml"


def get_data_dir() -> Path:
    """Get myapp data directory."""
    xdg = os.environ.get("XDG_DATA_HOME")
    base = Path(xdg) if xdg and Path(xdg).is_absolute() else Path.home() / ".local" / "share"
    return base / APP_NAME


def get_cache_dir() -> Path:
    """Get myapp cache directory."""
    xdg = os.environ.get("XDG_CACHE_HOME")
    base = Path(xdg) if xdg and Path(xdg).is_absolute() else Path.home() / ".cache"
    return base / APP_NAME


def get_state_dir() -> Path:
    """Get myapp state directory."""
    xdg = os.environ.get("XDG_STATE_HOME")
    base = Path(xdg) if xdg and Path(xdg).is_absolute() else Path.home() / ".local" / "state"
    return base / APP_NAME


def ensure_directories() -> None:
    """Create all required directories with appropriate permissions."""
    for directory in [get_config_dir(), get_data_dir(), get_cache_dir(), get_state_dir()]:
        directory.mkdir(parents=True, exist_ok=True)

Cross-Platform Implementation with platformdirs

For applications targeting Linux, macOS, and Windows, use the platformdirs library:

"""Cross-platform path management using platformdirs."""

from platformdirs import user_config_dir, user_data_dir, user_cache_dir, user_state_dir
from pathlib import Path

APP_NAME = "myapp"
APP_AUTHOR = "myapp"  # Used on Windows

# Get platform-appropriate directories
# Linux: Uses XDG specification
# macOS: Uses ~/Library/Application Support, ~/Library/Caches
# Windows: Uses %APPDATA%, %LOCALAPPDATA%

config_dir = Path(user_config_dir(APP_NAME, APP_AUTHOR))
data_dir = Path(user_data_dir(APP_NAME, APP_AUTHOR))
cache_dir = Path(user_cache_dir(APP_NAME, APP_AUTHOR))
state_dir = Path(user_state_dir(APP_NAME, APP_AUTHOR))

# Auto-create directories
config_dir = Path(user_config_dir(APP_NAME, APP_AUTHOR, ensure_exists=True))

Platform-specific paths:

PlatformConfigDataCacheState
Linux~/.config/myapp~/.local/share/myapp~/.cache/myapp~/.local/state/myapp
macOS~/Library/Application Support/myapp~/Library/Application Support/myapp~/Library/Caches/myapp~/Library/Application Support/myapp
WindowsC:\Users\<user>\AppData\Local\myapp\myappC:\Users\<user>\AppData\Local\myapp\myappC:\Users\<user>\AppData\Local\myapp\myapp\CacheC:\Users\<user>\AppData\Local\myapp\myapp

When to use platformdirs:

  • Application targets multiple operating systems
  • Need native platform conventions (macOS ~/Library, Windows %APPDATA%)
  • Want automatic directory creation with ensure_exists=True

When to use stdlib-only:

  • Application targets only Linux/Unix
  • Minimize dependencies
  • Need complete control over path resolution logic

Common Anti-Patterns

1. Using ~/.appname (Legacy Pattern)

Problem: Violates XDG specification, clutters home directory.

# ❌ WRONG
config_file = Path.home() / ".myapp" / "config.toml"

Solution: Use ~/.config/appname/

# ✅ CORRECT
def get_config_dir() -> Path:
    xdg = os.environ.get("XDG_CONFIG_HOME")
    base = Path(xdg) if xdg and Path(xdg).is_absolute() else Path.home() / ".config"
    return base / "myapp"


config_file = get_config_dir() / "config.toml"

2. Ignoring Environment Variables

Problem: Hardcoded paths prevent user customization.

# ❌ WRONG
config_dir = Path.home() / ".config" / "myapp"

Solution: Always check environment variables first.

# ✅ CORRECT
xdg = os.environ.get("XDG_CONFIG_HOME")
base = Path(xdg) if xdg and Path(xdg).is_absolute() else Path.home() / ".config"
config_dir = base / "myapp"

3. Accepting Relative Paths

Problem: XDG specification mandates absolute paths only.

# ❌ WRONG
xdg = os.environ.get("XDG_CONFIG_HOME", str(Path.home() / ".config"))
return Path(xdg)  # Accepts relative paths

Solution: Validate absolute paths, fall back to default for relative.

# ✅ CORRECT
xdg = os.environ.get("XDG_CONFIG_HOME")
if xdg and Path(xdg).is_absolute():
    return Path(xdg)
return Path.home() / ".config"  # Default for unset or relative

4. Missing Directory Creation

Problem: Writing files without ensuring parent directories exist.

# ❌ WRONG
config_file = get_config_dir() / "config.toml"
config_file.write_text(data)  # Fails if directory doesn't exist

Solution: Create directories before writing files.

# ✅ CORRECT
config_file = get_config_dir() / "config.toml"
config_file.parent.mkdir(parents=True, exist_ok=True)
config_file.write_text(data)

5. Storing Cache in Config Directory

Problem: Mixing regenerable data with configuration.

# ❌ WRONG
cache_file = get_config_dir() / "download_cache.json"

Solution: Use $XDG_CACHE_HOME for regenerable data.

# ✅ CORRECT
cache_file = get_cache_dir() / "download_cache.json"

6. Large Files in Runtime Directory

Problem: $XDG_RUNTIME_DIR often tmpfs-mounted with size limits.

# ❌ WRONG
large_file = get_runtime_dir() / "model.gguf"  # May be 1GB+

Solution: Use $XDG_DATA_HOME for large persistent files.

# ✅ CORRECT
large_file = get_data_dir() / "models" / "model.gguf"

7. Not Handling Unset XDG_RUNTIME_DIR

Problem: $XDG_RUNTIME_DIR has no default value.

# ❌ WRONG
runtime_dir = get_runtime_dir()
socket_path = runtime_dir / "socket"  # Fails if None

Solution: Check for None before using.

# ✅ CORRECT
runtime_dir = get_runtime_dir()
if runtime_dir is None:
    raise RuntimeError("XDG_RUNTIME_DIR not set by system")
socket_path = runtime_dir / "socket"

Testing XDG Compliance

Manual Testing with Environment Variables

# Test with custom XDG directories
export XDG_CONFIG_HOME=/tmp/test-config
export XDG_DATA_HOME=/tmp/test-data
export XDG_CACHE_HOME=/tmp/test-cache
export XDG_STATE_HOME=/tmp/test-state

# Run application
myapp --help

# Verify files are in correct locations
ls -la /tmp/test-config/myapp/
ls -la /tmp/test-data/myapp/
ls -la /tmp/test-cache/myapp/
ls -la /tmp/test-state/myapp/

# Test with unset variables (should use defaults)
unset XDG_CONFIG_HOME XDG_DATA_HOME XDG_CACHE_HOME XDG_STATE_HOME
myapp --help
ls -la ~/.config/myapp/
ls -la ~/.local/share/myapp/
ls -la ~/.cache/myapp/
ls -la ~/.local/state/myapp/

Automated Testing

"""Test XDG compliance."""

import os
import tempfile
from pathlib import Path
import pytest


def test_xdg_config_home_override(monkeypatch):
    """XDG_CONFIG_HOME environment variable is respected."""
    with tempfile.TemporaryDirectory() as tmpdir:
        monkeypatch.setenv("XDG_CONFIG_HOME", tmpdir)
        config_dir = get_config_dir()
        assert config_dir == Path(tmpdir) / "myapp"


def test_xdg_config_home_default(monkeypatch):
    """Default used when XDG_CONFIG_HOME unset."""
    monkeypatch.delenv("XDG_CONFIG_HOME", raising=False)
    config_dir = get_config_dir()
    assert config_dir == Path.home() / ".config" / "myapp"


def test_relative_path_ignored(monkeypatch):
    """Relative paths in XDG variables are ignored per specification."""
    monkeypatch.setenv("XDG_CONFIG_HOME", "relative/path")
    config_dir = get_config_dir()
    # Should fall back to default, not use relative path
    assert config_dir == Path.home() / ".config" / "myapp"


def test_empty_string_uses_default(monkeypatch):
    """Empty string in XDG variable uses default."""
    monkeypatch.setenv("XDG_CONFIG_HOME", "")
    config_dir = get_config_dir()
    assert config_dir == Path.home() / ".config" / "myapp"


def test_runtime_dir_none_when_unset(monkeypatch):
    """XDG_RUNTIME_DIR returns None when unset (no default)."""
    monkeypatch.delenv("XDG_RUNTIME_DIR", raising=False)
    runtime_dir = get_runtime_dir()
    assert runtime_dir is None


def test_config_dirs_search_path(monkeypatch):
    """XDG_CONFIG_DIRS parsed as colon-separated search path."""
    monkeypatch.setenv("XDG_CONFIG_DIRS", "/etc/xdg:/opt/config")
    dirs = get_config_dirs()
    assert dirs == [Path("/etc/xdg"), Path("/opt/config")]


def test_data_dirs_ignores_relative_paths(monkeypatch):
    """XDG_DATA_DIRS filters out relative paths."""
    monkeypatch.setenv("XDG_DATA_DIRS", "/usr/share:relative/path:/opt/data")
    dirs = get_data_dirs()
    assert dirs == [Path("/usr/share"), Path("/opt/data")]

Example Directory Structure

~/.config/myapp/              # XDG_CONFIG_HOME
    config.toml               # Main configuration
    credentials.json          # User credentials

~/.local/share/myapp/         # XDG_DATA_HOME
    models/                   # Downloaded models
        model-v1.gguf
    databases/
        user.db

~/.local/state/myapp/         # XDG_STATE_HOME
    history.log               # Command history
    recent-files.json         # Recently used files

~/.local/bin/                 # User binaries (convention)
    myapp                     # Application binary

~/.cache/myapp/               # XDG_CACHE_HOME
    downloads/                # Downloaded temporary files
    build/                    # Build artifacts

Configuration File Loading Pattern

For TOML configuration files with XDG support, activate the toml-python skill:

Skill(skill: "python3-development:toml-python")

The toml-python skill provides comprehensive guidance on TOML parsing with tomllib (Python 3.11+) and tomli (backport), including validation with Pydantic models.

Related Skills

Activate these skills for related functionality:

  • toml-python - TOML configuration file parsing and validation
  • python3-development - Modern Python development patterns and best practices
  • uv - Python package and project management

References

Official Specification

Implementation Guides

Community Resources

Key Principles

  1. Absolute Paths Only: Validate all XDG paths are absolute; ignore relative paths
  2. Environment Variable Priority: Always check XDG environment variables before defaults
  3. Specification Compliance: Follow XDG Base Directory Specification v0.8 exactly
  4. Directory Creation: Create parent directories before writing files
  5. Appropriate Storage: Use correct directory for data type (config vs data vs cache vs state)
  6. Runtime Directory Limits: Avoid large files in $XDG_RUNTIME_DIR (tmpfs limits)
  7. Cross-Platform Awareness: Use platformdirs for macOS/Windows support
  8. Search Path Handling: Parse colon-separated search paths correctly
  9. No Default for Runtime: $XDG_RUNTIME_DIR has no default; check for None
  10. Testing: Validate XDG compliance with environment variable overrides

Frequently asked questions

What to verify before installation and use

What does the xdg-base-directory source document cover?

Implement standardized directory paths for configuration, data, cache, and state files following the XDG Base Directory Specification.

How do I install xdg-base-directory?

The source record exposes this install command: npx skills add https://github.com/Jamie-BitFlight/claude_skills --skill "plugins/xdg-base-directory/skills/xdg-base-directory". Inspect the command and pinned source before running it.

Alternatives

Compare before choosing

Computed 98262

majiayu000/spellbook

comprehensive-testing

Complete testing strategy covering TDD workflow, test pyramid, unit/integration/E2E/property testing, framework best practices (Jest, Vitest, pytest), mock strategies, and CI integration. Use when writing tests, reviewing test quality, or establishing testing standards.

Computed 97779

rampstackco/claude-skills

data-warehouse-experimentation

Running experiments out of the data warehouse instead of via dedicated experiment platforms. SQL-based assignment, exposure logging discipline, metric definitions in dbt models, statistical analysis in SQL or Python, variance reduction with CUPED, sequential testing, and the operational tradeoffs vs platforms like Statsig and Optimizely. Triggers on warehouse-native experimentation, run experiments in BigQuery, run experiments in Snowflake, dbt experiments, SQL t-test, CUPED variance reduction,

Computed 97273

Aperivue/medsci-skills

calc-sample-size

Interactive sample size calculator for medical research. Decision-tree guided test selection, reproducible R/Python code, effect size interpretation, and IRB-ready justification text. Supports diagnostic accuracy, agreement, proportions, continuous outcomes, survival, ANOVA, logistic regression, and non-inferiority/equivalence designs.

Computed 97211

PramodDutta/qaskills

Pairwise Test Generator

Generate optimized test combinations using pairwise (all-pairs) testing algorithms to achieve maximum coverage with minimum test cases across multiple input parameters