How Ponytail Handles Host-Specific Adapters for Different AI Platforms
Ponytail uses a thin-adapter architecture that keeps core logic in shared skill files while providing host-specific glue code for Claude Code, Codex, OpenCode, Hermes, MCP servers, and others.
The Ponytail project—available at DietrichGebert/ponytail—implements a "lazy senior developer" coding assistant that runs across dozens of AI platforms. Rather than duplicating logic for every host, the codebase separates core behavior from platform-specific adapters, enabling consistent behavior with minimal per-host code.
The Three-Layer Adapter Architecture
Ponytail organizes its host support into three conceptual layers. Understanding this structure explains why adding a new platform requires only thin wiring code.
Core Skills Layer
The six Ponytail skills live under skills/ as markdown rule files:
ponytail— main coding assistantponytail-review— code review modeponytail-audit— security audit modeponytail-debt— technical debt analysisponytail-gain— optimization suggestionsponytail-help— documentation mode
Each skill's SKILL.md contains the complete rule set injected into the model's prompt. Adapters never re-implement this logic—they only point the host at the correct file path.
Always-On Rule Files
For hosts without skill or hook support, Ponytail provides static rule copies:
AGENTS.md— compact universal rule set.cursor/rules/ponytail.md— Cursor-specific copy.windsurf/rules/ponytail.md— Windsurf copy.qoder/rules/ponytail.md— Qoder copy
These files contain identical logic reformatted for each host's expected structure.
Plugin Manifests and Hook Wiring
Full-featured adapters use JSON/YAML manifests and JavaScript hook files:
| Component | Purpose | Example Path |
|---|---|---|
| Plugin manifest | Declares version, entry points, skill paths | .qoder-plugin/plugin.json |
| Hook configuration | Maps lifecycle events to handler files | hooks/qoder-hooks.json |
| Mode tracker | Parses /ponytail commands, persists state |
hooks/ponytail-mode-tracker.js |
| Activation script | Runs on sessionStart |
hooks/ponytail-activate.js |
The shared ponytail-mcp/instructions.js builds the actual instruction payload, ensuring all adapters inject identical context regardless of host platform.
How Host-Specific Adapters Work
The adapter lifecycle follows four standard phases across all supported platforms.
1. Discovery via Manifest
When a host initializes, it reads a platform-specific manifest file. The Qoder manifest at .qoder-plugin/plugin.json demonstrates the pattern:
{
"name": "ponytail",
"version": "1.0.0",
"skillsDir": "skills/",
"hooks": "hooks/qoder-hooks.json",
"commands": ["/ponytail", "/ponytail-review"]
}
The skillsDir field enables skill registration; the hooks field enables lifecycle integration.
2. Hook Registration and Execution
The hook configuration file maps host events to handler scripts. From hooks/qoder-hooks.json:
{
"sessionStart": "hooks/ponytail-activate.js",
"userPromptSubmitted": "hooks/ponytail-mode-tracker.js"
}
These hooks execute at precise moments in the conversation lifecycle, enabling stateful mode management without host-native code.
3. Skill Registration
For hosts supporting callable skills (Claude Code, Codex, Hermes, OpenCode, pi), the manifest registers each skills/<name>/SKILL.md as an invocable tool. Users trigger skills via:
ponytail:review(Claude Code style)@ponytail-review(Codex style)/ponytail-review(Discord-like slash commands)
4. Mode-Specific Injection
The critical function build_injected_context (Hermes __init__.py) or buildInstructions (MCP server) filters the skill markdown by current mode before each LLM call. This ensures the model receives only relevant instructions—ultra mode for exhaustive analysis, lite for quick tasks, review for focused critique.
Supported Host Adapters
Ponytail ships working adapters for 12+ AI platforms, organized by capability level.
Full-Featured Adapters (Skills + Hooks + Commands)
Claude Code — .claude-plugin/plugin.json, commands/, hooks/claude-codex-hooks.json
Complete implementation with session activation, mode tracking, and status-line integration.
Codex — .codex-plugin/plugin.json, hooks/claude-codex-hooks.json
Identical feature set to Claude Code, sharing the same hook file.
Hermes Agent — plugin.yaml, __init__.py
Native Python plugin using Hermes's pre_llm_call hook for context injection. The __init__.py implements slash-command rewriting and skill registration:
# Hermes skill registration
ctx.register_skill('ponytail', Path('skills/ponytail/SKILL.md'))
# Pre-LLM injection hook
async def pre_llm_call(self, context):
mode = self.get_mode()
context.system_prompt += build_injected_context(mode)
OpenCode — .opencode/plugins/ponytail.mjs
Server plugin using experimental.chat.system.transform to modify prompts each turn.
Qoder — .qoder-plugin/plugin.json, hooks/qoder-hooks.json
Auto-loads AGENTS.md and provides all six skills with full hook support.
Always-On Rule Adapters (Static Files Only)
These hosts read rules but don't support dynamic hooks:
| Host | Adapter Location | Mechanism |
|---|---|---|
| Cursor | .cursor/rules/ponytail.md |
Rules file in project root |
| Windsurf | .windsurf/rules/ponytail.md |
IDE-specific rules directory |
| Cline | .cline/rules/ponytail.md |
Same pattern |
| Antigravity | .antigravity/rules/ponytail.md |
Same pattern |
| Gemini CLI | gemini-extension.json |
contextFileName → AGENTS.md |
| GitHub Copilot | .github/copilot-instructions.md |
Repository-level instructions |
MCP Server Adapter
ponytail-mcp/index.js — Platform-agnostic entry point for any MCP-capable host.
The MCP server exposes Ponytail as both a prompt (for direct injection) and a tool (for on-demand retrieval):
# Start the MCP server
node ponytail-mcp/index.js --mode ultra
Tool invocation from any MCP client:
{
"tool": "ponytail_instructions",
"input": { "mode": "lite" }
}
Response includes structured instructions and plain-text version. This adapter does not replace always-on adapters—it provides an optional, clean integration path for tool-aware hosts.
Marketplace/Distribution Adapters
Grok Build — .grok-plugin/marketplace.json, plugin.json
Installable via grok plugin install ponytail. Uses always-on rules without lifecycle hooks.
Practical Adapter Usage Examples
Switching Modes in Claude Code
// In an active Claude Code session
/ponytail full
The userPromptSubmitted hook in hooks/ponytail-mode-tracker.js detects this command, writes "full" to a temporary state file, and returns the complete instruction set for the new mode.
Using OpenCode with Plugin
opencode chat --plugin ponytail.mjs --prompt "Refactor this React component"
The experimental.chat.system.transform hook calls buildInstructions(currentMode) before every turn, ensuring consistent behavior across the conversation.
Hermes Agent Script Integration
# In a Hermes agent workflow
await ctx.run_skill('ponytail-audit') # Triggers security audit rules
await ctx.run_skill('ponytail') # Returns to default coding mode
The pre_llm_call hook in __init__.py automatically injects the correct SKILL.md content based on the active skill and mode.
Direct MCP Tool Call
# From any MCP-compatible client
echo '{"tool": "ponytail_instructions", "input": {"mode": "debt"}}' \
| node ponytail-mcp/index.js
Returns technical debt analysis rules formatted for immediate use.
Key Design Principles
The Ponytail adapter system follows strict architectural constraints visible throughout the source:
- Adapters stay thin — No logic duplication; all instruction building flows through
ponytail-mcp/instructions.js - Single source of truth —
skills/*/SKILL.mdfiles are the authoritative rules - Host capability detection — Adapters degrade gracefully: full hooks where supported, static files where not
- Stateless where possible — Mode state lives in environment variables or temp files, not host-specific storage
These principles appear in the docs/agent-portability.md documentation and are enforced by the shared buildInstructions implementation.
Summary
- Ponytail separates core skills (
skills/*/SKILL.md) from host-specific adapters that wire those skills to platform APIs - Full-featured adapters (Claude Code, Codex, Hermes, OpenCode, Qoder, pi) use manifests, hooks, and mode-tracking scripts to enable dynamic skill switching
- Always-on adapters (Cursor, Windsurf, Gemini, Copilot) copy static rule files to host-expected locations
- The MCP server adapter (
ponytail-mcp/index.js) provides a clean, protocol-based integration for any tool-capable host - All adapters share
ponytail-mcp/instructions.jsfor instruction building, ensuring identical behavior across platforms - Mode-specific injection happens via
build_injected_context(Hermes) orbuildInstructions(MCP), filtering skill content before each LLM call
Frequently Asked Questions
What makes a Ponytail adapter "thin"?
A thin adapter contains only platform-specific glue code—manifest parsing, hook registration, and event forwarding—while delegating all instruction building to shared scripts like ponytail-mcp/instructions.js. The "no logic in adapters" rule ensures that fixing a bug in skill behavior requires changing only the core SKILL.md files, not every adapter.
Can I use Ponytail with a host not in the supported list?
Yes. Copy AGENTS.md or any skills/*/SKILL.md file to your host's rules/instructions location. For hosts supporting custom tools or MCP, run node ponytail-mcp/index.js and configure the host to connect to this server. The docs/agent-portability.md file provides guidance for building new adapters.
How does mode switching work across different adapters?
Mode state persists in environment variables or temporary flag files (e.g., .ponytail_mode), readable by all hook scripts. When you type /ponytail review in Claude Code or Codex, hooks/ponytail-mode-tracker.js writes this state; the next pre_llm_call or userPromptSubmitted hook reads it and calls buildInstructions(mode) with the new value.
What's the difference between a skill and a mode in Ponytail?
A skill is a complete rule set in skills/<name>/SKILL.md (e.g., ponytail-review). A mode is a filtering parameter (lite, full, ultra) passed to build_instructions that selects how much of the active skill's content to inject. Skills switch behavior categories; modes adjust depth within a category.
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 →