# How Ponytail Mode Precedence Works: Runtime, Config, and Default Resolution

> Understand Ponytail mode precedence. Learn how runtime commands, config files, and default settings determine the effective mode in your application.

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

---

**Ponytail resolves the effective mode by checking three sources in strict priority: runtime slash commands override configuration files, which override the built-in default of `"full"`.**

The `DietrichGebert/ponytail` repository implements a deterministic mode precedence system that controls which parts of the built-in skill are injected into LLM prompts. Understanding Ponytail mode precedence is essential for configuring how the tool behaves across different environments and sessions.

## The Three-Tier Mode Resolution Hierarchy

Ponytail determines the effective mode by evaluating three independent sources in descending order of priority. This ensures that the most specific instruction always governs the injected context.

### 1. Runtime Slash Commands (Highest Priority)

The `/ponytail <mode>` slash command provides immediate, session-specific control. When invoked, the `_handle_mode_command()` function (defined in [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py) at lines 167–177) normalizes the argument via `_normalize_runtime_mode()` and stores the result in the module-level variable `_current_mode`. This runtime setting persists for the duration of the session and overrides all other configuration sources.

### 2. Configuration Layer

If no runtime mode is active, Ponytail falls back to the configuration layer via the `_default_mode()` function (lines 52–63 in [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py)). This function checks two sources in order:

- **Environment variable**: `PONYTAIL_DEFAULT_MODE` takes precedence if set.
- **Config file**: `~/.config/ponytail/config.json` is parsed for the `defaultMode` field if the environment variable is absent.

### 3. Built-in Default Fallback

When neither runtime nor configuration sources provide a value, Ponytail uses the hard-coded constant `DEFAULT_MODE = "full"` defined in [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py). This ensures the system always has a valid mode even in clean environments.

## Resolution Flow and Skill Content Filtering

The resolution logic combines these sources in `build_injected_context()` (lines 105–122) using the following flow:

```python
configured = _normalize_config_mode(mode) or _default_mode()          # ← step 2

effective = _normalize_runtime_mode(configured) or DEFAULT_MODE      # ← step 1

```

Once the effective mode is determined, the system filters the skill content. The `_filter_skill_body_for_mode()` function (lines 70–85 in [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py)) parses the markdown in [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) and removes any block whose mode label does not match the effective mode. For example, sections marked with `| **lite** |` or `- lite: …` are preserved only when the effective mode is `"lite"`.

This filtering enables a single skill file to contain tiered advice, with granular control over which sections reach the LLM prompt based on the resolved precedence.

## Special Mode Behaviors

Two modes trigger unique behaviors beyond standard content filtering:

- **`"off"`** → Injected context becomes an empty string, effectively disabling Ponytail's skill injection.
- **`"review"`** → Loads the separate review skill from [`skills/ponytail-review/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail-review/SKILL.md) instead of the standard ponytail skill.

## Practical Configuration Examples

Configure Ponytail mode precedence using these patterns:

```python

# 1️⃣ Set mode at runtime (slash command)

# In a chat with Hermes:

#   /ponytail ultra

# The command triggers `_handle_mode_command`, storing `_current_mode = "ultra"`.

```

```python

# 2️⃣ Set a default via environment variable

import os
os.environ["PONYTAIL_DEFAULT_MODE"] = "lite"

# No runtime command; Ponytail will use "lite" for every session.

```

```json
// 3️⃣ Provide a config file (~/.config/ponytail/config.json)
{
  "defaultMode": "full"
}
// With no env var and no runtime command, "full" is used.

```

```python

# 4️⃣ Disable injection completely

os.environ["PONYTAIL_DEFAULT_MODE"] = "off"

# or `/ponytail off` → injected context becomes an empty string.

```

```python

# 5️⃣ Inspect which text is injected

from ponytail import build_injected_context
print(build_injected_context())   # respects the precedence rules above

```

## Summary

- **Runtime commands** take precedence over all other sources via `_current_mode`.
- **Configuration** follows the order: `PONYTAIL_DEFAULT_MODE` environment variable, then `~/.config/ponytail/config.json` (`defaultMode` field).
- **Built-in default** is `"full"` when no other value is set.
- **Content filtering** applies the effective mode to skill markdown sections via `_filter_skill_body_for_mode()`.
- **Special modes** `"off"` and `"review"` modify behavior by disabling injection or loading alternate skills.

## Frequently Asked Questions

### What is the default mode if I don't configure anything?

The built-in constant `DEFAULT_MODE = "full"` in [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py) serves as the final fallback when no runtime command is active and neither the `PONYTAIL_DEFAULT_MODE` environment variable nor the config file exists.

### How do I temporarily override the mode for a single session?

Use the `/ponytail <mode>` slash command, which triggers `_handle_mode_command()` and sets the module-level `_current_mode` variable. This persists for the session but does not modify configuration files or environment variables.

### What happens when I set the mode to "off"?

The system returns an empty string for the injected context, effectively disabling Ponytail's skill injection. This is processed early in `build_injected_context()` before any skill content filtering occurs.

### Where is the mode resolution logic implemented in the source code?

All core logic resides in [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py) within the `DietrichGebert/ponytail` repository. Key functions include `_default_mode()` for configuration resolution, `_handle_mode_command()` for runtime overrides, and `_filter_skill_body_for_mode()` for content filtering.