How Xberg resolves configuration — CLI-mode and server/MCP-mode precedence orders, config file auto-discovery (xberg.toml walk-up, then the user config dir), field-level inline JSON merge (merge_json_into_config), the ExtractionOverrides CLI layer, and the two mechanisms that make a config change silently do nothing. Load when adding a config flag or env var, changing config precedence, or debugging why a setting is or isn't taking effect.
67
80%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
--ocr, --output-format, --chunk)--config-json or --config-json-base64)--config path.toml)xberg.toml in cwd/parents, then the user config dir)--host, --port)XBERG_HOST, XBERG_PORT)[server] section127.0.0.1:8000)ExtractionConfig::discover() (core/config/extraction/loaders.rs) does two different things:
xberg.toml only — no
.yaml/.yml/.json at this stage. First hit wins.dirs::config_dir()/xberg) and probes four basenames in a fixed order:
xberg.toml, xberg.yaml, xberg.yml, xberg.json.So a project-local xberg.yaml is not auto-discovered — pass it with --config.
Field-level merge (not whole-object replacement):
fn merge_json_into_config(base: &ExtractionConfig, json: Value) -> Result<ExtractionConfig> {
let mut config_json = serde_json::to_value(base)?;
// Merge fields from json into config_json
serde_json::from_value(merged)?
}Use --config-json-base64 for shell escaping.
TOML (xberg.toml):
use_cache = true
[ocr]
backend = "tesseract"
languages = ["eng", "deu"]
[security_limits]
max_archive_size = 524288000YAML and JSON follow equivalent structure.
crates/xberg-cli/src/commands/overrides.rs: the ExtractionOverrides struct's validate()
runs first, then apply(self, config: &mut ExtractionConfig) lays individual CLI flags over
the merged config. There is no apply_extraction_overrides() and no commands.rs —
commands/ is a directory.
Inline JSON enters through apply_json_overrides(config, config_json, config_json_base64)
(crates/xberg-cli/src/input.rs), which delegates to merge_json_into_config.
Duplicate Default impls. TesseractConfig is defined twice — public
(types/formats.rs, binding-friendly types) and internal (ocr/types.rs, engine-side types)
— bridged by a From impl, each with its own Default. Changing one default fixes only the
routes that materialise that struct. Before changing any config default, grep the bare
type name (a pub use module::*; makes a qualified path unsearchable) and check for a second
definition.
Unknown keys are ignored. #[serde(deny_unknown_fields)] is on exactly two structs:
ExtractionConfig (core/config/extraction/core.rs) and UrlExtractionConfig
(core/config/extraction/types.rs). Every nested config silently ignores a typo'd key, so a
wrong setting parses clean, does nothing, and the test still passes. Write config fixtures
against the serde wire names (ChunkingConfig declares max_characters but renames to
max_chars), and assert the parsed config differs from the default rather than that it parsed.
xberg.toml only; other extensions need --config--config-json-base64 for shell-safe JSON passing[server] section + extraction config04336bd
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.