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_DATAif available, otherwise falls back togetClaudeDir() - Codex: Uses
process.env.PLUGIN_DATAdirectly - 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-activereadMode(): Reads the file and returns the trimmed mode string, ornullif the file is absentclearMode(): 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
Related Components Supporting Persistence
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-activeinside environment-specific directories. - Native Claude environments default to
~/.claude/.ponytail-active, while Qoder uses~/.qoder/.ponytail-active, and Codex respects thePLUGIN_DATAenvironment 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(), andclearMode()functions provide a complete API for state management. - The uninstall script at
scripts/uninstall.jsexplicitly 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →