What Is the Purpose of the Hooks Directory in Ponytail?
The hooks directory contains runtime-only scripts that integrate Ponytail with Claude-based IDEs and shell status lines, handling automatic activation, instruction emission, and mode-aware badge display.
The hooks directory in the DietrichGebert/ponytail repository serves as the execution bridge between Ponytail's configuration logic and external development environments. Located at the repository root, this directory contains JavaScript and shell scripts that initialize the plugin on Claude session start, persist mode state across commands, and render visual feedback in the terminal prompt.
Runtime Integration Architecture
The hooks act as the activation layer that connects Ponytail to Claude Code, Copilot, and other Claude-based IDEs without requiring manual configuration file edits. When a Claude session initializes, the integration files qoder-hooks.json and copilot-hooks.json declare which scripts to run, triggering the activation flow automatically.
Session Activation and Flag Management
When a Claude session starts, ponytail-activate.js executes automatically. This script performs three critical tasks:
- Resolves the default mode (lite, full, ultra, or off) via
getDefaultMode()fromponytail-config.js - Writes a flag file to
$CLAUDE_CONFIG_DIR/.ponytail-activeviasetMode()(implemented inponytail-runtime.js) - Emits the Ponytail instruction set using functions from
ponytail-instructions.js
Instruction Emission to Claude
The activation hook calls getPonytailInstructions(mode) to generate the "ruleset" that drives Ponytail's lazy-senior-dev behavior. These instructions are sent back to the IDE via writeHookOutput(), ensuring Claude receives the configuration immediately upon session start.
Shell Status Line Integration
The directory provides ponytail-statusline.sh (Unix) and ponytail-statusline.ps1 (PowerShell) to read the flag file and print colored badges like [PONYTAIL] or [PONYTAIL:ULTRA] using ANSI color codes (108 for green default, 173 for amber in ultra mode).
Key Files in the Hooks Directory
| File | Responsibility |
|---|---|
ponytail-activate.js |
Entry point executed on every Claude session start; orchestrates activation by writing the flag file and emitting instructions |
ponytail-config.js |
Resolves default modes and provides utility functions like isShellSafe() and getClaudeDir() |
ponytail-runtime.js |
Manages runtime state with setMode(), clearMode(), and writeHookOutput() |
ponytail-instructions.js |
Generates the instruction text sent to Claude based on current mode |
ponytail-statusline.sh |
Bash script rendering the status badge for Unix shells |
ponytail-statusline.ps1 |
PowerShell script for Windows terminal integration |
qoder-hooks.json |
Declares hook scripts for Claude Code integration |
copilot-hooks.json |
Declares hook scripts for Copilot integration |
Activation Hook Implementation
The ponytail-activate.js file runs automatically when Claude initializes. It checks if Ponytail is disabled (mode === 'off'), sets the active flag, and emits instructions:
#!/usr/bin/env node
// ponytail‑activate.js – runs on every Claude session start
const { getDefaultMode, getClaudeDir, isShellSafe } = require('./ponytail-config');
const { getPonytailInstructions } = require('./ponytail-instructions');
const { setMode, writeHookOutput } = require('./ponytail-runtime');
const mode = getDefaultMode(); // Resolve mode (env → config → 'full')
if (mode === 'off') { // Disable Ponytail entirely
writeHookOutput('SessionStart', 'off', 'OK');
process.exit(0);
}
setMode(mode); // Write `$CLAUDE_CONFIG_DIR/.ponytail-active`
const instructions = getPonytailInstructions(mode);
writeHookOutput('SessionStart', mode, instructions);
This script ensures the .ponytail-active flag file exists and contains the current mode, enabling cross-session persistence for the status line scripts.
Status Line Badge Generation
The shell scripts read the flag file created by the activation hook to display the current mode. For Unix systems, ponytail-statusline.sh implements the logic:
#!/usr/bin/env bash
flag="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/.ponytail-active"
[ -f "$flag" ] || exit 0 # No flag → no badge
mode=$(head -n1 "$flag" | tr -d '[:space:]')
color=108 # default green
[ "$mode" = "ultra" ] && color=173 # amber for ultra mode
if [ -z "$mode" ] || [ "$mode" = "full" ]; then
printf '\033[38;5;%sm[PONYTAIL]\033[0m' "$color"
else
printf '\033[38;5;%sm[PONYTAIL:%s]\033[0m' "$color" "$(printf '%s' "$mode" | tr '[:lower:]' '[:upper:]')"
fi
The PowerShell equivalent (ponytail-statusline.ps1) provides identical functionality for Windows environments, reading the same flag file to determine which colored badge to display.
Automatic Setup Detection
When ponytail-activate.js detects missing status-line configuration in Claude's settings.json, it emits a one-time setup nudge:
STATUSLINE SETUP NEEDED: The ponytail plugin includes a statusline badge showing active mode.
To enable, add this to /home/you/.claude/settings.json:
"statusLine": { "type": "command", "command": "bash \"/path/to/ponytail/hooks/ponytail-statusline.sh\"" }
This guides users to integrate the badge into their terminal prompt without requiring manual documentation review.
Summary
- The hooks directory provides the runtime layer that activates Ponytail automatically when Claude sessions start, eliminating the need for manual initialization.
ponytail-activate.jswrites the.ponytail-activeflag file and emits instruction sets to the IDE viawriteHookOutput().- Status line scripts (
ponytail-statusline.shand.ps1) read the flag file to display colored mode badges (lite, full, ultra) in the terminal prompt. - Configuration utilities (
ponytail-config.js,ponytail-runtime.js) handle mode resolution and state persistence across commands using the Claude configuration directory. - JSON descriptors (
qoder-hooks.json,copilot-hooks.json) declare which scripts each IDE integration should execute on session start.
Frequently Asked Questions
What triggers the scripts in the hooks directory?
The activation hook (ponytail-activate.js) runs automatically when Claude Code or Copilot initializes a session, triggered by the hook declarations in qoder-hooks.json or copilot-hooks.json. This initialization happens before the user issues any commands, ensuring Ponytail is active from the start of the session.
How does Ponytail remember which mode is active across different commands?
The setMode() function in ponytail-runtime.js writes the current mode (lite, full, or ultra) to a flag file located at $CLAUDE_CONFIG_DIR/.ponytail-active. Subsequent commands and status-line scripts read this file to determine the active state, providing persistence across the entire Claude session.
Can I disable Ponytail without uninstalling it?
Yes. If getDefaultMode() in ponytail-config.js returns 'off', the activation hook immediately exits after writing an "off" status, skipping instruction emission and flag creation. This effectively disables Ponytail for that session without modifying the installation files.
Why does the status line show different colors?
The bash script (ponytail-statusline.sh) uses ANSI color code 108 (green) by default, but switches to color 173 (amber/orange) when the mode is set to ultra. This provides immediate visual feedback about the current behavior level directly in the terminal prompt.
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 →