How loading works
The load_from_iter method (used by the convenience load) performs the
following steps:
-
Builds a
figmentconfiguration profile. A defaults provider constructed from the#[ortho_config(default = …)]attributes is added first. -
Attempts to load a configuration file. Candidate file paths are searched in the following order:
-
If provided, a path supplied via the CLI flag generated by the
discovery(...)attribute (which defaults to a hidden--config-path) or the<PREFIX>CONFIG_PATHenvironment variable (for example,APP_CONFIG_PATHorCONFIG_PATH) takes precedence; see Config path override. -
A dotfile named
.<prefix>.tomlin the current working directory. -
A dotfile of the same name in the user's home directory.
-
On Unix‑like systems, the XDG configuration directory (e.g.
~/.config/app/config.toml) is searched using thexdgcrate; on Windows, the%APPDATA%and%LOCALAPPDATA%directories are checked. -
If the
json5oryamlfeatures are enabled, files with.json,.json5,.yaml, or.ymlextensions are also considered in these locations.
-
-
Adds an environment provider using the prefix specified on the struct. Keys are upper‑cased and nested fields use double underscores (
__) to separate components. -
Adds a provider containing the CLI values (captured as
Option<T>fields) as the final layer. -
Merges vector fields according to the
merge_strategy(currently onlyappend) so that lists of values from lower precedence sources are extended with values from higher precedence ones. -
Attempts to extract the merged configuration into the concrete struct. On success it returns the completed configuration; otherwise an
OrthoErroris returned.
Config path override
The derive macro always recognises a configuration override flag and the
associated environment variables even when you do not declare a field
explicitly. By default a hidden --config-path flag is accepted alongside
<PREFIX>CONFIG_PATH and the unprefixed CONFIG_PATH. Applying the
struct-level discovery(...) attribute customises this behaviour, allowing you
to rename or expose the CLI flag and adjust the filenames searched during
discovery:
#[derive(Debug, Deserialize, ortho_config::OrthoConfig)]
#[ortho_config(
prefix = "APP_",
discovery(
app_name = "demo",
env_var = "DEMO_CONFIG_PATH",
config_file_name = "demo.toml",
dotfile_name = ".demo.toml",
project_file_name = ".demo.toml",
config_cli_long = "config",
config_cli_short = 'c',
config_cli_visible = true,
)
)]
struct CliArgs {
#[ortho_config(default = 8080)]
port: u16,
}
The snippet above exposes a visible --config/-c flag, renames the
environment override to DEMO_CONFIG_PATH, and instructs discovery to search
for demo.toml (and .demo.toml) within the standard directories. Omitting
config_cli_visible keeps the flag hidden while still parsing it, and leaving
config_cli_short unset skips the short alias. When the discovery(...)
attribute is absent, the defaults—hidden --config-path, <PREFIX>CONFIG_PATH
and CONFIG_PATH, and the automatically derived dotfile names—remain in effect.
Source precedence
Values are loaded from each layer in a specific order. Later layers override earlier ones. The precedence, from lowest to highest, is:
-
Application‑defined defaults – values provided via
defaultattributes orOption<T>fields are considered defaults. -
Configuration file – values from a TOML (or JSON5/YAML) file loaded from one of the paths listed above.
-
Environment variables – variables prefixed with the struct's
prefix(e.g.APP_PORT,APP_DATABASE__URL) override file values. -
Command‑line arguments – values parsed by
clapoverride all other sources.
Nested structs are flattened in the environment namespace by joining field
names with double underscores. For example, if AppConfig has a nested
database field and the prefix is APP, then APP_DATABASE__URL sets the
database.url field. If a nested struct has its own prefix attribute, that
prefix is used for its fields (e.g. APP_DB_URL).
When clap's flatten attribute is employed to compose argument groups, the
flattened struct is initialized even if no CLI flags within the group are
specified. During merging, ortho_config discards these empty groups so that
values from configuration files or the environment remain in place unless a
field is explicitly supplied on the command line.
Using defaults and optional fields
Fields of type Option<T> are treated as optional values. If no source
provides a value for an Option<T> field then it remains None. To provide a
default value for a non‑Option field or for an Option<T> field that should
have an initial value, specify #[ortho_config(default = expr)]. This default
acts as the lowest‑precedence source and is overridden by file, environment or
CLI values.
Environment variable naming
Environment variables are upper‑cased and use underscores. The struct‑level
prefix (if supplied) is prepended without any separator, and nested fields are
separated by double underscores. For the AppConfig and DatabaseConfig
example above, valid environment variables include
APP_LOG_LEVEL, APP_PORT, APP_DATABASE__URL and APP_DATABASE__POOL_SIZE.
If the nested struct has its own prefix (DB), then the environment variable
becomes APP_DB_URL.
Comma-separated values such as DDLINT_RULES=A,B,C are parsed as lists. The
loader converts these strings into arrays before merging, so array fields
behave the same across environment variables, CLI arguments and configuration
files. Values containing literal commas must be wrapped in quotes or brackets
to disable list parsing.