keepcalculator

06 Numbers and Powers

Config Precedence & Defaults: CLI Flags Explained

Card No. 06·65324 · Updated · Standard formula, shown below

This article explains how command-line flags, configuration files, and default values interact, and which one wins when they conflict. The rule is simple: command-line flags override config file settings, and config file settings override defaults. This precedence order is consistent across most tools, but the exact mechanics and edge cases are worth understanding before you rely on it.

Background: Why Precedence Exists

Configuration systems evolved from a simple need: let users set defaults for a tool, allow teams to share settings, and still let individuals override anything on a per-run basis. Early Unix tools used only flags, but as software grew, config files became necessary to avoid typing the same flags every time. The precedence order emerged as a convention because it is intuitive: a one-off command should beat a persistent file. This is not a formal standard, but it is followed by Git, curl, npm, pip, Docker, and most modern CLIs.

How the Precedence Chain Works

When a tool starts, it typically reads settings in this order:

  • Defaults are compiled into the binary or defined in code.
  • Config file (e.g., .gitconfig, pyproject.toml, settings.json) is parsed next, overriding defaults.
  • Environment variables (e.g., GIT_AUTHOR_NAME, NPM_CONFIG_REGISTRY) override config files.
  • Command-line flags override everything because they are explicitly typed for this run.

Some tools reverse the environment variable and config file order, but the flag is always last. The key nuance is that most tools do not merge multiple config files; they pick one based on a search path (current directory, then home directory, then system directory). The first found file wins, not the last.

How to Choose the Right Layer

Deciding which layer to use depends on the scope of the setting:

  • Default: use for sensible fallbacks that rarely change, like a timeout of 30 seconds.
  • Config file: use for project-specific or user-specific settings that should persist, like a preferred editor or a remote repository URL.
  • Environment variable: use for secrets, machine-specific paths, or CI/CD overrides, because these are often set outside the codebase.
  • CLI flag: use for one-off changes, debugging, or when you want to test a value without editing a file.

A common mistake is putting a secret in a config file that gets committed to version control. Environment variables or a separate untracked file are safer. Another mistake is assuming a flag will override a config file when the tool actually uses the config file as a base and the flag as an addition (e.g., --verbose sets a boolean that the config file cannot turn off).

Common Problems and Misconceptions

One frequent issue is that some tools treat flags as absolute overrides, while others treat them as incremental. For example, --config in many tools replaces the entire config file rather than merging with it. This means a flag that sets one option can silently clear all other config values. Another problem is precedence between multiple config files: tools like Git use a hierarchy (system, global, local), and each level overrides the previous one, but the local file always beats the global one. A misconception is that environment variables are always stronger than config files; in tools like Ansible, the config file actually wins over environment variables. Always check the specific tool’s documentation.

Comparisons: Flag vs. Config vs. Env Var

Here is a practical comparison of the three layers for a typical setting like a logging level:

  • CLI flag (--log-level=debug): explicit, visible in the command history, but must be retyped each time.
  • Environment variable (LOG_LEVEL=debug): set once per shell session, easy to export, but can be forgotten when moving to a new terminal.
  • Config file (log_level = "debug"): persists across sessions, can be shared with a team, but requires editing a file and knowing its format.

The best choice depends on whether the setting is temporary, machine-specific, or project-wide. For temporary debugging, a flag is best. For a personal preference, a config file is best. For a CI pipeline, an environment variable is often best because it is set in the pipeline configuration, not in the code.

Costs and Risks of Misusing Precedence

The main cost is debugging time. When a tool behaves unexpectedly, you have to check four layers to find the culprit. A hidden config file in a parent directory can override your carefully set flag. An environment variable set in a previous session can change behavior without any visible trace. The risk is especially high in shared environments: a developer’s local config can override a team’s standard, or a CI environment variable can override a config file that was meant to be authoritative. To mitigate this, most tools offer a --no- prefix to explicitly turn off a boolean, or a --config flag to point to a specific file. Also, running tool --verbose or tool config list often shows the effective values and their source.

Safety and Best Practices

To avoid surprises, follow these practices:

  • Always document the precedence order in your project’s README.
  • Use environment variables for secrets, never config files that are committed.
  • Test your tool with --help or a dry-run mode to see what values are being used.
  • When writing a new tool, implement the standard precedence (flag > env > config > default) unless you have a strong reason not to.
  • If you are a user, use strace or ltrace on Linux to see which config files a tool opens, or use the tool’s own debug output.

Alternatives to the Standard Precedence

Some tools deliberately deviate. For example, curl does not have a config file by default; it relies entirely on flags and environment variables. ansible gives config files a higher priority than environment variables. systemd uses a drop-in directory system where files are read in lexicographic order, and later files override earlier ones. Another alternative is the --config flag that points to a specific file, which then becomes the only config source, bypassing the search path. Some tools also support multiple config files that merge, with a --config flag to add an extra file rather than replace. Understanding these deviations is crucial when switching between tools.

Frequently Asked Questions

Q: Does a CLI flag always beat a config file?
A: Yes, in the vast majority of tools. The flag is the most specific and most recent instruction, so it wins. However, some tools have flags that only add to a list (e.g., --include), so the config file’s list is still used. Check the tool’s documentation for whether a flag replaces or appends.

Q: What if the same setting appears in two config files?
A: The tool uses a search path. Usually the first file found wins, not the last. For example, Git uses the local repository config before the global config. If you have a setting in both, the local one wins. Some tools merge multiple files, but the last one read wins.

Q: How do I see the effective configuration after all layers are applied?
A: Most tools offer a command like git config --list, npm config list, or tool --show-config. If not, run the tool with a debug flag (e.g., --verbose or --debug) to see what values were loaded and from where.

Q: Can I force a config file to ignore environment variables?
A: Not usually. The precedence is fixed by the tool. Your options are to unset the environment variable, or use a flag that explicitly overrides it. Some tools have a --no-env flag, but it is rare. The safest approach is to make your environment variables consistent with your config file.

Q: Why does my tool ignore my config file when I run it from a different directory?
A: Because the config file search path is relative to the current directory. The tool looks for a config file in the current directory first, then in your home directory. If you run the tool from a subdirectory, it may find a different config file or none at all. Use an absolute path with --config to avoid this.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →