Ponytail Architecture: How the Lazy Senior Dev Plugin Is Structured
Ponytail implements a three‑layer architecture consisting of declarative Core Skills, stateful Runtime Hooks, and thin host Adapters that inject a "lazy senior dev" mindset into any LLM‑powered coding assistant.
Ponytail is a portable agent‑skill suite developed by DietrichGebert to enforce minimalist, platform‑native coding practices across diverse LLM environments. The Ponytail architecture centers on a skill‑based rule system and runtime injection mechanism that dynamically adapts to hosts like Claude Code, Codex, and Gemini CLI without duplicating core logic.
The Three Pillars of Ponytail Architecture
The repository is organized around three structural pillars that separate behavior definition, runtime orchestration, and host integration.
Core Skills Layer
The Core Skills layer contains declarative, reusable behavior definitions stored as markdown files. Each skill resides in its own directory under skills/ponytail-<name>/ and includes a SKILL.md file that serves as both documentation and prompt template.
For example, the primary skill is defined in skills/ponytail/SKILL.md, which encodes the "lazy senior dev" ladder (YAGNI → std‑lib → platform → one‑liner) as raw text that the host agent reads directly. This design makes skills portable across any LLM client that can ingest markdown instructions.
Runtime Hooks Layer
The Runtime Hooks layer manages state persistence and context injection. Located in the hooks/ directory, these JavaScript modules detect the host environment, track the current intensity mode, and format output accordingly.
Key files include:
hooks/ponytail-runtime.js– Detects the host via environment variables (COPILOT_PLUGIN_DATA,PLUGIN_DATA,QODER_SESSION_ID) and emits host‑specific JSON or plain text containing the active ruleset.hooks/ponytail-mode-tracker.js– Persists the current mode to a.ponytail-activefile in the host‑specific state directory.hooks/ponytail-activate.js– Registers the/ponytail [lite|full|ultra|off]command and invokessetMode()to update state.hooks/ponytail-config.js– Abstracts configuration lookups from~/.config/ponytail/config.jsonor thePONYTAIL_DEFAULT_MODEenvironment variable.
Adapter Layer
The Adapter Layer provides thin wrappers that map host‑specific plugin formats to the shared core. Rather than duplicating logic, adapters merely point to the unified skills/ and hooks/ directories.
Supported adapters include:
- Claude Code –
hooks/claude-codex-hooks.jsonandplugin.json - Codex –
.codex-plugin/plugin.json - Gemini CLI –
gemini-extension.json - Qoder –
.qoder-plugin/plugin.jsonandhooks/qoder-hooks.json - Cursor, Windsurf, Cline – Various
.mdcrule files referencingAGENTS.md
How Runtime Hooks Inject Context into LLM Turns
The hooks/ponytail-runtime.js module serves as the engine that injects instructions on every LLM interaction. It reads the current mode via readMode(), loads the compact ruleset from AGENTS.md, and formats output based on the detected host.
// Simplified flow from hooks/ponytail-runtime.js
const mode = readMode(); // e.g., "full"
if (mode) {
const rules = fs.readFileSync(path.join(__dirname, '..', 'AGENTS.md'), 'utf8');
writeHookOutput(event, mode, rules);
}
When running under Codex, the hook outputs structured JSON:
{
"systemMessage": "PONYTAIL:FULL",
"hookSpecificOutput": { "...": "..." }
}
For Claude Code, it writes raw text to stdout. This host‑specific branching ensures the ruleset reaches the LLM context regardless of the client implementation.
Portable Skill System and the YAGNI Ladder
Skills are pure markdown declarations that enforce the platform‑native philosophy documented in docs/platform-native.md. The ladder prioritizes:
- YAGNI – Do not write code you do not need today.
- Standard Library – Use language builtins before external packages.
- Platform APIs – Leverage browser, Node.js, or database native features.
- One‑Liners – Implement tiny utilities inline rather than importing dependencies.
Adding a custom skill requires only a new directory and SKILL.md:
# skills/ponytail-debounce/SKILL.md
You are a lazy senior dev. Implement a debounce helper without any dependency.
```js
let t;
const debounce = (fn, ms) => (...a) => { clearTimeout(t); t = setTimeout(() => fn(...a), ms); };
## Configuration and State Management
Ponytail maintains minimal mutable state. The [`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-mode-tracker.js) module writes the active mode to `.ponytail-active` in the host's state directory (e.g., `~/.qoder` or `%APPDATA%/Copilot`). The `readMode()` function checks this file on every hook invocation to determine which intensity level to inject.
Configuration sources are resolved in this priority:
1. **Explicit command** – `/ponytail ultra` (sets immediately via `setMode()`)
2. **State file** – `.ponytail-active` (persisted across sessions)
3. **Environment variable** – `PONYTAIL_DEFAULT_MODE`
4. **Config file** – `~/.config/ponytail/config.json`
## Summary
- **Core Skills** reside in `skills/ponytail-*/SKILL.md` as declarative markdown prompts that encode the "lazy senior dev" ladder.
- **Runtime Hooks** in [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) detect the host environment and inject the appropriate ruleset on every LLM turn.
- **Adapters** are thin host‑specific manifests ([`plugin.json`](https://github.com/DietrichGebert/ponytail/blob/main/plugin.json), [`gemini-extension.json`](https://github.com/DietrichGebert/ponytail/blob/main/gemini-extension.json), etc.) that wire the shared core into Claude, Codex, Gemini, and other agents.
- **State** is persisted to `.ponytail-active` and supports four modes: `lite`, `full`, `ultra`, and `off`.
- **Configuration** can be set via environment variables or JSON files, abstracted by [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js).
## Frequently Asked Questions
### How does Ponytail detect which LLM host is running?
The [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js) module inspects environment variables to determine the host context. It checks for `COPILOT_PLUGIN_DATA` for GitHub Copilot, `PLUGIN_DATA` for Claude Code, and `QODER_SESSION_ID` for Qoder. Based on the detected host, it branches the output format to match the expected plugin protocol, ensuring the ruleset is injected correctly whether the agent expects JSON or plain text.
### What is the difference between the lite, full, and ultra modes?
These modes control the intensity of the "lazy senior dev" enforcement. **Lite** applies minimal constraints, suggesting std‑lib alternatives only for obvious cases. **Full** enforces the complete YAGNI ladder and blocks unnecessary dependencies. **Ultra** adds aggressive one‑liner enforcement and rejects any code that could be replaced with a platform‑native equivalent. The mode is stored in `.ponytail-active` and read by [`hooks/ponytail-mode-tracker.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-mode-tracker.js) on every invocation.
### How do I add a custom skill to Ponytail?
Create a new directory under `skills/` following the `ponytail-<name>` convention and add a [`SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/SKILL.md) file containing your prompt template and logic. The runtime loads these skills declaratively, so no JavaScript registration is required. For host‑specific packaging, ensure your adapter manifest includes the new skill directory in its file mapping, as demonstrated in the Claude and Codex plugin configurations.
### Where does Ponytail store configuration and state?
Ponytail stores the active mode in a file named `.ponytail-active` located in the host‑specific state directory (e.g., `~/.qoder` for Qoder or the Copilot plugin data folder on Windows). Global defaults can be set via the `PONYTAIL_DEFAULT_MODE` environment variable or in `~/.config/ponytail/config.json`, which is abstracted by the [`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js) helper module.
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 →