# How the nGPT CLI Configuration System Stores and Applies Persistent Default Settings

> Learn how the nGPT CLI configuration system manages persistent default settings. Discover its platform-specific JSON storage and runtime argument merging for robust command execution.

- Repository: [nazDridoy/ngpt](https://github.com/nazdridoy/ngpt)
- Tags: internals
- Published: 2026-03-07

---

**The nGPT CLI configuration system stores persistent defaults in a platform-specific JSON file and merges them with command-line arguments at runtime, respecting type validation, context modes, and mutual exclusivity rules.**

The nGPT CLI configuration system provides a robust mechanism for maintaining permanent defaults across terminal sessions. Located in the `nazdridoy/ngpt` repository, this system allows users to customize command-line behavior without repeatedly typing flags. By storing settings in a persistent JSON file, the CLI configuration system ensures that preferences like temperature, model selection, and output formats persist across system restarts.

## Configuration File Location and Storage

The CLI configuration system uses a dedicated JSON file named [`ngpt-cli.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt-cli.conf) located in a platform-specific directory determined by the `get_cli_config_dir()` function in [`ngpt/core/cli_config.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/core/cli_config.py) (lines 27-41).

### Platform-Specific Paths

| Operating System | Configuration Path |
|------------------|-------------------|
| Linux/Unix | `~/.config/ngpt/ngpt-cli.conf` (or `$XDG_CONFIG_HOME/ngpt/ngpt-cli.conf`) |
| macOS | `~/Library/Application Support/ngpt/ngpt-cli.conf` |
| Windows | `%APPDATA%\ngpt\ngpt-cli.conf` |

The directory is created automatically using `mkdir(parents=True, exist_ok=True)` (line 44) if it does not exist, ensuring the configuration file can be written immediately.

## Loading and Saving Configuration Data

The system provides two core functions for persistence in [`ngpt/core/cli_config.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/core/cli_config.py):

- **`load_cli_config()`** (lines 51-66): Reads the JSON file if it exists and returns a dictionary. If the file is missing or corrupted, it returns an empty dictionary.
- **`save_cli_config(config)`** (lines 68-75): Writes the configuration dictionary back to [`ngpt-cli.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt-cli.conf) with pretty-printed JSON formatting, ensuring human-readable storage.

## Defining Available Configuration Options

All configurable options are declared in the `CLI_CONFIG_OPTIONS` constant (lines 7-25 of [`ngpt/core/cli_config.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/core/cli_config.py)). Each entry specifies:

- **Type**: `str`, `int`, `float`, or `bool`
- **Built-in default value**: Used when no configuration exists
- **Contexts**: A list determining when the option applies (e.g., `"code"`, `"gitcommsg"`, or `"all"`)
- **Exclusive options**: Optional list of mutually exclusive flags (e.g., `provider` ↔ `config-index`)

This schema ensures type safety and context-aware application of settings.

## Setting, Getting, and Unsetting Values

The system provides three primary functions for manipulating configuration values:

### Setting Options

`set_cli_config_option(option, value)` (lines 80-144) validates the input against the declared type, respects mutual exclusivity rules, updates the in-memory dictionary, and persists changes to disk. When setting a boolean option to `True`, it automatically forces all exclusive options to `False` (lines 66-74).

### Getting Options

`get_cli_config_option(option=None)` (lines 145-170) retrieves either a single value (falling back to the built-in default if unset) or the entire configuration dictionary.

### Unsetting Options

`unset_cli_config_option(option)` (lines 171-198) removes a key from the JSON file, causing subsequent runs to use the built-in default instead.

## Applying Configuration to Command Execution

The `apply_cli_config(args, mode)` function (lines 199-278) merges stored defaults with command-line arguments at runtime. This function implements the priority hierarchy documented in [`docs/usage/cli_config.md`](https://github.com/nazdridoy/ngpt/blob/main/docs/usage/cli_config.md).

### Priority Order

The system applies settings in the following priority (highest to lowest):

1. **Explicit command-line arguments**
2. **Environment variables** (`OPENAI_API_KEY`, etc.)
3. **CLI configuration** ([`ngpt-cli.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt-cli.conf)) — handled by this function
4. **Main configuration file** ([`ngpt.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt.conf))
5. **Built-in defaults** from `CLI_CONFIG_OPTIONS`

### Merge Algorithm

The `apply_cli_config` function executes the following logic:

- Loads the JSON config via `load_cli_config()`
- Detects which options the user explicitly supplied on the command line (`explicit_args`)
- Tracks exclusive options already set explicitly
- Iterates over stored options:
  - Skips options whose context does not match the current mode (e.g., skipping git-specific settings in code mode)
  - Skips options already provided via command line
  - Skips options if an exclusive alternative has been applied
  - Assigns the stored value to the `args` namespace via `setattr`

For boolean options set to `True`, the function automatically disables all exclusive alternatives (lines 66-74), ensuring mutually exclusive flags remain consistent.

## Managing Configuration via Command Line

Users interact with the CLI configuration system through the `--cli-config` subcommand, handled by [`ngpt/cli/handlers/cli_config_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/cli_config_handler.py).

### Setting a Default Value

```bash

# Make temperature 0.9 the default for every run

ngpt --cli-config set temperature 0.9

```

This invokes `set_cli_config_option("temperature", "0.9")`, which parses the string to a float, validates it, and persists it to [`ngpt-cli.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt-cli.conf).

### Retrieving Configuration Values

```python
from ngpt.core.cli_config import get_cli_config_option

success, value = get_cli_config_option("temperature")
if success:
    print(f"Default temperature = {value}")   # → 0.9 (or built‑in default 0.7)

```

### Applying Defaults Programmatically

```python
import argparse
from ngpt.core.cli_config import apply_cli_config

parser = argparse.ArgumentParser()
parser.add_argument("--temperature", type=float, default=None)
args = parser.parse_args()

# Apply stored defaults for the generic 'all' mode

args = apply_cli_config(args, mode="all")

print(args.temperature)   # Will be 0.9 unless the user passed --temperature on the CLI

```

### Reverting to Built-in Defaults

```bash
ngpt --cli-config unset temperature

```

This executes `unset_cli_config_option("temperature")`, removing the key from [`ngpt-cli.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt-cli.conf) and causing subsequent runs to use the built-in default of `0.7`.

## Summary

- The nGPT CLI configuration system stores persistent defaults in a platform-specific JSON file ([`ngpt-cli.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt-cli.conf)) located in OS-specific directories (`~/.config/ngpt/` on Linux, `~/Library/Application Support/ngpt/` on macOS, `%APPDATA%\ngpt\` on Windows).
- Core functions in [`ngpt/core/cli_config.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/core/cli_config.py) handle loading (`load_cli_config`), saving (`save_cli_config`), and manipulating settings with type validation and mutual exclusivity checks.
- The `apply_cli_config` function merges stored defaults with command-line arguments, respecting a strict priority order: explicit CLI args > environment variables > CLI config > main config > built-in defaults.
- Context-aware application ensures mode-specific settings (e.g., `gitcommsg` vs `code`) only apply to relevant commands.
- Users manage settings via `ngpt --cli-config set|get|unset|list` commands, with changes persisting immediately to the JSON configuration file.

## Frequently Asked Questions

### Where does nGPT store the CLI configuration file?

The CLI configuration file [`ngpt-cli.conf`](https://github.com/nazdridoy/ngpt/blob/main/ngpt-cli.conf) is stored in a platform-specific directory determined by the `get_cli_config_dir()` function in [`ngpt/core/cli_config.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/core/cli_config.py). On Linux, it uses `~/.config/ngpt/` (or `$XDG_CONFIG_HOME/ngpt/`); on macOS, `~/Library/Application Support/ngpt/`; and on Windows, `%APPDATA%\ngpt\`. The directory is created automatically if it does not exist.

### How does nGPT handle conflicts between CLI arguments and stored configuration values?

nGPT applies a strict priority hierarchy when merging configuration sources. Explicit command-line arguments always take precedence over stored configuration values. The `apply_cli_config()` function in [`ngpt/core/cli_config.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/core/cli_config.py) tracks which arguments the user explicitly provided and skips applying stored defaults for those specific options. This ensures that one-off command-line flags override persistent settings without deleting them from the configuration file.

### What happens when I set mutually exclusive options in the CLI configuration?

The CLI configuration system enforces mutual exclusivity rules defined in the `CLI_CONFIG_OPTIONS` constant. When you set a boolean option to `True` using `set_cli_config_option()`, the system automatically sets all its exclusive peers to `False` (lines 66-74 in [`ngpt/core/cli_config.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/core/cli_config.py)). For non-boolean options, setting one exclusive option removes all its exclusive alternatives from the configuration dictionary (lines 28-32). This ensures that conflicting options cannot be active simultaneously, preventing runtime errors.

### Can I have different default settings for different nGPT modes (like code vs. gitcommsg)?

Yes, the CLI configuration system supports context-aware defaults through the `contexts` field in `CLI_CONFIG_OPTIONS`. Each configurable option can specify which modes it applies to, such as `"code"`, `"gitcommsg"`, or `"all"`. When `apply_cli_config()` processes stored settings, it accepts a `mode` parameter and skips any options whose context does not match the current execution mode. This allows you to set different default temperatures, models, or output formats specifically for code generation versus Git commit message generation.