Concordat's local configuration, credentials, caches, and state live under the XDG base directories. A single global headline file names the active configured owner; per-owner configuration, credentials, estate caches, and state are namespaced beneath that owner, while the OpenTofu provider plugin cache is shared across owners, since provider binaries are identical regardless of owner:
$XDG_CONFIG_HOME/concordat/config.yaml— the headline config, global rather than owner-namespaced; itsgithub_ownerkey names the active owner. Manage it withconcordat owner use <owner>and inspect it withconcordat owner show.$XDG_CONFIG_HOME/concordat/owners/<owner>/config.yaml— that owner's estates and active estate.$XDG_CONFIG_HOME/concordat/owners/<owner>/credentials.yaml— optional credential fallbacks, mapping credential environment-variable names (GITHUB_TOKEN,SCW_ACCESS_KEY,SCW_SECRET_KEY,AWS_*,SPACES_*) to values. Environment variables always win. The file must bechmod 600: concordat refuses to read one carrying any group or world permission bit. Concordat never writes this file.$XDG_CACHE_HOME/concordat/owners/<owner>/estates/<alias>— estate repository caches.$XDG_CACHE_HOME/concordat/tofu/plugin-cache— the shared OpenTofu provider plugin cache (exported asTF_PLUGIN_CACHE_DIRunless already set).$XDG_STATE_HOME/concordat/owners/<owner>/runs/— throwaway OpenTofu working trees; removed after each run unless--keep-workdiris given.
Remote OpenTofu state stored in the configured S3 backend (for example Scaleway Object Storage) is unaffected by this layout.
Migration from the legacy flat format. Older releases wrote estates
directly into $XDG_CONFIG_HOME/concordat/config.yaml — the same path the
headline config now occupies. A file found there carrying an estate section
is therefore a legacy configuration: its estates are moved into
owners/<owner>/config.yaml automatically the first time the owner can be
derived from those records, and the headline file is rewritten with only its
github_owner key and any other non-estate settings.