# How Ponytail Handles Host-Specific Adapters for Different AI Platforms

> Discover how Ponytail's thin-adapter architecture streamlines host-specific code for diverse AI platforms like Claude Code, Codex, and Hermes, enhancing shared skill logic.

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

---

**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 assistant
- `ponytail-review` — code review mode
- `ponytail-audit` — security audit mode
- `ponytail-debt` — technical debt analysis
- `ponytail-gain` — optimization suggestions
- `ponytail-help` — documentation mode

Each skill's [`SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/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`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md) — compact universal rule set
- [`.cursor/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.cursor/rules/ponytail.md) — Cursor-specific copy
- [`.windsurf/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.windsurf/rules/ponytail.md) — Windsurf copy
- [`.qoder/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.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`](https://github.com/DietrichGebert/ponytail/blob/main/.qoder-plugin/plugin.json) |
| Hook configuration | Maps lifecycle events to handler files | [`hooks/qoder-hooks.json`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/qoder-hooks.json) |
| Mode tracker | Parses `/ponytail` commands, persists state | [`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-mode-tracker.js) |
| Activation script | Runs on `sessionStart` | [`hooks/ponytail-activate.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-activate.js) |

The shared [`ponytail-mcp/instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/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`](https://github.com/DietrichGebert/ponytail/blob/main/.qoder-plugin/plugin.json) demonstrates the pattern:

```json
{
  "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`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/qoder-hooks.json):

```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`](https://github.com/DietrichGebert/ponytail/blob/main/__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`](https://github.com/DietrichGebert/ponytail/blob/main/.claude-plugin/plugin.json), `commands/`, [`hooks/claude-codex-hooks.json`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/claude-codex-hooks.json)

Complete implementation with session activation, mode tracking, and status-line integration.

**Codex** — [`.codex-plugin/plugin.json`](https://github.com/DietrichGebert/ponytail/blob/main/.codex-plugin/plugin.json), [`hooks/claude-codex-hooks.json`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/claude-codex-hooks.json)

Identical feature set to Claude Code, sharing the same hook file.

**Hermes Agent** — [`plugin.yaml`](https://github.com/DietrichGebert/ponytail/blob/main/plugin.yaml), [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py)

Native Python plugin using Hermes's `pre_llm_call` hook for context injection. The [`__init__.py`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py) implements slash-command rewriting and skill registration:

```python

# 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`](https://github.com/DietrichGebert/ponytail/blob/main/.qoder-plugin/plugin.json), [`hooks/qoder-hooks.json`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/qoder-hooks.json)

Auto-loads [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/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`](https://github.com/DietrichGebert/ponytail/blob/main/.cursor/rules/ponytail.md) | Rules file in project root |
| Windsurf | [`.windsurf/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.windsurf/rules/ponytail.md) | IDE-specific rules directory |
| Cline | [`.cline/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.cline/rules/ponytail.md) | Same pattern |
| Antigravity | [`.antigravity/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.antigravity/rules/ponytail.md) | Same pattern |
| Gemini CLI | [`gemini-extension.json`](https://github.com/DietrichGebert/ponytail/blob/main/gemini-extension.json) | `contextFileName` → [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md) |
| GitHub Copilot | [`.github/copilot-instructions.md`](https://github.com/DietrichGebert/ponytail/blob/main/.github/copilot-instructions.md) | Repository-level instructions |

### MCP Server Adapter

**[`ponytail-mcp/index.js`](https://github.com/DietrichGebert/ponytail/blob/main/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):

```bash

# Start the MCP server

node ponytail-mcp/index.js --mode ultra

```

Tool invocation from any MCP client:

```json
{
  "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`](https://github.com/DietrichGebert/ponytail/blob/main/.grok-plugin/marketplace.json), [`plugin.json`](https://github.com/DietrichGebert/ponytail/blob/main/plugin.json)

Installable via `grok plugin install ponytail`. Uses always-on rules without lifecycle hooks.

## Practical Adapter Usage Examples

### Switching Modes in Claude Code

```javascript
// In an active Claude Code session
/ponytail full

```

The `userPromptSubmitted` hook in [`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/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

```bash
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

```python

# 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`](https://github.com/DietrichGebert/ponytail/blob/main/__init__.py) automatically injects the correct [`SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/SKILL.md) content based on the active skill and mode.

### Direct MCP Tool Call

```bash

# 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`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/instructions.js)
- **Single source of truth** — `skills/*/SKILL.md` files 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`](https://github.com/DietrichGebert/ponytail/blob/main/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`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/index.js)) provides a clean, protocol-based integration for any tool-capable host
- All adapters share [`ponytail-mcp/instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/instructions.js) for instruction building, ensuring identical behavior across platforms
- Mode-specific injection happens via `build_injected_context` (Hermes) or `buildInstructions` (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`](https://github.com/DietrichGebert/ponytail/blob/main/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`](https://github.com/DietrichGebert/ponytail/blob/main/SKILL.md) files, not every adapter.

### Can I use Ponytail with a host not in the supported list?

Yes. Copy [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/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`](https://github.com/DietrichGebert/ponytail/blob/main/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`](https://github.com/DietrichGebert/ponytail/blob/main/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.