How Ponytail Detects Different AI Agent Platforms: Environment Variables and Hook Loading

Ponytail detects the active AI agent platform by checking environment variables like COPILOT_PLUGIN_DATA, CODX_PLUGIN_DATA, and CLAUDE_PLUGIN_DATA, then loads platform-specific hook configurations to adapt its behavior accordingly.

The open-source project DietrichGebert/ponytail implements a lightweight runtime detection system that identifies whether it is running under GitHub Copilot, OpenAI Codex, Anthropic Claude, or a generic instruction-only environment. This detection mechanism allows Ponytail to dynamically adjust its operational modes and hook sets based on the specific capabilities and constraints of each AI agent platform.

Platform Detection via Environment Variables

Ponytail's detection logic centers on environment variables injected by each AI agent's plugin integration. When the runtime initializes in hooks/ponytail-runtime.js, it inspects process.env for platform-specific data directory pointers that indicate which agent is hosting the session.

GitHub Copilot Detection

When running under GitHub Copilot, the runtime checks for the COPILOT_PLUGIN_DATA environment variable. This variable contains a path to a temporary directory where Copilot stores session-specific state files.

// hooks/ponytail-runtime.js
if (env.COPILOT_PLUGIN_DATA) {
  return { name: 'copilot', dataDir: env.COPILOT_PLUGIN_DATA };
}

The existence of this variable triggers Copilot-specific behavior, including the loading of hooks/copilot-hooks.json and verification of marker files within the data directory.

OpenAI Codex Detection

For OpenAI Codex integration, Ponytail looks for the CODX_PLUGIN_DATA environment variable. This follows the same pattern as Copilot detection but directs the runtime to Codex-specific configuration files.

if (env.CODX_PLUGIN_DATA) {
  return { name: 'codex', dataDir: env.CODX_PLUGIN_DATA };
}

When detected, the runtime imports hook configurations appropriate for the Codex execution environment.

Anthropic Claude Detection

Anthropic Claude is identified through the CLAUDE_PLUGIN_DATA environment variable. The runtime treats this similarly to other platforms, using the provided data directory path to locate Claude-specific resources and configuration files.

if (env.CLAUDE_PLUGIN_DATA) {
  return { name: 'claude', dataDir: env.CLAUDE_PLUGIN_DATA };
}

Runtime Implementation in ponytail-runtime.js

The core detection logic resides in hooks/ponytail-runtime.js, which exports a detectPlatform() function that performs sequential checks against the environment. This function returns a platform descriptor object containing the platform name and data directory path, or falls back to a generic configuration.

// hooks/ponytail-runtime.js (simplified)
function detectPlatform() {
  const env = process.env;

  if (env.COPILOT_PLUGIN_DATA) {
    return { name: 'copilot', dataDir: env.COPILOT_PLUGIN_DATA };
  }
  if (env.CODX_PLUGIN_DATA) {
    return { name: 'codex', dataDir: env.CODX_PLUGIN_DATA };
  }
  if (env.CLAUDE_PLUGIN_DATA) {
    return { name: 'claude', dataDir: env.CLAUDE_PLUGIN_DATA };
  }
  // Fallback – use instruction files only
  return { name: 'generic', dataDir: null };
}

After detection, the runtime uses the returned platform name to import the appropriate hook set from the corresponding JSON configuration files.

Platform-Specific Hook Loading

Once Ponytail identifies the active platform, it dynamically loads hook configurations that define which capabilities and modes are available for that specific agent.

Hook Configuration Files

Each supported platform has a dedicated configuration file in the hooks/ directory:

The runtime imports these files based on the name property returned by detectPlatform(), ensuring that only compatible hooks are activated for the current environment.

Marker Files and Mode Detection

For platforms like Copilot, Ponytail performs additional validation by checking for marker files within the data directory. The runtime looks for .ponytail-active inside the COPILOT_PLUGIN_DATA directory to determine the current operational mode.

function getCopilotMode(copilotDir) {
  const modePath = require('path').join(copilotDir, '.ponytail-active');
  try {
    return require('fs').readFileSync(modePath, 'utf8').trim();
  } catch (_) {
    return 'full'; // default mode
  }
}

This file stores values like full or ultra, allowing the platform to persist session preferences across invocations.

Fallback Detection Strategy

When none of the platform-specific environment variables are defined, Ponytail enters a generic "instruction-only" mode. In this fallback state, the runtime relies on static instruction files rather than dynamic hook loading.

The fallback mechanism checks for:

  • AGENTS.md – A generic instruction file read when no platform-specific environment is detected
  • .github/copilot-instructions.md – Used by the Copilot CLI and other agents that provide instruction files without plugin data directories

This design ensures Ponytail remains functional even when running in simplified environments or local CLI contexts where full plugin integration is unavailable.

Summary

  • Environment variable inspection is the primary detection method, with COPILOT_PLUGIN_DATA, CODX_PLUGIN_DATA, and CLAUDE_PLUGIN_DATA serving as platform identifiers.
  • hooks/ponytail-runtime.js contains the detectPlatform() function that implements the sequential checking logic and returns platform-specific configurations.
  • Hook configuration files like hooks/copilot-hooks.json and hooks/claude-codex-hooks.json provide platform-specific behavior definitions that are loaded dynamically after detection.
  • Marker files such as .ponytail-active within data directories enable fine-grained mode detection for supported platforms.
  • Fallback handling through AGENTS.md and .github/copilot-instructions.md ensures compatibility with instruction-only agent environments.

Frequently Asked Questions

How does Ponytail distinguish between Copilot and Codex when both might be present?

Ponytail checks environment variables in a specific priority order within detectPlatform(). Whichever variable is present first determines the active platform. Since each AI agent platform sets only its own specific variable during execution, conflicts are rare. If multiple variables were somehow present, the first match in the conditional chain (Copilot, then Codex, then Claude) would take precedence.

What happens if none of the AI agent environment variables are set?

When COPILOT_PLUGIN_DATA, CODX_PLUGIN_DATA, and CLAUDE_PLUGIN_DATA are all undefined, detectPlatform() returns a generic configuration with name: 'generic' and dataDir: null. The runtime then falls back to reading static instruction files from AGENTS.md or .github/copilot-instructions.md, operating in a reduced functionality mode without dynamic hooks.

Can new AI agent platforms be added to Ponytail without modifying the core code?

Yes, the architecture supports extensibility by following the established pattern. New platforms need only provide a unique *_PLUGIN_DATA environment variable and a corresponding hooks JSON file (e.g., hooks/newagent-hooks.json). The detection logic in hooks/ponytail-runtime.js would need a new conditional check, and the plugin manifest at .github/plugin/plugin.json requires updating to register the new hook file.

Where does Ponytail store the detected platform mode for GitHub Copilot?

When running under GitHub Copilot, Ponytail reads the current mode from a file named .ponytail-active located in the directory specified by the COPILOT_PLUGIN_DATA environment variable. The getCopilotMode() function in the runtime constructs this path using path.join(copilotDir, '.ponytail-active') and returns the file contents, defaulting to 'full' if the file does not exist.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →