# How Destructive Command Guard's Layered Configuration System Prioritizes Environment Variables vs Config Files

> Learn how Destructive Command Guard's layered configuration prioritizes DCG_ environment variables over config files and discover the cascade from project users to system defaults.

- Repository: [Jeff Emanuel/destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard)
- Tags: internals
- Published: 2026-07-16

---

**Environment variables prefixed with `DCG_` override all configuration files, while settings cascade through project-level, user-level, system-level, and finally compiled defaults.**

Destructive Command Guard (dcg) implements a deterministic **layered configuration system** that balances flexibility with predictability. Written in Rust, the tool loads settings from multiple sources according to strict precedence rules documented in the header of [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs)【L3-L9】, ensuring that environment variables always take precedence over file-based configurations.

## The Five-Layer Configuration Hierarchy

The dcg configuration system builds settings from five distinct layers, applying a "higher-precedence wins" merge strategy:

### Environment Variables (Highest Priority)

Any setting supplied via a `DCG_…` variable shadows values from all configuration files. The constant `ENV_PREFIX` is defined at line 44 in [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs)【L43-L45】, enabling per-run overrides without modifying persistent files.

### Project-Level Configuration

The [`.dcg.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/.dcg.toml) file in the repository root provides project-specific settings. When running dcg inside a project directory, values here override user-level and system-level configurations but yield to environment variables.

### User-Level Configuration

Settings specific to the current user are read from `$XDG_CONFIG_HOME/dcg/config.toml` (falling back to `~/.config/dcg/config.toml` on most systems). This layer applies only when project-level files are absent or when specific fields remain unset.

### System-Level Configuration

Global system defaults reside in [`/etc/dcg/config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main//etc/dcg/config.toml) on Linux/macOS or `%ProgramData%\dcg\config.toml` on Windows. These provide organization-wide defaults while allowing individual users and projects to override them.

### Compiled Defaults (Lowest Priority)

When no configuration files exist and no environment variables are set, dcg uses the Rust `Default` implementations defined for each config struct (e.g., `GeneralConfig::default()` at line 46【L46-L48】).

## The Merge Algorithm and ConfigLayer Structure

The merging logic centers on the `ConfigLayer` struct defined at line 84 in [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs)【L84-L90】. Each configuration field uses `Option<T>` to represent presence or absence:

- **Some(T)** indicates an explicit value from that layer
- **None** indicates the layer did not provide that setting

During initialization, dcg parses each file into a layer, then applies the merge algorithm: if a field is `Some` in a higher layer (e.g., environment variables), it shadows any `Some` value from lower layers. Only fields that remain `None` after evaluating all layers receive the compiled defaults.

## Practical Override Examples

### Overriding a Boolean via Environment Variable

The compiled default for verbose output is `false`. Setting the environment variable enables verbose logging for a single run regardless of file configurations:

```bash
DCG_VERBOSE=true dcg explain "git reset --hard"

```

*Result:* `verbose` is `true` regardless of values set in [`.dcg.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/.dcg.toml), `~/.config/dcg/config.toml`, or [`/etc/dcg/config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main//etc/dcg/config.toml).

### Selecting a Custom Config File

The special variable `DCG_CONFIG` selects an alternate TOML file, separate from per-setting overrides【L52-L56】:

```bash
DCG_CONFIG=/tmp/my-config.toml dcg --version

```

*Result:* dcg loads the specified file instead of the normal search order, then still applies any `DCG_…` overrides on top of that file.

### Project-Level Precedence Over User Files

Assume the following scenario:
- `~/.config/dcg/config.toml` contains `check_updates = false`
- The project's [`.dcg.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/.dcg.toml) contains `check_updates = true`

Running dcg inside the repository:

```bash
cd my-repo
dcg explain "rm -rf /"

```

*Result:* `check_updates` evaluates to `true` because the project file outranks the user file.

## Core Implementation Files

- **[`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs)** – Contains the `ConfigLayer` struct, `ENV_PREFIX` constant, and the layered merging logic that implements the precedence rules.
- **[`src/main.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/main.rs)** – Parses command-line arguments and orchestrates the configuration loading sequence before applying environment variable overrides.
- **[`src/trace.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/trace.rs)** – Emits diagnostic messages indicating when a setting was overridden by the environment (e.g., "BLOCK: config override").
- **[`src/cli.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/cli.rs)** – Implements the `dcg config show` command, which respects the precedence rules to display active settings.

## Summary

- **Environment variables** with the `DCG_` prefix take precedence over all configuration files.
- **Configuration files** apply in descending order: project ([`.dcg.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/.dcg.toml)) → user (`~/.config/dcg/config.toml`) → system ([`/etc/dcg/config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main//etc/dcg/config.toml)).
- **Compiled defaults** from Rust `Default` implementations serve as the final fallback.
- The `ConfigLayer` struct uses `Option<T>` fields to implement the "higher-precedence wins" merge algorithm.
- The `DCG_CONFIG` environment variable can specify a custom configuration file path, which is then subject to additional `DCG_` overrides.

## Frequently Asked Questions

### What happens if I set both DCG_CONFIG and specific DCG_ variable overrides?

Dcg first loads the file specified by `DCG_CONFIG`, then applies any additional `DCG_` environment variable overrides on top of that file. Environment variables always represent the final authority regardless of which file was loaded initially.

### How does dcg handle configuration on Windows versus Linux?

On Linux and macOS, dcg searches [`/etc/dcg/config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main//etc/dcg/config.toml) for system-level settings and `$XDG_CONFIG_HOME/dcg/config.toml` (or `~/.config/dcg/config.toml`) for user-level settings. On Windows, the system-level path becomes `%ProgramData%\dcg\config.toml`, while user-level configuration follows the same XDG pattern if available, or falls back to the standard config directory.

### Can I see which configuration layer provided a specific setting?

Yes. When running dcg with verbose or trace output enabled, the system emits messages via [`src/trace.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/trace.rs) indicating when a configuration value was overridden by an environment variable. This helps debug which layer is active for specific settings like `verbose` or `check_updates`.

### What occurs if no configuration files exist at any level?

If dcg finds no [`.dcg.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/.dcg.toml), user config, or system config, it initializes the configuration using only the compiled defaults defined in the `Default` trait implementations for each struct (e.g., `color = "auto"` and `check_updates = true`). You can then selectively override these defaults using `DCG_` environment variables as needed.