config¶
Feature: Config. Passthrough subtree — --output must appear after the word
config.
config behaves differently depending on whether the host tool called
Application::builder().config::<C>(...). Both paths are documented below; the
difference is called out per subcommand.
Which file config reads and writes¶
The canonical user file is <config_dir>/config.yaml, where <config_dir> is
directories::ProjectDirs::from("dev", "", <tool name>).config_dir():
| Platform | Path for a tool named mytool |
|---|---|
| Linux | $XDG_CONFIG_HOME/mytool/config.yaml, else ~/.config/mytool/config.yaml |
| macOS | ~/Library/Application Support/dev.mytool/config.yaml |
| Windows | %APPDATA%\mytool\config\config.yaml |
If a config directory cannot be derived — HOME unset, for instance — the command
fails with no config directory available for tool <name>.
Only set and validate accept --config-file PATH to point somewhere else.
show, get and schema do not.
File format is chosen by extension¶
| Extension | Format |
|---|---|
.toml |
TOML |
.json |
JSON |
| anything else, including none | YAML |
That default is a real trap for --config-file: a path with no extension, or with
an unfamiliar one like .conf, is parsed and written as YAML.
config show¶
Prints the resolved configuration to stdout.
With typed config wired, it serialises the merged Config<C> value as YAML.
Without, it prints two comment lines and exits 0:
$ mytool config show
# no typed configuration is installed on this App
# (call `Application::builder().config(C)` to wire it)
show is the default: mytool config with no subcommand runs it. It ignores
--output; it is always YAML or the placeholder.
config get <PATH>¶
Reads one value and prints it.
The path accepts two spellings, both resolved to a JSON Pointer:
| You write | Pointer used |
|---|---|
/server/port |
/server/port |
.server.port |
/server/port |
server.port |
/server/port |
Where it reads from depends on wiring. With typed config, get reads the merged
value — embedded defaults and env overlays included. Without, it reads the user
file directly, and a missing file is an error rather than an empty result.
Output honours --output:
text(default) — a bare string prints unquoted; anything else prints as JSON.json— pretty-printed JSON, including for strings.
A path that does not resolve is an error: path `<PATH>` not found in <source>,
where <source> is either merged config or the quoted file path.
config set <PATH> <VALUE>¶
Writes a value into the user file (or --config-file PATH) and prints
set `<PATH>` in `<file>`.
VALUE is parsed as JSON first. If that fails it is stored as a string. So
config set .port 8080 stores the number 8080, config set .name alice stores
the string "alice", and config set .name '"8080"' stores the string "8080".
Intermediate objects are created as needed. Missing files are created, along with their parent directories.
What set cannot write¶
- Array elements.
config set /hosts/0 example.comfails withcannot set `0` on a non-object value. There is no way to address an element of a list; rewrite the whole list as a JSON literal instead —config set /hosts '["a","b"]'. - Anything under a scalar.
/foo/barwherefoois a number fails the same way. - A document whose top level is not a map. If the existing file parses to a
list or a scalar,
setreplaces the whole document with a fresh map containing only the value being written. The previous contents are gone. Back up any hand-written file with an unusual shape before runningsetagainst it.
set validates before it writes, but only with a schema wired¶
When typed config is wired, the candidate document is validated against the tool's JSON Schema before anything is written. A rejection leaves the file untouched:
Without typed config there is no schema, so no validation happens at all — any JSON-shaped value lands in the file, and the tool discovers the problem the next time it loads its config.
config schema¶
Prints the JSON Schema for the tool's typed config, pretty-printed.
Without typed config wiring this is an error, not an empty document:
with help pointing at Application::builder().config(...).
config validate¶
Validates a candidate document and prints one line on success.
Three sources, in order of preference:
--config-file <PATH>— always wins. A path that does not exist is an error.- No override, typed config wired — validates the in-memory merged value.
- No override, no typed config — validates the canonical user file. A missing file is an error.
What "validates" means also depends on wiring:
ok: `<file>` validates against the wired schema # schema present
ok: `<file>` parses cleanly (no schema wired — format check only)
The second line is the whole story without typed config: it proves the file is well-formed YAML/TOML/JSON and nothing more. Unknown keys, wrong types and missing required fields all pass.
Failure prints config validation failed at <label>: <detail> and exits non-zero.