How Ponytail Injects Rulesets and Context into an Agent's System Prompt
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:
- Activation: Initializes mode state and delivers the initial ruleset payload
- Tracking: Monitors runtime mode switches and updates context accordingly
- Propagation: Ensures child agents inherit the active configuration
Each stage interfaces with 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 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, 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 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 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
hookSpecificOutputobject without thesystemMessagefield - 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. The getPonytailInstructions(mode) function reads 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:
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:
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:
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 inhooks/ponytail-runtime.jsabstracts platform differences between Copilot, Codex, Qoder, and native Claude - Rulesets filter through intensity levels (lite/full/ultra) via
getPonytailInstructions()inhooks/ponytail-instructions.js - Mode persistence relies on a flag file (
.ponytail-active) updated bysetMode()and monitored across all hook scripts - Sub-agents automatically inherit rulesets through
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 script handles SessionStart, while 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. 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 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 is unreadable or absent, the getPonytailInstructions() function in 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.
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 →