# Configuration Resolution Order for Ponytail Modes: Environment Variables vs. Config Files

> Understand the Ponytail modes configuration resolution order. Learn how environment variables and config files set your default mode, prioritizing PONYTAIL_DEFAULT_MODE and config.json.

- Repository: [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
- Tags: how-to-guide
- Published: 2026-09-04

---

**The configuration resolution order for Ponytail modes follows a strict three-tier hierarchy: the `PONYTAIL_DEFAULT_MODE` environment variable takes precedence, followed by the `defaultMode` value in a [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) file, and finally falling back to the hard-coded default of `"full"`.**

Determining how Ponytail selects its operational intensity—whether `off`, `lite`, `full`, or `ultra`—requires understanding the configuration resolution order for Ponytail modes. In the **DietrichGebert/ponytail** repository, this resolution chain is implemented in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js), where the `getDefaultMode` function orchestrates the precedence between environment variables, persistent configuration files, and built-in defaults.

## The Three-Tier Configuration Resolution Hierarchy

The resolver evaluates potential mode sources in a fixed sequence defined in the file header and implemented in the `getDefaultMode` function (lines 76–100).

### 1. Environment Variable (Highest Priority)

The resolver first checks `process.env.PONYTAIL_DEFAULT_MODE`. If this variable is set and contains a valid runtime mode (`off`, `lite`, `full`, or `ultra`), its value is used immediately. This allows for temporary, session-specific overrides without modifying persistent files. (See lines 76–84 in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js).)

### 2. Configuration File

If no environment variable is set, the resolver searches for [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) in platform-specific locations, in order:

- `$XDG_CONFIG_HOME/ponytail/config.json` (any platform)
- `~/.config/ponytail/config.json` (Linux/macOS fallback)
- `%APPDATA%\ponytail\config.json` (Windows fallback)

The file path construction logic resides at lines 67–69. If the file exists and its `defaultMode` field contains a valid runtime mode, that value is selected. (See lines 86–94.)

### 3. Built-in Fallback

When neither the environment variable nor a configuration file provides a valid mode, Ponytail defaults to `"full"`. This hard-coded fallback ensures the application always launches with a defined operational level. (See lines 99–100.)

## Mode Validation and Normalization

The resolution process includes strict validation to ensure only runtime-appropriate modes are persisted. The **`normalizeMode`** function accepts only `off`, `lite`, `full`, and `ultra`.

Additionally, **`normalizeConfigMode`** accepts `review` as a valid mode during processing, but the implementation explicitly prevents `review` from becoming the persistent default. This safety mechanism ensures that temporary review states never accidentally become the permanent configuration. (See comments around lines 79–82.)

## Practical Code Examples

Retrieve the currently resolved mode:

```javascript
const { getDefaultMode } = require('./hooks/ponytail-config');
console.log('Current Ponytail mode →', getDefaultMode());
// → "full" (if no env var or config file is present)

```

Override via environment variable:

```javascript
process.env.PONYTAIL_DEFAULT_MODE = 'lite';
console.log('Overridden mode →', getDefaultMode());
// → "lite"

```

Persist a new default to the configuration file:

```javascript
const { writeDefaultMode } = require('./hooks/ponytail-config');
writeDefaultMode('ultra');   // creates/updates ~/.config/ponytail/config.json

```

## Key Files in the Resolution Chain

| File | Purpose |
|------|---------|
| **[`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js)** | Central resolver for the default mode, defines precedence, normalisation, and persistence. |
| **[`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-mode-tracker.js)** | Tracks the active mode per session (uses the resolver’s output). |
| **[`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js)** | Injects the resolved mode into the agent’s runtime context. |

## Summary

- **The configuration resolution order for Ponytail modes** prioritizes the `PONYTAIL_DEFAULT_MODE` environment variable, then checks [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) in XDG-compliant or platform-specific directories, and finally defaults to `"full"`.
- Only runtime modes (`off`, `lite`, `full`, `ultra`) can be set as defaults; the `review` mode is explicitly excluded from persistence.
- The resolution logic resides in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js), specifically within the `getDefaultMode` function (lines 76–100).
- Configuration files follow the XDG Base Directory Specification, falling back to standard OS-specific paths on Linux/macOS and Windows.

## Frequently Asked Questions

### What is the highest priority source for Ponytail mode configuration?

The `PONYTAIL_DEFAULT_MODE` environment variable holds the highest priority. When set to a valid runtime mode, it overrides any configuration file settings and the built-in default, as implemented in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) at lines 76–84.

### Where does Ponytail store its configuration file?

Ponytail searches for [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) in three locations: first at `$XDG_CONFIG_HOME/ponytail/config.json`, then `~/.config/ponytail/config.json` on Linux/macOS, and finally `%APPDATA%\ponytail\config.json` on Windows. The first existing file in this order is used according to the path resolution logic at lines 67–69.

### Why can't I set "review" as the default mode?

The `review` mode is accepted by `normalizeConfigMode` for temporary session use, but the configuration resolution logic explicitly prevents it from being persisted as the default. This design ensures transitional review states don't become permanent operational settings in the configuration file.

### What happens if no configuration source is found?

If neither the environment variable nor a configuration file specifies a valid mode, Ponytail falls back to the hard-coded default of `"full"` as implemented in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) at lines 99–100, ensuring the application always operates with a defined intensity level.