# What Is `hooks/ponytail-runtime.js`? Purpose and Implementation in Ponytail

> Understand hooks/ponytail-runtime.js, the core Ponytail runtime. Learn how it enables communication with VS Code Copilot, Codex, Qoder, and Claude by managing environment detection, state persistence, and hook output formatting.

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

---

**[`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js)** is the central runtime helper that enables Ponytail to communicate its current mode to VS Code Copilot, Codex, Qoder, and native Claude by detecting the host environment, persisting state to disk, and formatting platform-specific hook outputs.

In the DietrichGebert/ponytail repository, [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) functions as the unified communication layer between Ponytail's core logic and the various AI assistant platforms it supports. This single file abstracts environment detection, state management, and output formatting to ensure consistent **"PONYTAIL:<MODE>"** signaling across different coding assistants.

## Core Responsibilities of [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js)

### Environment Detection (Lines 13-23)

The runtime begins by identifying which AI assistant is hosting Ponytail. As implemented in lines 13-23 of [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js), the script sets three Boolean flags—**`isCopilot`**, **`isCodex`**, and **`isQoder`**—by inspecting the execution context. If none of these flags match, the system defaults to native **Claude UI** mode.

### Mode Persistence (Lines 33-49)

To maintain state across sessions, the file manages a hidden `.ponytail-active` file stored in platform-specific directories. The **`setMode()`** function creates this file with the current mode string, while **`readMode()`** retrieves the stored value and **`clearMode()`** removes the file for cleanup. These operations rely on directory helpers from [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js), which provides `getClaudeDir()` and `getConfigDir()` to locate the appropriate state directory for each environment.

### Hook Output Formatting (Lines 51-90)

The **`writeHookOutput()`** function generates environment-specific JSON payloads based on the detected host. For **VS Code Copilot**, it emits `additionalContext` only during `SessionStart` events. **Codex** receives a `systemMessage` with the mode plus optional `hookSpecificOutput`, while **Qoder** gets similar formatting without the system message wrapper. For **native Claude**, the function sends raw `additionalContext` for `SessionStart` or wraps it in a `hookSpecificOutput` object for `SubagentStart`.

## Working with [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js): Practical Examples

The following examples demonstrate how to interact with the runtime's public API:

### Setting and Reading the Current Mode

To activate **Ponytail** in live mode or check the current state:

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

// Activate live mode - creates .ponytail-active file
setMode('live');

// Read current state
const current = readMode();   // => 'live' | 'off' | null
console.log(`Ponytail is ${current || 'inactive'}`);

```

### Emitting Formatted Output for VS Code Copilot

When running under Copilot, use `writeHookOutput` with the `isCopilot` flag:

```javascript
const { writeHookOutput, isCopilot } = require('./hooks/ponytail-runtime');

if (isCopilot) {
  writeHookOutput('SessionStart', 'live', 'Here is extra context');
  // Output: {"additionalContext":"Here is extra context"}
}

```

### Handling Native Claude Subagent Events

For native Claude UI subagent interactions:

```javascript
const { writeHookOutput } = require('./hooks/ponytail-runtime');

writeHookOutput('SubagentStart', 'debug', 'debug information');
// Output: {"hookSpecificOutput":{"hookEventName":"SubagentStart","additionalContext":"debug information"}}

```

## Integration with the Ponytail Ecosystem

[`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) imports directory resolution logic from **[`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js)**, which exposes `getClaudeDir()` and `getConfigDir()`. The runtime's behavior is validated by **[`tests/hooks.test.js`](https://github.com/DietrichGebert/ponytail/blob/main/tests/hooks.test.js)** and consumed by the TOML command definitions in `commands/ponytail-*.toml` that trigger `setMode` and `clearMode` operations.

## Summary

- **Environment detection**: [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) identifies the host AI assistant (Copilot, Codex, Qoder, or native Claude) during initialization by setting `isCopilot`, `isCodex`, and `isQoder` flags.
- **Mode persistence**: The runtime stores the current operational mode (**live**, **off**, or **debug**) in a `.ponytail-active` file using `setMode()`, `readMode()`, and `clearMode()`.
- **Output formatting**: The `writeHookOutput()` function emits JSON payloads tailored to each platform's expected input structure, handling `SessionStart` and `SubagentStart` events differently per environment.
- **Cross-agent consistency**: By centralizing these responsibilities, the file ensures that all supported agents receive a consistent mode signal regardless of the underlying platform.

## Frequently Asked Questions

### What is the primary purpose of [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js)?

[`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) serves as the central runtime helper bridging Ponytail's core with AI assistant environments. It detects the host platform, persists modes to disk, and formats output for VS Code Copilot, Codex, Qoder, and Claude.

### How does [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) detect which AI assistant is running?

The runtime inspects execution context at lines 13-23 to set Boolean flags `isCopilot`, `isCodex`, and `isQoder`. If none match, it defaults to native Claude UI mode.

### Where does Ponytail store the current mode state?

The runtime stores modes in a hidden `.ponytail-active` file via `setMode()`, using directories resolved by `getClaudeDir()` and `getConfigDir()` from [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js). This handles Claude config, Copilot plugin data, and Qoder home paths.

### Can I use functions from [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) in my own scripts?

Yes, you can require the module to call `setMode()`, `readMode()`, or `writeHookOutput()` for custom integrations. However, it is designed primarily for internal use by Ponytail's TOML command definitions.