# Understanding the Role of Configuration Files in Ponytail

> Discover how Ponytail uses JSON configuration files and environment variables to manage runtime behavior. Learn about its priority chain for settings.

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

---

**Ponytail stores user preferences in a JSON configuration file located in the XDG configuration directory, using a priority chain of environment variables → config file → hardcoded defaults to determine runtime behavior.**

The DietrichGebert/ponytail repository implements a robust configuration system that persists user preferences across sessions. The configuration file serves as the single source of truth for runtime behavior, enabling platform-agnostic storage of intensity levels, UI visibility settings, and startup preferences.

## Configuration File Location and Platform Support

Ponytail adheres to the XDG Base Directory Specification, storing settings in [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) under the XDG configuration hierarchy. The lookup follows a strict platform-specific priority order.

On macOS and Linux, the resolver checks `$XDG_CONFIG_HOME/ponytail/config.json` first, falling back to `~/.config/ponytail/config.json`. Windows systems use `%APPDATA%\ponytail\config.json`.

The path resolution logic lives in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) within the `getConfigPath()` and `getConfigDir()` helper utilities (lines 54–69).

## Core Configuration API in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js)

The [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) module exports a set of getter and setter functions that abstract file I/O and validation. These functions determine runtime behavior through a predictable precedence: environment variables override file settings, which override hardcoded defaults.

### Retrieving and Setting the Default Mode

The `getDefaultMode()` function (lines 76–99) returns the persistent intensity level for Ponytail sessions. It accepts four valid runtime modes: `off`, `lite`, `full`, and `ultra`. The function explicitly rejects the `review` mode—reserved for session-only use—preventing invalid persistent states.

To persist a new default, `writeDefaultMode(mode)` (lines 36–50) writes to the JSON file, creating the directory structure if it does not exist.

### Controlling UI Visibility Flags

Two boolean flags control interface elements. The `getQuietStartup()` function checks the `PONYTAIL_QUIET_STARTUP` environment variable or the `quietStartup` config key to suppress the "Ponytail loaded" toast notification (lines 5–14). Similarly, `getHideStatus()` reads `PONYTAIL_HIDE_STATUS` or `hideStatus` to determine whether to render the status-bar indicator (lines 19–28).

## Configuration Validation and Priority Chain

Ponytail implements a strict validation layer to prevent malformed configurations from crashing the system. When loading settings, the resolver follows this priority chain:

1. **Environment variables** (`PONYTAIL_DEFAULT_MODE`, `PONYTAIL_QUIET_STARTUP`, `PONYTAIL_HIDE_STATUS`) for temporary, ad-hoc overrides
2. **Configuration file values** ([`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json)) for persistent user preferences
3. **Hardcoded fallbacks** (`full` for intensity, `false` for boolean flags)

This design allows developers to test different modes without modifying JSON files, while end-users retain persistent settings across restarts.

## Reading and Writing Configuration Programmatically

The following examples demonstrate how to interact with Ponytail's configuration system in JavaScript.

To read the current default mode:

```js
const { getDefaultMode } = require('./hooks/ponytail-config');

const defaultMode = getDefaultMode(); // → 'lite' | 'full' | 'ultra' …
console.log(`Current default Ponytail mode: ${defaultMode}`);

```

To persist a new default intensity:

```js
const { writeDefaultMode } = require('./hooks/ponytail-config');

const newMode = writeDefaultMode('ultra');
if (newMode) {
  console.log(`Default mode saved as "${newMode}"`);
} else {
  console.error('Invalid mode – must be one of off, lite, full, ultra');
}

```

Checking visibility preferences before rendering UI elements:

```js
const { getQuietStartup, getHideStatus } = require('./hooks/ponytail-config');

if (getQuietStartup()) {
  // Suppress the startup toast
  console.log('Quiet startup enabled – no toast will be shown.');
}

if (getHideStatus()) {
  // Skip writing the status line
  console.log('Status bar indicator hidden per config.');
}

```

## Configuration Lifecycle and Cleanup

Configuration files persist across application restarts, but the system handles cleanup during uninstallation. The [`scripts/uninstall.js`](https://github.com/DietrichGebert/ponytail/blob/main/scripts/uninstall.js) script invokes `getConfigPath()` to locate and remove [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json), ensuring no orphaned state remains after removal.

Third-party extensions, such as the Pi-extension in [`pi-extension/index.js`](https://github.com/DietrichGebert/ponytail/blob/main/pi-extension/index.js), consume the same configuration helpers to maintain consistency with core Ponytail behavior.

## Summary

- Ponytail stores settings in [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) under the XDG configuration directory, with platform-specific fallbacks for Windows, macOS, and Linux
- The [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) module provides functions like `getDefaultMode()` and `writeDefaultMode()` to read and persist intensity levels and UI flags
- Configuration resolution follows a strict priority: environment variables override file settings, which override hardcoded defaults
- The system validates inputs to prevent invalid modes (such as `review`) from being persisted
- The uninstall script ([`scripts/uninstall.js`](https://github.com/DietrichGebert/ponytail/blob/main/scripts/uninstall.js)) removes configuration files to prevent state leakage

## Frequently Asked Questions

### Where is the Ponytail configuration file stored?

Ponytail follows the XDG Base Directory Specification. On macOS and Linux, it stores [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) in `$XDG_CONFIG_HOME/ponytail/` or `~/.config/ponytail/`. Windows systems use `%APPDATA%\ponytail\config.json`. The exact resolution logic is implemented in `getConfigPath()` within [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js).

### How do I permanently change the default Ponytail mode?

Use the `writeDefaultMode()` function from [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js), passing one of the valid runtime modes: `off`, `lite`, `full`, or `ultra`. This writes to [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) and survives application restarts. Alternatively, set the `PONYTAIL_DEFAULT_MODE` environment variable for temporary overrides.

### What happens to my Ponytail configuration when I uninstall?

The [`scripts/uninstall.js`](https://github.com/DietrichGebert/ponytail/blob/main/scripts/uninstall.js) script automatically removes the [`config.json`](https://github.com/DietrichGebert/ponytail/blob/main/config.json) file by calling `getConfigPath()` and deleting the resolved location. This ensures no persistent user data remains after the software is removed from the system.

### Can environment variables override settings in the Ponytail config file?

Yes. Ponytail checks environment variables (`PONYTAIL_DEFAULT_MODE`, `PONYTAIL_QUIET_STARTUP`, `PONYTAIL_HIDE_STATUS`) before reading the JSON configuration file. This allows temporary, session-specific overrides without modifying persistent configuration files.