How to Define Ponytail Commands for Different AI Hosts: Claude, Gemini, and OpenCode
Ponytail commands are defined through a dual-format adapter system where command metadata is registered once in pi-extension/index.js and then emitted as TOML files for Claude/Gemini and Markdown files for OpenCode.
The Ponytail repository (DietrichGebert/ponytail) implements a host-specific command catalog that adapts to the consumption requirements of multiple AI execution environments. Each supported host—Claude Code, Gemini CLI, and OpenCode—expects command metadata in distinct formats, necessitating a flexible definition strategy that maintains a single source of truth while generating compatible representations.
Host-Specific Command Formats
Ponytail uses different file formats depending on the target AI host. The repository maintains parallel definitions to ensure compatibility across Claude, Gemini, and OpenCode environments.
Claude and Gemini: TOML Definitions
Both Claude Code and Gemini CLI consume command definitions written in TOML format. These files reside in the commands/ directory and share identical structure between the two hosts.
In commands/ponytail.toml, the command metadata follows this pattern:
description = "Switch ponytail intensity level (lite/full/ultra/off)"
prompt = "Switch to ponytail {{args}} mode. If no level specified, use full. \
Lazy senior dev mode, before any code: does it need to exist at all (YAGNI)? \
Does the standard library do it? A native platform feature? Can it be one line? \
Build the minimum that works."
The {{args}} placeholder allows dynamic argument injection when the command executes. Every sub-command receives its own TOML file in this directory, ensuring granular control over each operation's prompt engineering and description.
OpenCode: Markdown Definitions
OpenCode requires a different approach, consuming command definitions as Markdown files located in the hidden .opencode/command/ directory. These files wrap the same metadata in a host-specific structure.
The file .opencode/command/ponytail.md demonstrates the OpenCode format:
# ponytail
Switch ponytail intensity level (lite/full/ultra/off).
> **Prompt**
> Switch to ponytail {{args}} mode. If no level specified, use full.
While the semantic content mirrors the TOML version, the Markdown format uses header-based titles and blockquote sections to satisfy OpenCode's parsing expectations.
The Registration and Adapter Generation Pipeline
The canonical definitions for all Ponytail commands originate in pi-extension/index.js, where the π-extension registers each command using the registerCommand function.
// pi-extension/index.js (excerpt)
registerCommand('ponytail', {
description: 'Switch ponytail intensity level',
prompt: 'Switch to ponytail {{args}} mode. If no level specified, use full.'
});
When the registration system executes, it triggers an adapter generation process that emits two representations for every registered command name:
- A TOML file under
commands/<name>.tomlfor Claude and Gemini consumption - A Markdown file under
.opencode/command/<name>.mdfor OpenCode integration
This pipeline ensures that the source code remains the single source of truth while automatically producing the host-specific artifacts required by each execution environment.
Validating Command Definitions Across Hosts
The repository enforces consistency through automated testing in tests/commands.test.js. This test suite verifies that every registered command maintains parity across host formats.
Specifically, the tests validate that:
- Each command registered via
registerCommand()has a correspondingcommands/<name>.tomlfile - Each registered command also has a matching
.opencode/command/<name>.mdfile - No orphaned definition files exist without matching registration entries
This strict validation prevents drift between the TOML and Markdown representations, ensuring that Claude, Gemini, and OpenCode users all interact with identical command functionality despite the different file formats.
Complete Command Definition Examples
TOML Structure for Claude/Gemini
When defining commands for Claude Code or Gemini CLI, include the description and prompt fields in the TOML format:
# commands/ponytail.toml
description = "Switch ponytail intensity level (lite/full/ultra/off)"
prompt = "Switch to ponytail {{args}} mode. If no level specified, use full. \
Lazy senior dev mode, before any code: does it need to exist at all (YAGNI)? \
Does the standard library do it? A native platform feature? Can it be one line? \
Build the minimum that works."
Markdown Structure for OpenCode
For OpenCode hosts, structure the definition with a level-1 header and prompt blockquote:
<!-- .opencode/command/ponytail.md -->
# ponytail
Switch ponytail intensity level (lite/full/ultra/off).
> **Prompt**
> Switch to ponytail {{args}} mode. If no level specified, use full.
Registration in the π-Extension
All definitions begin with JavaScript registration in the extension entry point:
// pi-extension/index.js
registerCommand('ponytail', {
description: 'Switch ponytail intensity level',
prompt: 'Switch to ponytail {{args}} mode. If no level specified, use full.'
});
Summary
- Claude and Gemini consume TOML files located in
commands/, sharing identical format specifications. - OpenCode requires Markdown files placed in
.opencode/command/with specific header and blockquote conventions. - The
registerCommand()function inpi-extension/index.jsserves as the single source of truth for all command metadata. - An automated adapter generation process creates both TOML and Markdown representations from the canonical registration.
tests/commands.test.jsenforces format parity, ensuring every registered command exists in both host-specific formats.
Frequently Asked Questions
What file format does Claude use for Ponytail commands?
Claude Code consumes TOML files (.toml extension) stored in the commands/ directory. These files contain description and prompt fields that define the command's behavior and user-facing explanation.
How does OpenCode differ from Claude in command definitions?
OpenCode uses Markdown files (.md extension) placed in the .opencode/command/ hidden directory instead of TOML. While the semantic content remains identical, OpenCode expects the command name as a level-1 header and the prompt wrapped in a blockquote section with a "Prompt" label.
Where is the source of truth for Ponytail commands?
The π-extension (pi-extension/index.js) serves as the source of truth, where each command is registered via registerCommand(name, metadata). This registration drives the generation of both TOML and Markdown adapter files, ensuring consistency across all supported hosts.
How does Ponytail ensure consistency across host formats?
The repository uses tests/commands.test.js to enforce a strict contract: every command registered in the π-extension must have both a commands/<name>.toml file for Claude/Gemini and a .opencode/command/<name>.md file for OpenCode. Tests fail if either representation is missing or if definition files exist without corresponding registrations.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →