Where Ponytail Stores Its Active Mode Flag for Persistence

Ponytail persists its active mode flag in a hidden file named .ponytail-active located inside environment-specific configuration directories such as ~/.claude, ~/.qoder, or the path specified by PLUGIN_DATA.

The open-source tool Ponytail (DietrichGebert/ponytail) maintains its operational state across process restarts by writing the current mode to a simple text file. Understanding exactly where this active mode flag resides—and how the runtime resolves its location—is critical for debugging, manual configuration resets, or integrating with custom environments.

The .ponytail-active State File

Ponytail uses a single hidden file named .ponytail-active to store the current mode as a plain-text string.

When present, the file contains values such as full, lite, or ultra. If the file is missing, Ponytail interprets this as the off state and behaves accordingly.

Environment-Specific Storage Locations

The directory containing the active mode flag is determined at runtime based on the detected environment:

  • Native Claude: Defaults to the Claude configuration directory, resolved via getClaudeDir() (typically $HOME/.claude)
  • VS Code Copilot: Uses process.env.COPILOT_PLUGIN_DATA if available, otherwise falls back to getClaudeDir()
  • Codex: Uses process.env.PLUGIN_DATA directly
  • Qoder: Creates and uses a dedicated directory at path.join(os.homedir(), '.qoder')

This logic results in default paths such as ~/.claude/.ponytail-active for standard Claude usage or ~/.qoder/.ponytail-active when running under Qoder.

Runtime Resolution Logic in ponytail-runtime.js

The core implementation for resolving, reading, and writing the active mode flag lives in hooks/ponytail-runtime.js.

Directory Selection Algorithm

Lines 24-30 determine the target directory by checking environment flags in priority order:

let stateDir = getClaudeDir();
if (isCodex) stateDir = process.env.PLUGIN_DATA;
if (isCopilot) stateDir = process.env.COPILOT_PLUGIN_DATA || getClaudeDir();
if (isQoder) stateDir = path.join(os.homedir(), '.qoder');

The filename constant is defined at line 6:

const STATE_FILE = '.ponytail-active';

And the complete persistence path is assembled at line 31:

const statePath = path.join(stateDir, STATE_FILE);

Managing the Active Mode Flag

The runtime exposes three helper functions to interact with the state file, implemented in lines 33-49:

  • setMode(mode): Creates the target directory if it does not exist, then writes the mode string to .ponytail-active
  • readMode(): Reads the file and returns the trimmed mode string, or null if the file is absent
  • clearMode(): Deletes the flag file, effectively setting the active mode to off

Practical Code Example

const { readMode, setMode, clearMode } = require('./hooks/ponytail-runtime');

// Persist the mode as "ultra"
setMode('ultra');

// Later, or in a separate process, retrieve the persisted active mode
const current = readMode();
console.log('Current Ponytail mode:', current); // "ultra"

// Reset the mode (turn Ponytail off)
clearMode();
console.log('Mode after clear:', readMode()); // null

Several files in the DietrichGebert/ponytail repository interact with the active mode flag:

File Purpose
hooks/ponytail-runtime.js Defines STATE_FILE, implements directory resolution (lines 24-30), and provides setMode(), readMode(), and clearMode()
hooks/ponytail-config.js Supplies getClaudeDir() and getConfigDir() helpers used to locate default configuration directories
scripts/uninstall.js Removes the flag file during cleanup via removeIfExists(path.join(getClaudeDir(), '.ponytail-active'))
tests/hooks.test.js Validates flag creation, cross-process persistence, and proper cleanup across supported plugin environments

Summary

  • Ponytail stores its active mode flag in a hidden file named .ponytail-active inside environment-specific directories.
  • Native Claude environments default to ~/.claude/.ponytail-active, while Qoder uses ~/.qoder/.ponytail-active, and Codex respects the PLUGIN_DATA environment variable.
  • The resolution and I/O logic is centralized in hooks/ponytail-runtime.js, specifically at lines 6 (constant definition), 24-30 (directory selection), and 33-49 (helper functions).
  • The setMode(), readMode(), and clearMode() functions provide a complete API for state management.
  • The uninstall script at scripts/uninstall.js explicitly targets this file to ensure clean removal.

Frequently Asked Questions

What happens if I manually delete the .ponytail-active file?

If you manually remove the file, Ponytail treats this as an "off" state. The next call to readMode() returns null, and the tool behaves as if no mode is active until setMode() recreates the file with a new value.

Can I change the location where the active mode flag is stored?

The storage location is hardcoded in hooks/ponytail-runtime.js relative to environment variables and the getClaudeDir() helper. To use a custom location, you must modify the stateDir assignment logic in lines 24-30, or set the appropriate environment variables (PLUGIN_DATA, COPILOT_PLUGIN_DATA, or QODER_SESSION_ID) before launching Ponytail.

Why does Ponytail use a text file for persistence instead of a database or registry?

According to the source code in hooks/ponytail-runtime.js, Ponytail uses a simple text file to ensure portability across Claude, Copilot, Codex, and Qoder environments without external dependencies. A single hidden file works identically across macOS, Linux, and Windows file systems and requires no administrative privileges or complex setup.

How do I completely reset Ponytail to its default state?

To fully reset Ponytail, invoke clearMode() from hooks/ponytail-runtime.js or manually delete the .ponytail-active file from your configuration directory (typically ~/.claude/.ponytail-active or ~/.qoder/.ponytail-active). The scripts/uninstall.js script also performs this cleanup automatically during removal.

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 →