Skip to content

Configuration

Where keryx reads configuration from, in what order it wins, and what happens when a value is missing or wrong. The keys themselves are on the configuration keys page.

Which files keryx reads

Four files, in two scopes.

~/.keryx/config.yaml must exist before any command will run. Without it, every command that does real work fails with:

failed to load configuration: no config file found hints="Run 'keryx init' to create a configuration."

keryx init writes it. The other three files are genuinely optional.

File Scope Holds
~/.keryx/config.yaml per user tool settings, provider selection, defaults
~/.keryx/themes.yaml per user the style library (themes.*)
~/.keryx/accounts.yaml per user platform credentials, and nothing else
.keryx.yaml per project the project's own settings, committed with the repo

The user directory is ~/.keryx — the home directory plus a dot and the tool name. It is not ~/.config/keryx, and XDG_CONFIG_HOME does not move it.

The project file is discovered by walking up from the working directory, so keryx run from anywhere inside the repo finds the same .keryx.yaml. This is what lets a blog repo carry its own themes and provider choices while the machine-wide file holds the API-independent preferences.

Which layer wins

Highest precedence first:

  1. Command-line flags you actually changed. A flag left at its default contributes nothing.
  2. The project .keryx.yaml.
  3. ~/.keryx/accounts.yaml, then ~/.keryx/themes.yaml, then ~/.keryx/config.yaml.
  4. Built-in defaults compiled into the binary.

The specialised user files outrank config.yaml deliberately. They are the canonical homes for credentials and themes, and a stale value left behind in config.yaml must not shadow the one that has been migrated out of it — which is what auth migrate and theme migrate do.

Merging is per key, not per file: a project file that sets only workspace.root still inherits every theme from the user library.

Environment variables do not override config keys

There is no environment-variable layer. keryx sets no env prefix, and the configuration store is built from files and flags only. Setting WORKSPACE_ROOT, PROVIDERS_IMAGE or KERYX_PROVIDERS_IMAGE has no effect on any config key.

Environment variables are used, but only where a specific piece of code reads a specific named variable — API keys, platform secrets, and the ffmpeg-wasi module path. Those are enumerated on the environment variables page. That list is exhaustive; anything not on it is not read.

What happens when a value is wrong

keryx fails at the point the value is used, naming the key and what it accepts.

Situation What you get
Unknown providers.<capability> unknown provider: <capability>="<name>" (available: …) listing the registered adapters
Unknown storage.provider unknown provider: storage.provider="<name>" (available: azure, file, gcs, mem, s3)
storage.provider unset Not an error — local-only mode. Media sync commands report the store as unconfigured and skip.
storage.s3.bucket unset with storage.provider: s3 storage.s3.bucket is not set
Unknown auth.writeback.backend unknown writeback backend "<name>" (have: local, gitlab)
Unknown auth.alerts.backend unknown alerts backend "<name>" (have: none, webhook, email)
Unknown tls.source No error — anything other than localca degrades to a self-signed certificate, and HTTPS is still served
A theme keyword that does not exist theme not found
No default theme for a type no theme configured for this type — add one with \keryx theme add --type ``
Malformed YAML in any layer The command refuses to run: failed to load configuration: … config: source could not be parsed: <path> document 0: yaml: line N: …. The path and line are named; keryx does not fall back to the other layers.

The two config shapes a key can have, and why it matters

Some providers.* keys are scalars (providers.render: afmpeg) and some are maps (providers.render.module: /path/to.wasm). YAML cannot give one key both shapes, and neither can the layer stack — the highest-precedence layer's shape wins outright and the other form resolves to empty.

The practical consequences are on configuration keys; the short version is that the module-override keys under providers.render.* cannot be combined with providers.render: afmpeg, and KERYX_FFMPEG_WASI is the working route.

Writing configuration from the tools

  • keryx theme add and friends write themes.* into ~/.keryx/themes.yaml or the project file, preserving comments and key order.
  • keryx auth writes credentials into ~/.keryx/accounts.yaml.
  • The studio Settings panel writes a fixed allowlist of non-secret keys into the active project's .keryx.yaml. It refuses every key outside that list, so no secret can be written through it.

Two of the keys on that allowlist do not do what the panel implies. The provider pickers write providers.image.provider, providers.voice.provider and so on, but the adapter is selected from the scalar providers.image — so a provider chosen in the panel is not the one keryx uses. And git.auto_push ("push on save") is read by nothing at all.

Hand-editing any of these files is supported and expected; nothing keeps a shadow copy.