Skip to content

CLI --config Overrides Reference

This document describes how to override rumdl configuration directly on the command line, without modifying any config file. This mirrors Ruff's --config flag overload.

Overview

The --config flag accepts either:

  1. A path to a TOML configuration file (.rumdl.toml, rumdl.toml, pyproject.toml, …), or
  2. An inline TOML KEY = VALUE snippet that overrides specific options at the highest precedence — beating values from config files and from other CLI flags such as --disable or --line-length.

Both forms can be mixed; --config may be passed multiple times. At most one value may be a file path; the remaining values must be inline TOML.

Quick Examples

# Override a rule option without editing config
rumdl check --config 'MD013.line-length=120'

# Combine multiple overrides — each --config is independent, not replacement
rumdl check --config 'MD013.line-length=120' --config 'MD013.reflow=true'

# Override a top-level (global) setting
rumdl check --config 'line-length=120'

# Use the explicit [global] section name
rumdl check --config 'global.flavor="mkdocs"'

# Pass arrays
rumdl check --config 'disable=["MD013","MD033"]'
rumdl check --config 'exclude=["**/tmp/*.md"]'

# A file plus inline overrides — inline always wins
rumdl check --config my-config.toml --config 'MD013.line-length=120'

# Inline overrides remain in effect with --no-config / --isolated
rumdl check --no-config --config 'MD013.reflow=true'

Syntax Forms

Form Where it lands Example
RULE.option = value Per-rule option --config 'MD013.line-length=120'
option = value (top-level) Global option --config 'line-length=120'
global.option = value Global option (explicit section) --config 'global.flavor="mkdocs"'
SECTION.key = value Non-rule section --config 'code-block-tools.enabled=false'

The dispatch is based on the shape of the value, not the key:

  • A table value (e.g. MD013.line-length=20 parses as a nested table) is first matched against the non-rule sections code-block-tools, per-file-ignores and per-file-flavor, and otherwise treated as a per-rule override. The key is then resolved against the rule registry, including markdownlint aliases (line-length → MD013). No rule answers to a section name, so the two vocabularies do not overlap. How much of a section an override displaces is covered under Non-rule sections.
  • A scalar or array is treated as a top-level/global override. This matters for keys like line-length, which is both a global setting and an MD013 alias: a bare line-length=120 is global; MD013.line-length=120 (or line-length.line-length=120) is per-rule.

Non-rule sections

code-block-tools, per-file-ignores and per-file-flavor are stored outside the rule map, and an override of one follows the same rule ruff's --config follows: it sets the settings it names, and settings it does not name keep what they were configured with.

# Sets one setting; the configured languages, tools and timeout stay in force
rumdl check --config 'code-block-tools.enabled = false' .

# Sets per-file-ignores; the map it held is replaced, not merged into
rumdl check --config 'per-file-ignores."README.md" = ["MD013"]' .

code-block-tools holds several settings, so naming one leaves the others alone. per-file-ignores and per-file-flavor are each a single setting whose value is a map of user-written patterns, so naming one pattern replaces the whole map: patterns the project configured for other files no longer apply to that run. This is what writing the section in a higher-precedence config file does, and what ruff does with lint.per-file-ignores. To keep the other patterns, name them in the same override.

Because the map is replaced, the order question per-file-flavor carries (a file takes the flavor of the first pattern it matches) is settled too: after an override the only patterns to match are the ones it named.

Precedence

Inline --config overrides are applied at ConfigSource::Cli precedence — the highest. Order from lowest to highest:

  1. Built-in defaults
  2. User configuration (~/.config/rumdl/rumdl.toml; see User-level configuration for the per-platform locations)
  3. pyproject.toml
  4. Project configuration (.rumdl.toml / rumdl.toml)
  5. Other CLI flags (--disable, --line-length, …)
  6. --config inline overrides ← wins

When multiple --config arguments target the same key, the last one wins.

Key Resolution

Both rule names and option keys are normalized:

  • Rule names accept aliases: --config 'line-length.line-length=20' is the same as --config 'MD013.line-length=20'. Lowercase IDs (md013) also work.
  • Option keys accept kebab-case and snake_case interchangeably: MD013.line_length=20 is equivalent to MD013.line-length=20. The implementation collapses kebab/snake variants so serde does not see duplicate fields when an alias is set in a config file.

Path Detection

A --config value with no = character is always treated as a file path. A value containing = is preferred as a file path only if a file by that literal name exists; otherwise it is parsed as inline TOML.

If a --config value has = and is neither an existing file nor valid TOML, clap reports a ValueValidation error with the parser's TOML error message and a usage tip — no panic, no silent fallback.

Validation Warnings

The standard config validator runs against the merged config, so an unknown rule or option named in a --config override is reported the way a config file's would be. A value the setting cannot hold is reported by the override itself, naming the key it came from. Both reach stderr as [config warning], with no RUST_LOG needed:

Bad input Warning
--config 'MD9999.foo=1' Unknown rule in config: MD9999
--config 'MD013.no_such_option=1' Unknown option for rule MD013: no_such_option
--config 'totally_bogus_key=1' Unknown global option: totally_bogus_key
--config 'line-length="huge"' --config: expected integer for global key 'line-length'
--config 'code-block-tools.enabled="x"' --config [code-block-tools]: invalid type: string "x", expected a boolean
--config 'per-file-flavor."a.md"="nope"' --config per-file-flavor."a.md": invalid flavor 'nope'
--config 'per-file-ignores."a.md"="MD013"' --config per-file-ignores."a.md": expected an array of rule names

Warnings are written to stderr and do not affect the exit code on their own; --deny-config-warnings turns them into a failing exit. The lint/format command continues with the valid portions of the merged config: a value it could not use is skipped and the rest of the override still applies. A skipped setting keeps what it was configured with; a skipped pattern inside a per-file-ignores or per-file-flavor override is simply absent from the map that override installs.

What is not validated inside a non-rule section: a misspelled key (code-block-tools.enabldd=true) and an unknown rule name in a per-file-ignores list are both accepted in silence, on the command line and in a config file alike. Only the value's shape is checked.

Errors

Bad input Outcome
Two --config values that are file paths Tool error: multiple --config file paths given
--config /no/such/file.toml Tool error: config file not found
--config /file.toml --no-config Tool error: --config <CONFIG_OPTION> (file path) cannot be used with --no-config (inline TOML overrides are unaffected)
--config 'this is not valid toml = =' clap value error with TOML parse details

Watch Mode

Inline overrides are reapplied on every config-file reload while watching, so edits to .rumdl.toml cannot quietly undo what was set on the command line.