# How to Develop and Test Ponytail Rules: A Complete Guide

> Learn to develop and test Ponytail rules efficiently. Edit AGENTS.md, validate consistency with check-rule-copies.js, and run npm test for thorough verification. A complete guide for developers.

- Repository: [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
- Tags: how-to-guide
- Published: 2026-08-28

---

**To develop and test Ponytail rules, edit the canonical [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md) file, run `node scripts/check-rule-copies.js` to validate consistency across all host-specific copies, and execute `npm test` to verify rule injection and runtime behavior.**

Ponytail is an AI assistant framework by **DietrichGebert/ponytail** that implements a "lazy senior developer" mode through configurable rules. When you develop and test Ponytail rules, you are maintaining the behavioral guidelines that drive every turn of the AI's reasoning across multiple editor integrations including OpenCode, Cursor, Qoder, and Windsurf.

## Understanding the Ponytail Rule Architecture

The rule system relies on a strict single-source-of-truth pattern with automated synchronization checks. Three architectural layers ensure consistent behavior across all supported AI hosts.

### The Canonical Source (AGENTS.md)

All Ponytail rules originate in **[`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md)** at the repository root. This file contains the definitive prose that defines the lazy senior developer persona, coding standards, and safety constraints. When you need to modify any rule, this is the only file you edit directly. The canonical source enforces invariants such as "input validation at trust boundaries" and security-related phrasing that must never be removed.

### Host-Specific Rule Copies

Each AI host consumes rules through its own file format and location. The repository maintains synchronized copies in host-specific directories:

- [`.agents/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.agents/rules/ponytail.md)
- [`.qoder/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.qoder/rules/ponytail.md)
- `.cursor/rules/ponytail.mdc`
- [`.windsurf/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.windsurf/rules/ponytail.md)
- [`.clinerules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.clinerules/ponytail.md)
- [`.github/copilot-instructions.md`](https://github.com/DietrichGebert/ponytail/blob/main/.github/copilot-instructions.md)
- [`.kiro/steering/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.kiro/steering/ponytail.md)

These copies must remain byte-for-byte identical to the canonical source (excluding host-specific frontmatter). Drift between [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md) and any copy causes the validation script to fail, preventing inconsistent behavior across different AI assistants.

### The Injection Layer

The **OpenCode plugin** (`.opencode/plugins/ponytail.mjs`) dynamically injects rules into the system prompt on every turn. It imports `getPonytailInstructions(mode)` from [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js)—a shared instruction builder also used by the Pi extension and Qoder plugin. This guarantees that every host receives identical rule text regardless of how the underlying system consumes the instructions.

## How to Develop New Ponytail Rules

Follow this workflow to safely modify the rule set while maintaining consistency across all supported platforms.

1. **Edit [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md)** to add, remove, or rephrase rules using standard markdown bullet lists.

2. **Validate copy synchronization** by running the consistency checker:
   ```bash
   node scripts/check-rule-copies.js
   ```

   The script normalizes each copy (stripping frontmatter where appropriate) and compares against the canonical body.

3. **Fix any drift errors** if the script reports mismatches (e.g., `/.cursor/rules/ponytail.mdc drifted from AGENTS.md`).

4. **Add unit tests** under `tests/` if your rule influences runtime behavior or command processing.

5. **Run the full test suite** with `npm test` to verify rule injection and MCP integration.

6. **Commit and push**. The CI pipeline automatically runs the same validation script to block merges with inconsistent rule copies.

## How to Test Ponytail Rules

Testing occurs at two levels: static validation of rule copies and dynamic verification of injection behavior.

### Validating Rule Copy Consistency

The [`scripts/check-rule-copies.js`](https://github.com/DietrichGebert/ponytail/blob/main/scripts/check-rule-copies.js) script enforces that all host files match [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md). When successful, it outputs:

```text
Rule copies match AGENTS.md; 9 rule invariants present in SKILL.md and AGENTS.md.

```

The script specifically checks for safety-critical phrases to prevent accidental deletion of security or accessibility requirements. If validation fails, the script exits with a non-zero code and lists the offending file paths.

### Running the Full Test Suite

Execute the comprehensive test suite to verify that rules correctly influence AI behavior:

```bash
npm test

```

This command runs:
- Unit tests in `tests/*.test.js`
- Pi-extension tests (`npm test --prefix pi-extension`)
- MCP benchmark tests (`npm test --prefix ponytail-mcp`)

The suite validates that the `/ponytail` command persists modes correctly and that `experimental.chat.system.transform` appends the rule text to system prompts.

### Testing Rule Injection

Verify that the OpenCode plugin injects rules by checking the system prompt output. The plugin (`ponytail.mjs`) pushes instructions via:

```javascript
const instructions = getPonytailInstructions(mode);
output.system.push(instructions);

```

Monitor the system prompt in your host editor to confirm the full rule set appears on each turn.

## Code Examples

### Adding a New Rule to AGENTS.md

Edit the canonical file to append behavioral constraints:

```markdown

# Ponytail, lazy senior dev mode

…  

- **Never use `console.log` in production code** – logging should be gated behind a debug flag.
- **Validate all inputs at trust boundaries** – assume all external data is malicious until proven otherwise.

```

### Synchronizing Rule Copies

Run the validation script from the repository root:

```bash
node scripts/check-rule-copies.js

```

If copies match:

```text
Rule copies match AGENTS.md; 9 rule invariants present in SKILL.md and AGENTS.md.

```

If drift detected:

```text
/.cursor/rules/ponytail.mdc drifted from AGENTS.md

```

### Executing the Complete Test Suite

```bash
npm test

```

Expected output includes:

```text
> ponytail@4.9.0 test
> node --test tests/*.test.js && npm test --prefix pi-extension && npm test --prefix ponytail-mcp

✔ tests/behaviour.test.js
✔ tests/commands.test.js
…
All tests passed (123ms)

```

### Implementing Rule Injection in OpenCode

The plugin automatically appends rules each turn:

```javascript
// Inside .opencode/plugins/ponytail.mjs
import { getPonytailInstructions } from '../hooks/ponytail-instructions.js';

export default {
  name: 'ponytail',
  hooks: {
    'experimental.chat.system.transform': (output, context) => {
      const mode = context.config.get('mode') || 'lazy-senior-dev';
      const instructions = getPonytailInstructions(mode);
      output.system.push(instructions);
      return output;
    }
  }
};

```

## Summary

- **Single source of truth**: Always edit [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md); never modify host-specific copies directly.
- **Validation is mandatory**: Run `node scripts/check-rule-copies.js` after every rule change to ensure synchronization across `.cursor/rules/ponytail.mdc`, [`.qoder/rules/ponytail.md`](https://github.com/DietrichGebert/ponytail/blob/main/.qoder/rules/ponytail.md), and other host files.
- **Safety invariants**: The validation script checks for critical phrases regarding security and input validation to prevent accidental deletion.
- **Test coverage**: Execute `npm test` to verify both static consistency and dynamic injection behavior through the OpenCode plugin and MCP benchmarks.
- **Shared infrastructure**: The [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js) builder ensures identical rule text across OpenCode, Pi extensions, and Qoder adapters.

## Frequently Asked Questions

### What happens if I edit a host-specific rule file instead of AGENTS.md?

If you modify `.cursor/rules/ponytail.mdc` or any other copy directly, the [`check-rule-copies.js`](https://github.com/DietrichGebert/ponytail/blob/main/check-rule-copies.js) script will fail with a drift error. The CI pipeline blocks all merges where copies diverge from the canonical source. Always edit [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md) first, then run the validation script to confirm synchronization.

### How do I test that my new rule actually affects AI behavior?

Add a unit test under `tests/` that verifies the rule's impact on command processing or behavior selection. Run `npm test` to execute the full suite, which includes tests for the `/ponytail` command persistence and system-prompt transformation. You can also manually inspect the system prompt in your host editor to confirm the rule text appears.

### Why does Ponytail maintain separate copies for each AI host?

Different editors require specific file formats and locations. Cursor uses `.mdc` files with frontmatter, while Qoder and OpenCode use plain `.md` files. The [`scripts/check-rule-copies.js`](https://github.com/DietrichGebert/ponytail/blob/main/scripts/check-rule-copies.js) script normalizes these formats during comparison, ensuring the core rule content remains identical while accommodating host-specific metadata requirements.

### What are the "9 rule invariants" mentioned in the validation script?

The invariants are safety-critical phrases embedded in [`AGENTS.md`](https://github.com/DietrichGebert/ponytail/blob/main/AGENTS.md) that must never be removed, including references to "input validation at trust boundaries", "security", and "accessibility". The validation script scans every copy to verify these phrases remain present, preventing accidental weakening of safety constraints during routine rule updates.