# How Ponytail Filters Mode-Specific Instructions from Skill Files

> Discover how Ponytail filters mode-specific instructions from skill files. Learn to parse Markdown line-by-line, keeping only relevant content for lite, full, ultra, or review modes.

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

---

**Ponytail filters mode-specific instructions by parsing the Markdown skill file line-by-line, keeping only intensity table rows and worked-example bullets that match the active mode (lite, full, ultra, or review) while preserving all generic content.**

Ponytail stores its prompting rules in a Markdown skill file located at [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md). When a user activates a specific intensity level, the system dynamically tailors the prompt by extracting only the relevant sections from this master file. This filtering mechanism ensures that the language model receives precisely calibrated instructions based on the selected operational mode.

## The Skill File Structure

The source of truth for Ponytail’s behavior lives in **[`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md)**. This file contains the complete set of rules organized into three distinct content types:

- **Generic prose** – Universal guidelines that apply regardless of mode
- **Intensity tables** – Markdown tables with rows labeled by mode (e.g., `| **lite** | ... |`)
- **Worked examples** – Bullet lists with mode prefixes (e.g., `- lite: "..."`)

The filtering system treats these content types differently, preserving generic prose while conditionally extracting table rows and bullets based on the active mode.

## Core Filtering Logic in `filterSkillBodyForMode`

The heart of the filtering system resides in **[`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js)**, specifically within the `filterSkillBodyForMode` function. This function executes a four-stage pipeline to transform the raw skill file into mode-specific instructions.

### Step 1: Normalizing the Requested Mode

Before processing content, the function canonicalizes the mode string via `normalizeMode` (defined in **[`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js)**). Supported modes include `lite`, `full`, `ultra`, and `review`. If the requested mode is undefined or invalid, the system falls back to the `DEFAULT_MODE` constant.

```javascript
// From hooks/ponytail-config.js
const normalizeMode = (mode) => {
  const valid = ['lite', 'full', 'ultra', 'review'];
  return valid.includes(mode) ? mode : DEFAULT_MODE;
};

```

### Step 2: Stripping Front-Matter

The function removes the leading YAML front-matter block (delimited by `---`) from the skill file. This ensures that metadata headers do not contaminate the instruction set sent to the language model.

### Step 3: Line-by-Line Inspection

The body content splits on line breaks, and each line undergoes pattern matching against two specific regex filters:

**Intensity Table Rows**
Lines matching `^\|\s*\*\*(.+?)\*\*\s*\|` indicate table rows with bold mode labels. The capture group extracts the mode name (e.g., `lite`). The line is retained **only** if the extracted mode matches the effective mode.

**Worked-Example Bullets**
Lines matching `^-\s*([^:]+):\s*"` indicate mode-prefixed bullet points. The capture group extracts the leading word before the colon. If this word normalizes to a valid mode, the line is kept only when it matches the active mode.

**All Other Lines**
Any line failing to match either pattern is preserved verbatim, ensuring generic rules survive every mode filter.

### Step 4: Reconstructing the Output

The filtered lines concatenate back into a single string. This processed content becomes the mode-specific instruction set returned by `getPonytailInstructions`.

## Mode Detection and Injection

The **[`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-mode-tracker.js)** file orchestrates the detection and injection workflow. When a user issues a `/ponytail` command followed by a mode name, the hook:

1. Detects the mode switch
2. Stores the mode via `setMode()`
3. Calls `getPonytailInstructions(mode)` to retrieve filtered content
4. Injects the result into the prompt using `writeHookOutput()`

```javascript
// From hooks/ponytail-mode-tracker.js
if (mode && mode !== 'off') {
  setMode(mode);                                 // Persist session mode
  writeHookOutput('UserPromptSubmit',
                  mode,
                  getPonytailInstructions(mode)); // Inject filtered rules
}

```

## Error Handling and Fallbacks

If `getPonytailInstructions` fails to read [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) (due to missing files or permission errors), the function invokes `getFallbackInstructions()`. This returns a hard-coded description ensuring the system remains functional even when the skill file is unavailable.

## Practical Implementation Examples

To programmatically retrieve instructions for a specific mode:

```javascript
const { getPonytailInstructions } = require('./hooks/ponytail-instructions');
const instructions = getPonytailInstructions('lite');
console.log(instructions);

```

Within the hook execution context, after detecting a valid mode transition:

```javascript
if (mode && mode !== 'off') {
  setMode(mode);
  writeHookOutput('UserPromptSubmit',
                  mode,
                  getPonytailInstructions(mode));
}

```

## Summary

- **Primary filter**: `filterSkillBodyForMode` in [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js) processes [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md)
- **Mode normalization**: `normalizeMode` in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) validates `lite`, `full`, `ultra`, `review`
- **Content parsing**: Regex patterns `^\|\s*\*\*(.+?)\*\*\s*\|` (tables) and `^-\s*([^:]+):\s*"` (bullets) identify mode-specific lines
- **Preservation logic**: Generic prose survives all filters; only table rows and worked examples undergo mode matching
- **Injection point**: [`ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mode-tracker.js) calls `writeHookOutput()` to send filtered instructions to the LLM
- **Resilience**: `getFallbackInstructions()` provides hard-coded defaults when the skill file is inaccessible

## Frequently Asked Questions

### What file contains the main filtering logic for Ponytail modes?

The **[`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js)** file contains the `filterSkillBodyForMode` function, which implements the core filtering algorithm. This function handles mode normalization, front-matter stripping, line-by-line pattern matching, and content reconstruction.

### How does Ponytail handle missing skill files?

When `getPonytailInstructions` encounters a file read error (such as a missing [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md)), it automatically falls back to `getFallbackInstructions()`. This function returns a hard-coded description of Ponytail's capabilities, ensuring the hook continues functioning even without the skill file present.

### What regex patterns does Ponytail use to identify mode-specific content?

Ponytail employs two specific regular expressions: `^\|\s*\*\*(.+?)\*\*\s*\|` matches intensity table rows with bold mode labels, while `^-\s*([^:]+):\s*"` matches worked-example bullets prefixed with mode names. The first capture group in each pattern extracts the mode identifier for comparison against the active mode.

### Which modes does Ponytail support for instruction filtering?

The system supports four distinct intensity levels: **`lite`**, **`full`**, **`ultra`**, and **`review`**. These modes are defined in [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) alongside the `DEFAULT_MODE` constant and the `normalizeMode` validation function that ensures only recognized modes trigger specific filtering logic.