# System map — DietrichGebert/ponytail

> Canonical page: https://codevetter.com/unpack/ponytail/system-map

# System map — DietrichGebert/ponytail

Scanned commit e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156 (2026-09-14). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

There is no long-running application: ponytail is a distribution of instruction text plus small adapter shims that host agents invoke. The runtime core is five CommonJS scripts in hooks/ (config resolution, instruction building, host detection/output, activation, mode tracking, subagent injection) spawned by host lifecycle hooks. Per-host adapters (Claude/Codex plugin manifest + hooks JSON, Copilot hooks JSON, Cursor hooks installer, Gemini extension manifest, OpenCode .mjs plugin, pi extension, Hermes Python plugin, MCP stdio server, and instruction-only rule files) all funnel into the shared instruction builder. State is a single mode flag file plus an optional config.json in the user's home/config dirs. Tests are node:test files at tests/, plus nested suites in pi-extension/test and ponytail-mcp/test, driven by `npm test` and the test.yml GitHub Action.
- The npm package's only entrypoint is the OpenCode plugin module: package.json sets "main" and exports to ./.opencode/plugins/ponytail.mjs. — [package.json#L19-23](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/package.json#L19-L23)
- The runtime core is five shared CommonJS modules — ponytail-config.js (mode/config resolution), ponytail-instructions.js (ruleset builder), ponytail-runtime.js (host detection, state file, stdout protocol), ponytail-activate.js (SessionStart), ponytail-mode-tracker.js (UserPromptSubmit), ponytail-subagent.js (SubagentStart). — [hooks/ponytail-config.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-config.js) [hooks/ponytail-instructions.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-instructions.js) [hooks/ponytail-runtime.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js) [hooks/ponytail-activate.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-activate.js) [hooks/ponytail-mode-tracker.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-mode-tracker.js) [hooks/ponytail-subagent.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-subagent.js)
- Claude Code and Codex share one hook map, hooks/claude-codex-hooks.json, wiring SessionStart → ponytail-activate.js, SubagentStart → ponytail-subagent.js, and UserPromptSubmit → ponytail-mode-tracker.js, each run as `node "${CLAUDE_PLUGIN_ROOT}/hooks/…"` with a 5s timeout. — [hooks/claude-codex-hooks.json](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/claude-codex-hooks.json) [.claude-plugin/plugin.json#L9](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.claude-plugin/plugin.json#L9) [.codex-plugin/plugin.json#L14](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.codex-plugin/plugin.json#L14)
- Host detection is env-var based and order-sensitive: COPILOT_PLUGIN_DATA (or a CLAUDE_PLUGIN_ROOT under .vscode/agent-plugins) → Copilot, PLUGIN_DATA → Codex, QODER_SESSION_ID → Qoder, CURSOR_VERSION → Cursor, otherwise native Claude; each host picks a different stateDir and a different stdout JSON shape. — [hooks/ponytail-runtime.js#L13-39](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js#L13-L39) [hooks/ponytail-runtime.js#L80-131](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js#L80-L131)
- The single source of truth for the ruleset is skills/ponytail/SKILL.md; getPonytailInstructions() reads it and strips mode-keyed table rows/example bullets for the active level, falling back to an embedded condensed ruleset if the file is unreadable. — [hooks/ponytail-instructions.js#L9-41](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-instructions.js#L9-L41) [hooks/ponytail-instructions.js#L77-92](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-instructions.js#L77-L92) [skills/ponytail/SKILL.md](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/skills/ponytail/SKILL.md)
- Runtime state is a per-host flag file named .ponytail-active holding the mode string (e.g. ~/.claude/.ponytail-active, $PLUGIN_DATA/.ponytail-active, ~/.cursor/.ponytail-active, ~/.qoder/.ponytail-active); an absent flag means ponytail is off. — [hooks/ponytail-runtime.js#L6-57](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js#L6-L57)
- User configuration resolves in order: PONYTAIL_DEFAULT_MODE env var, then defaultMode in $XDG_CONFIG_HOME/ponytail/config.json (~/.config/ponytail or %APPDATA%\ponytail), then the built-in 'full'. — [hooks/ponytail-config.js#L54-100](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-config.js#L54-L100)
- The OpenCode adapter is a server plugin that registers slash commands from .opencode/command/*.md, adds skills/ to config.skills.paths, appends the ruleset via the experimental.chat.system.transform hook, and persists /ponytail switches in command.execute.before to ~/.config/opencode/.ponytail-active. — [.opencode/plugins/ponytail.mjs#L27-98](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.opencode/plugins/ponytail.mjs#L27-L98) [.opencode/plugins/ponytail-frontmatter.cjs](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.opencode/plugins/ponytail-frontmatter.cjs)
- The pi adapter (pi-extension/index.js) registers six slash commands, paints a status-bar indicator via ctx.ui.setStatus, persists session mode through pi.appendEntry('ponytail-mode'), and prepends the ruleset in the before_agent_start event. — [pi-extension/index.js#L63-210](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/pi-extension/index.js#L63-L210)
- The Hermes adapter is the root __init__.py Python plugin: register() exposes the six skills, hooks pre_llm_call for ruleset injection and pre_gateway_dispatch to rewrite authorized /ponytail-* gateway commands into agent prompts. — [__init__.py#L125-217](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/__init__.py#L125-L217) [plugin.yaml](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/plugin.yaml)
- ponytail-mcp is a private, internal-only MCP stdio server that serves the same ruleset as a 'ponytail' prompt and a 'ponytail_instructions' tool, reusing hooks/ponytail-instructions.js via createRequire. — [ponytail-mcp/index.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/ponytail-mcp/index.js) [ponytail-mcp/instructions.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/ponytail-mcp/instructions.js) [ponytail-mcp/package.json](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/ponytail-mcp/package.json)
- Instruction-only hosts get verbatim copies of the compact ruleset: .cursor/rules/ponytail.mdc, .windsurf/rules/ponytail.md, .clinerules/ponytail.md, .agents/rules/ponytail.md, .qoder/rules/ponytail.md, .github/copilot-instructions.md, .kiro/steering/ponytail.md — all byte-compared against AGENTS.md by scripts/check-rule-copies.js. — [scripts/check-rule-copies.js#L15-37](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/scripts/check-rule-copies.js#L15-L37) [docs/agent-portability.md](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/docs/agent-portability.md)
- Build/test: `npm test` runs `node --test tests/*.test.js` then the nested pi-extension and ponytail-mcp suites; CI (.github/workflows/test.yml) additionally runs check-rule-copies.js and check-versions.js on Node 22 / Python 3.12. Release is `npm publish` via publish.yml using OIDC trusted publishing, no token. — [package.json#L37-38](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/package.json#L37-L38) [.github/workflows/test.yml](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.github/workflows/test.yml) [.github/workflows/publish.yml](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.github/workflows/publish.yml)
- Deployment shape is per-host plugin manifests: .claude-plugin/, .codex-plugin/, .devin-plugin/, .github/plugin/ (Copilot), .qoder-plugin/, .grok-plugin/marketplace.json, .agents/plugins/marketplace.json, gemini-extension.json, plugin.yaml (Hermes), .openclaw/skills/ (ClawHub), and the pi package block in package.json. — [.claude-plugin/plugin.json](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.claude-plugin/plugin.json) [.codex-plugin/plugin.json](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.codex-plugin/plugin.json) [.devin-plugin/plugin.json](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.devin-plugin/plugin.json) [.github/plugin/plugin.json](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.github/plugin/plugin.json) [gemini-extension.json](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/gemini-extension.json) [plugin.yaml](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/plugin.yaml) [package.json#L40-43](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/package.json#L40-L43)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
