Configuration
Configuration
The TOML config is the behavior. Nothing about a particular library is compiled into the binary.
Every section and key, with defaults.
What can be overridden without touching the file.
ignore_dirs, globs, and the * vs ** rule.
Where the config comes from
Resolution order — the first file that exists wins:
--config/-c$SUBTRACE_CONFIG./subtrace.toml$XDG_CONFIG_HOME/subtrace/subtrace.toml(~/.config/subtrace/subtrace.toml)/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.tomlHow 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 networkconfig 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
kindthat is notmovieortv - the same library path listed twice
- one library root nested inside another (it would walk the same files twice and inflate every count)
subtitles.namingwithout{basename}- an unknown provider name in
providers.order - every provider disabled
run.intervalthat 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 ignoredKeep order immediately under its [providers] header.