# How Ponytail Injects Rulesets and Context into an Agent's System Prompt

> Discover how Ponytail injects rulesets and context into agent system prompts using lifecycle scripts and specific execution points for enhanced AI behavior.

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

---

**Ponytail injects rulesets and context into an agent's system prompt through a series of lifecycle hook scripts that write JSON output containing `additionalContext` and `systemMessage` fields at specific execution points like SessionStart, UserPromptSubmit, and SubagentStart.**

The DietrichGebert/ponytail repository implements a cross-platform injection system that ensures AI agents—whether running Claude‑Code, Copilot, or Qoder—receive curated behavioral rulesets dynamically. By intercepting agent lifecycle events, Ponytail appends structured context to the system prompt without manual copy-pasting, ensuring consistent behavior across sessions and sub-agents.

## The Injection Architecture

Ponytail operates through five specialized components that coordinate to modify the agent's environment. The core mechanism relies on **hook scripts** that execute at predefined lifecycle events, generating JSON output that agent implementations parse into their system prompts.

The workflow flows through three distinct stages:

1. **Activation**: Initializes mode state and delivers the initial ruleset payload
2. **Tracking**: Monitors runtime mode switches and updates context accordingly  
3. **Propagation**: Ensures child agents inherit the active configuration

Each stage interfaces with [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js), which abstracts platform-specific output formats to ensure compatibility across Copilot, Codex (Claude‑Code), Qoder, and native Claude implementations.

## Lifecycle Hook Mechanisms

### Session Activation via ponytail-activate.js

The [`hooks/ponytail-activate.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-activate.js) script executes on every **SessionStart** event. It performs two critical operations: persisting the active mode to a flag file (`.ponytail-active`) and emitting the filtered ruleset as hidden context.

For **Copilot**, the script outputs a JSON object containing only the `additionalContext` field during SessionStart. **Claude‑Code (Codex)** receives a more complex payload including a `systemMessage` field prefixed with `PONYTAIL:<MODE>` and a nested `hookSpecificOutput` object carrying the ruleset. **Qoder** defers injection to the UserPromptSubmit phase rather than SessionStart, ensuring context arrives at the appropriate processing stage.

### Mode Tracking via ponytail-mode-tracker.js

User-initiated mode changes trigger [`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-mode-tracker.js), which parses `/ponytail` commands embedded in prompts. When detecting a mode switch, the script invokes `setMode()` to update the flag file and calls `writeHookOutput()` to emit confirmation messaging.

For non‑Qoder agents, this generates a confirmation header. For Qoder specifically, the tracker **injects the ruleset on the same prompt** that triggered the mode change, combining the confirmation header and ruleset into a single payload so the agent receives both simultaneously.

### Sub-agent Propagation via ponytail-subagent.js

When agents spawn child processes, [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js) executes as a **SubagentStart** hook. It checks for active Ponytail mode by reading the flag file, then forwards the identical ruleset to spawned sub-agents. The optional `PONYTAIL_SUBAGENT_MATCHER` regex allows scoping this behavior to specific sub-agent types, ensuring rulesets propagate across the entire agent tree while respecting boundary constraints.

## Runtime Output Abstraction

The [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) file contains the centralized `writeHookOutput(event, mode, context)` function that handles platform-specific serialization differences:

- **Copilot**: Writes `{"additionalContext": context}` exclusively for SessionStart events
- **Codex**: Produces `{"systemMessage": "PONYTAIL:<MODE>", "hookSpecificOutput": {"hookEventName": event, "additionalContext": context}}`
- **Qoder**: Emits only the `hookSpecificOutput` object without the `systemMessage` field
- **Native Claude**: For SubagentStart, outputs JSON with `hookSpecificOutput`; for other events, writes the plain context string directly

This abstraction ensures that regardless of the underlying agent platform, the ruleset reaches the system prompt through the appropriate channel—whether via `additionalContext` injection or direct string appending.

## Ruleset Generation

Content generation resides in [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js). The `getPonytailInstructions(mode)` function reads [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) and filters the markdown content based on the requested intensity level—**lite**, **full**, or **ultra**—returning only the relevant sections.

If the skill file is unreadable or missing, `getFallbackInstructions()` provides a hard-coded default ruleset to prevent injection failures. This dual-path approach ensures that the system prompt always receives valid context, even when file system issues occur.

## Implementation Examples

Activate Ponytail during session initialization for a Copilot environment:

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

const mode = 'full';
const rules = getPonytailInstructions(mode);
writeHookOutput('SessionStart', mode, rules);
// stdout: {"additionalContext":"PONYTAIL MODE ACTIVE — level: full\n\n…rules…"}

```

Switch modes dynamically during a Codex session:

```javascript
const { setMode, writeHookOutput } = require('./ponytail-runtime');
const { getPonytailInstructions } = require('./ponytail-instructions');

setMode('ultra');
const rules = getPonytailInstructions('ultra');
writeHookOutput('UserPromptSubmit', 'ultra',
  'PONYTAIL MODE CHANGED — level: ultra\n\n' + rules);
// stdout: {"systemMessage":"PONYTAIL:ULTRA","hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"PONYTAIL MODE CHANGED — level: ultra\n\n…rules…"}}

```

Inject rulesets into spawned sub-agents to maintain consistency:

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

const mode = 'lite';
writeHookOutput('SubagentStart', mode, getPonytailInstructions(mode));
// Sub-agent receives identical ruleset as parent agent

```

## Summary

- Ponytail utilizes **lifecycle hooks** at SessionStart, UserPromptSubmit, and SubagentStart events to intercept agent execution points
- The `writeHookOutput()` function in [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) abstracts platform differences between Copilot, Codex, Qoder, and native Claude
- Rulesets filter through intensity levels (lite/full/ultra) via `getPonytailInstructions()` in [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js)
- Mode persistence relies on a flag file (`.ponytail-active`) updated by `setMode()` and monitored across all hook scripts
- Sub-agents automatically inherit rulesets through [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js), ensuring behavioral consistency across agent hierarchies

## Frequently Asked Questions

### What triggers Ponytail ruleset injection?

Ruleset injection triggers at three specific lifecycle events: **SessionStart** (initializing the session), **UserPromptSubmit** (handling mode switches in Qoder), and **SubagentStart** (spawning child agents). The [`hooks/ponytail-activate.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-activate.js) script handles SessionStart, while [`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-mode-tracker.js) monitors ongoing prompts for `/ponytail` commands to trigger runtime updates.

### How does Ponytail handle different AI agent platforms?

Ponytail detects the target platform through the `writeHookOutput()` abstraction layer in [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js). Copilot receives simple `additionalContext` JSON, Claude‑Code receives structured output with both `systemMessage` and `hookSpecificOutput` fields, and Qoder receives trimmed payloads without system messages. This ensures the ruleset integrates correctly with each agent's specific context handling mechanism.

### Can sub-agents inherit Ponytail rulesets?

Yes. The [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js) script executes on every SubagentStart event, reading the active mode from the `.ponytail-active` flag file and forwarding the identical ruleset to child agents. The optional `PONYTAIL_SUBAGENT_MATCHER` environment variable allows filtering which sub-agent types receive the injection, enabling precise control over context propagation.

### What happens if the SKILL.md file is missing?

If [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) is unreadable or absent, the `getPonytailInstructions()` function in [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js) falls back to `getFallbackInstructions()`, which returns a hard-coded default ruleset. This ensures that the system prompt always receives valid context even when file system errors occur, preventing injection failures from breaking agent functionality.