# Contributor handoff — DietrichGebert/ponytail

> Canonical page: https://codevetter.com/unpack/ponytail/agent-handoff

# Contributor handoff — DietrichGebert/ponytail

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

This repo edits its own dogma: AGENTS.md demands the smallest correct diff and `ponytail:` comments marking deliberate ceilings — match that style. The golden rules: SKILL.md and AGENTS.md are the sources of truth and every copy must stay in sync (CI enforces it); all shared logic lives in the CJS hooks/ modules so adapters stay thin; hooks must never hang or crash a session (fail-open, BOM-strip, timeouts); and any version bump touches 8 files. Always run `npm test` plus the two check scripts before claiming done.
- Read first, in order: AGENTS.md (the ruleset and the repo's own working style), skills/ponytail/SKILL.md (canonical long-form rules), hooks/ponytail-runtime.js + ponytail-config.js + ponytail-instructions.js (the shared core every adapter calls), then docs/agent-portability.md for the host→file map. — [AGENTS.md](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/AGENTS.md) [skills/ponytail/SKILL.md](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/skills/ponytail/SKILL.md) [hooks/ponytail-runtime.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js) [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) [docs/agent-portability.md](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/docs/agent-portability.md)
- After editing AGENTS.md or any rule copy (.cursor/rules/ponytail.mdc, .windsurf, .clinerules, .agents, .qoder, .github/copilot-instructions.md, .kiro), run `node scripts/check-rule-copies.js` — it fails CI on drift; after touching SKILL.md verify the 9 INVARIANTS phrases still appear verbatim. — [scripts/check-rule-copies.js#L19-76](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/scripts/check-rule-copies.js#L19-L76)
- Version bumps touch 8 files: .claude-plugin/plugin.json, .codex-plugin/plugin.json, .devin-plugin/plugin.json, .github/plugin/plugin.json, .qoder-plugin/plugin.json, gemini-extension.json, package.json, ponytail-mcp/package.json — run `node scripts/check-versions.js` to verify they agree. — [scripts/check-versions.js#L21-30](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/scripts/check-versions.js#L21-L30)
- Test command: `npm test` (root node:test suite + pi-extension + ponytail-mcp); the MCP suite needs `npm install --prefix ponytail-mcp` first (only directory with real deps: @modelcontextprotocol/sdk + zod). — [package.json#L37-38](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/package.json#L37-L38) [ponytail-mcp/package.json#L9-12](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/ponytail-mcp/package.json#L9-L12) [.github/workflows/test.yml#L26-27](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.github/workflows/test.yml#L26-L27)
- Hook contract traps: strip UTF-8 BOM before JSON.parse everywhere; never block on stdin without the 1s unref'd timeout + error handler (Windows swallows piped input, #443); native Claude SubagentStart requires hookSpecificOutput JSON not raw stdout; Cursor treats empty stdout as no-op and raw text as a parse error. — [hooks/ponytail-mode-tracker.js#L147-155](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-mode-tracker.js#L147-L155) [hooks/ponytail-runtime.js#L111-131](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js#L111-L131) [tests/cursor-hooks.test.js#L1-10](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/tests/cursor-hooks.test.js#L1-L10)
- Mode semantics: 'review' is session-only and must never be a default (#377) — validate against RUNTIME_MODES for defaults and VALID_MODES for persisted values; isDeactivationCommand only fires on the whole-message phrase, not substring matches. — [hooks/ponytail-config.js#L16-43](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-config.js#L16-L43) [tests/hooks.test.js#L466-475](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/tests/hooks.test.js#L466-L475)
- Safe edit boundaries: per-host manifests and hook JSONs are isolated (edit one without touching others); the shared hooks/ modules and skills/ are high blast-radius — a bug there affects every host. Anything in .openclaw/skills/ is generated — edit skills/ and rerun scripts/build-openclaw-skills.js instead. — [scripts/build-openclaw-skills.js#L1-12](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/scripts/build-openclaw-skills.js#L1-L12) [docs/agent-portability.md#L35-39](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/docs/agent-portability.md#L35-L39)
- House style: CommonJS in hooks/ and scripts/ (ESM only where the host requires it — ponytail.mjs and pi-extension/index.js bridge via createRequire), no dependencies outside ponytail-mcp, `ponytail:` comments mark deliberate simplifications with a named ceiling and upgrade path, and non-trivial logic leaves one runnable check behind. — [hooks/ponytail-runtime.js#L1-4](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js#L1-L4) [.opencode/plugins/ponytail.mjs#L12-24](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/.opencode/plugins/ponytail.mjs#L12-L24) [ponytail-mcp/package.json#L9-12](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/ponytail-mcp/package.json#L9-L12) [AGENTS.md](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/AGENTS.md)
- Issue-number archaeology matters: comments cite GitHub issues (#34 CLAUDE_CONFIG_DIR, #252 subagents, #377 review default, #443 Windows stdin, #483 nudge-once, #506 matcher, #528 VS Code Copilot, #573 Codex JSON shape, #817 Cursor) — when changing that code, re-check the referenced constraint or a regression test will catch it. — [hooks/ponytail-runtime.js#L8-29](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-runtime.js#L8-L29) [hooks/ponytail-config.js#L79-83](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-config.js#L79-L83) [hooks/ponytail-mode-tracker.js#L147-149](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-mode-tracker.js#L147-L149) [tests/hooks.test.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/tests/hooks.test.js)
- Windows is a first-class target: tests set both HOME and USERPROFILE, paths go through os.homedir(), cursor-hooks.js normalizes to forward slashes, the statusline has a .ps1 twin, and hooks-windows.test.js covers platform edges — don't introduce POSIX-only assumptions. — [tests/hooks.test.js#L53-59](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/tests/hooks.test.js#L53-L59) [scripts/cursor-hooks.js#L53-58](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/scripts/cursor-hooks.js#L53-L58) [hooks/ponytail-statusline.ps1](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/hooks/ponytail-statusline.ps1) [tests/hooks-windows.test.js](https://github.com/DietrichGebert/ponytail/blob/e3ba2aa6f1e6f0bc4d69eb09c9f0d0a93af56156/tests/hooks-windows.test.js)

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)
