Skip to content
Configuration

Configuration

The TOML config is the behavior. Nothing about a particular library is compiled into the binary.

Where the config comes from

Resolution order — the first file that exists wins:

  1. --config / -c
  2. $SUBTRACE_CONFIG
  3. ./subtrace.toml
  4. $XDG_CONFIG_HOME/subtrace/subtrace.toml (~/.config/subtrace/subtrace.toml)
  5. /config/subtrace.toml — the container default

If none exists, subtrace exits telling you where it looked and how to write one:

subtrace config init > subtrace.toml

How values are resolved

    flowchart LR
  A["Default()<br>built-in defaults"] --> B["decode subtrace.toml<br>over the defaults"]
  B --> C["applyEnv()<br>environment wins"]
  C --> D["applyFallbacks()<br>host-dependent defaults"]
  D --> E["Validate()"]
  

Two consequences worth remembering:

  • Environment beats file. That is how a container gets credentials without writing them to a mounted file.
  • A partial config is fine. Every optional field starts populated, so a file containing only [[library]] blocks is a working config.

Checking your config

subtrace config show       # effective config, secrets masked, after env + fallbacks
subtrace config validate   # parse and check; touches no network

config show is the honest answer to “what is subtrace actually using?” — it prints values after environment overrides and fallbacks have been applied, and masks every secret except its last four characters.

What validation rejects

  • no [[library]] blocks at all
  • a library with an empty path, or kind that is not movie or tv
  • the same library path listed twice
  • one library root nested inside another (it would walk the same files twice and inflate every count)
  • subtitles.naming without {basename}
  • an unknown provider name in providers.order
  • every provider disabled
  • run.interval that is not a Go duration ("12h", "90m")

A TOML trap in this file

A bare key written after a table belongs to that table. order lives under [providers], so moving it below [subtitles] silently turns it into subtitles.order instead of failing:

[subtitles]
languages = ["en"]

order = ["subdl"]   # WRONG: this is now subtitles.order and is ignored

Keep order immediately under its [providers] header.