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

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 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, 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.)

2. Configuration File

If no environment variable is set, the resolver searches for 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:

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:

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

Persist a new default to the configuration file:

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 Central resolver for the default mode, defines precedence, normalisation, and persistence.
hooks/ponytail-mode-tracker.js Tracks the active mode per session (uses the resolver’s output).
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 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, 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 at lines 76–84.

Where does Ponytail store its configuration file?

Ponytail searches for 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 at lines 99–100, ensuring the application always operates with a defined intensity level.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →