# How to Control Ponytail Injection into Subagents in OpenCode

> Learn how to control Ponytail injection into subagents in OpenCode. Discover how the global mode flag in .ponytail-active influences rule set appending to system prompts.

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

---

**Ponytail controls subagent injection through a global mode flag stored in `~/.config/opencode/.ponytail-active`, which the `experimental.chat.system.transform` hook reads to conditionally append rule sets to system prompts.**

The **DietrichGebert/ponytail** repository provides an OpenCode plugin that injects behavioral rules into AI conversations. Understanding how to **control Ponytail injection into subagents** requires knowing how the plugin uses a persistent state file and transform hooks to manage system prompt modifications across parent and child agents.

## Understanding the Core Injection Mechanism in ponytail.mjs

The injection logic resides in `.opencode/plugins/ponytail.mjs`. The plugin registers an `experimental.chat.system.transform` hook that intercepts every chat turn.

Inside this hook, the system calls `readMode()` to check the current Ponytail mode from disk. If the mode equals `'off'`, the hook returns early and performs no injection. Otherwise, it fetches instructions via `getPonytailInstructions(mode)` and appends them to the system prompt.

This design means **all agents in the same OpenCode session share the same injection state**, because they all read from the same file on every turn.

## The Global Mode State File

The mode persists in `$XDG_CONFIG_HOME/opencode/.ponytail-active` (falling back to `~/.config/opencode/.ponytail-active`). This file acts as a global switch for the entire OpenCode process.

When you execute the slash command `/ponytail <level>`, the `command.execute.before` hook writes the specified level to this file. Valid levels include intensity strings like `light`, `medium`, `hard`, or `off` to disable injection entirely. If you omit the level, `getDefaultMode()` provides the fallback value.

Because subagents spawn under the same OpenCode process, they automatically inherit this state. The transform hook reads the file on every turn, so **changes apply to the next turn but do not retroactively affect the current conversation turn**.

- **Mode = `off`**: No Ponytail rules are added to any subagent's system prompt.
- **Mode = `<level>`**: All subagents receive the same rule set for that level, appended to their system prompts on every turn.
- **Changing mode mid-session**: The new mode is written to the state file; the next turn (including subagents created afterward) uses the updated rules.

## Methods to Control Subagent Injection

You can precisely dictate Ponytail behavior for subagents using three approaches.

### Set Mode Before Spawning

Establish the desired intensity before creating the subagent:

```bash
/ponytail medium

# Subagent creation command follows

```

All subsequent agents, including subagents, receive the medium-intensity rule set.

### Disable Injection for Specific Subagents

To create a clean subagent without Ponytail rules:

```bash
/ponytail off

# Launch subagent here

```

The transform hook returns early when mode is `off`, leaving the subagent's system prompt unmodified.

### Temporary Mode Overrides

For one-off subagent execution with different rules:

```bash
opencode /ponytail off && \
opencode run subagent.js && \
opencode /ponytail medium

```

This pattern disables injection, runs the subagent, then restores your preferred intensity level.

## Programmatic Control Examples

You can automate mode switching within JavaScript or shell scripts when spawning subagents programmatically.

```javascript
// Toggle Ponytail for a specific subagent workflow
import { execSync } from 'child_process';

// Enable hard intensity
execSync('opencode /ponytail hard');

// Create subagent via OpenCode client API
await client.agent.create({ name: 'my-subagent' });

// Clean up for subsequent operations
execSync('opencode /ponytail off');

```

```bash

# Shell workflow with explicit cleanup

opencode /ponytail hard
opencode agent create --name "data-processor"
opencode /ponytail off  # Prevent leakage to next agent

```

## Key Source Files and Functions

The following files implement the injection control logic:

- **`.opencode/plugins/ponytail.mjs`**: Registers the `experimental.chat.system.transform` and `command.execute.before` hooks. Contains the `readMode()` logic and command parsing.
- **[`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js)**: Generates rule set text for each intensity level, imported via `../../hooks/ponytail-instructions`.
- **[`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js)**: Provides `getDefaultMode()` and `normalizePersistedMode()` utilities for mode validation and defaults.
- **Runtime state file**: `~/.config/opencode/.ponytail-active` stores the active mode between turns and across agent boundaries.

## Summary

- Ponytail uses a **global mode file** (`~/.config/opencode/.ponytail-active`) to control injection across all agents in an OpenCode session.
- The **`experimental.chat.system.transform` hook** in `ponytail.mjs` reads this file on every turn to determine whether to append rules.
- Use **`/ponytail off`** before spawning subagents to completely disable injection for that agent.
- Mode changes take effect on the **next turn** and do not retroactively modify existing conversation context.

## Frequently Asked Questions

### Can different subagents use different Ponytail intensity levels simultaneously?

No. Because the mode is stored in a single global file read by all agents in the OpenCode session, all active agents share the same intensity level. You must sequentially change modes between subagent spawn operations if you need different behaviors.

### Where is the Ponytail mode persisted between OpenCode sessions?

The mode persists in `$XDG_CONFIG_HOME/opencode/.ponytail-active`, or `~/.config/opencode/.ponytail-active` if the XDG variable is unset. This file survives until you explicitly change it or delete it.

### Does changing the Ponytail mode affect already running subagents?

Changes apply to the next chat turn, not the current one. Already running subagents will pick up the new mode on their subsequent turn, but the current turn's system prompt remains unchanged.

### How do I completely disable Ponytail injection for all future subagents?

Execute `/ponytail off` in your OpenCode session. This writes `off` to the state file, causing the `experimental.chat.system.transform` hook to return early for all future turns across all agents until you change the mode again.