# How ponytail-activate.js Initializes Ponytail on Session Start: Inside the Claude Hook Lifecycle

> Learn how ponytail-activate.js initializes Ponytail on session start. Discover how it configures the target mode, persists activation flags, and injects instructions into the SessionStart context.

- Repository: [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
- Tags: internals
- Published: 2026-08-27

---

**The [`ponytail-activate.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-activate.js) hook initializes Ponytail by determining the target mode from configuration, persisting an activation flag to the Claude config directory, and injecting mode-specific instructions into the invisible SessionStart context.**

The [`ponytail-activate.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-activate.js) script serves as the automatic entry point for the Ponytail system in Claude Code sessions. Located in the `DietrichGebert/ponytail` repository, this SessionStart hook ensures that every new Claude session begins with the appropriate behavioral ruleset active, eliminating the need for manual configuration on each launch.

## The Three-Phase Initialization Process

When a Claude Code session begins, [`ponytail-activate.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-activate.js) executes automatically and proceeds through three distinct logical phases to bootstrap the system.

### Phase 1: Determining the Target Mode

The hook first resolves which operational mode should govern the session. It calls `getDefaultMode` from the configuration layer to retrieve the user’s preferred setting.

If the returned mode is `"off"`, the hook performs an early exit sequence. It clears any previously stored mode state, writes a minimal "off" output, and terminates immediately. This ensures Ponytail remains dormant when explicitly disabled, preventing any interference with standard Claude behavior.

```javascript
// Simplified logic from lines 24-31
const mode = getDefaultMode();
if (mode === 'off') {
  clearMode();  // Remove any existing activation
  writeHookOutput('SessionStart', 'off', '');
  return;
}

```

### Phase 2: Activating the Mode

For active modes (`lite`, `full`, `ultra`, etc.), the hook proceeds to establish the runtime environment. It calls `setMode(mode)`, which writes a flag file named `.ponytail-active` to the Claude configuration directory (`$CLAUDE_CONFIG_DIR`).

Simultaneously, the hook generates the behavioral instructions specific to the selected intensity level by invoking `getPonytailInstructions(mode)` at line 42. These instructions constitute the hidden SessionStart context that Claude uses to constrain agent behavior for every subsequent turn in the conversation.

```javascript
// Core activation sequence (line 36, 42)
setMode(mode);  // Creates $CLAUDE_CONFIG_DIR/.ponytail-active
const instructions = getPonytailInstructions(mode);

```

### Phase 3: Optional Status-Line Nudging

For non-Copilot/Codex sessions, the hook performs an optional user experience enhancement between lines 47 and 85. It inspects the user’s [`settings.json`](https://github.com/DietrichGebert/ponytail/blob/main/settings.json) to detect whether a status-line configuration already exists.

If no status-line is configured and the user has not previously declined this suggestion (tracked via the `.ponytail-statusline-nudged` flag file), the hook creates the tracker file and appends a setup message to the output. This message includes a ready-to-copy snippet that adds a `statusLine` command pointing to either [`ponytail-statusline.sh`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-statusline.sh) or `ponytail-statusline.ps1` depending on the platform. If the installation path contains unsafe shell characters that could break command substitution, the hook emits a fallback message with manual instructions instead.

## Core Implementation Details

### Flag File Management

The activation state persists across sessions through a filesystem marker. The `setMode` function (provided by [`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js)) creates `.ponytail-active` in `$CLAUDE_CONFIG_DIR`, while `clearMode` removes it during deactivation or when the mode is set to `"off"`. This flag serves as the source of truth for other Ponytail components that need to verify whether the system is active between sessions.

### Instruction Injection

The final operation at line 93 sends the assembled payload back to Claude:

```javascript
writeHookOutput('SessionStart', mode, output);

```

This output remains invisible to the user but drives Ponytail’s behavior for the entire session. The `output` variable contains either the pure JSON instructions (for standard activation) or the instructions concatenated with the status-line setup hint (when nudging occurs).

## Code Architecture and Dependencies

The activation hook relies on a modular architecture split across three supporting files:

- **[`hooks/ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-config.js)** – Resolves configuration values, determines the Claude directory path, and performs safety checks on file locations.
- **[`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js)** – Provides the runtime helpers `setMode`, `clearMode`, and `writeHookOutput` that abstract filesystem and hook protocol operations.
- **[`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js)** – Generates the JSON-based instruction sets filtered by intensity level (lite, full, ultra), ensuring the agent receives only the rules relevant to the selected mode.

## Practical Usage Examples

### Automatic Session Initialization

Under normal operation, users do not invoke the hook manually. The script runs automatically when Claude starts a new session:

```javascript
// No manual intervention required
// The hook executes automatically on SessionStart, writes .ponytail-active,
// and injects the appropriate ruleset into the context window

```

### Programmatic Testing

For integration testing or development purposes, you can simulate the activation flow programmatically:

```javascript
const { getDefaultMode, setMode, writeHookOutput } = require('./hooks/ponytail-runtime');
const { getPonytailInstructions } = require('./hooks/ponytail-instructions');

function activatePonytailForTest(mode = 'full') {
  setMode(mode);                                      // writes .ponytail-active
  const instructions = getPonytailInstructions(mode);
  writeHookOutput('SessionStart', mode, instructions);
}

activatePonytailForTest(); // Defaults to the configured mode

```

## Summary

- **Three-phase initialization**: [`ponytail-activate.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-activate.js) determines the target mode via `getDefaultMode`, persists state through `setMode` writing to `$CLAUDE_CONFIG_DIR/.ponytail-active`, and generates instructions via `getPonytailInstructions`.
- **Early exit handling**: When the mode is `"off"`, the hook clears stored state and exits without writing activation flags or instructions.
- **Optional UX nudging**: The hook inspects [`settings.json`](https://github.com/DietrichGebert/ponytail/blob/main/settings.json) and creates `.ponytail-statusline-nudged` to offer one-time status-line setup assistance.
- **Final delivery**: `writeHookOutput` at line 93 transmits the invisible SessionStart payload that constrains agent behavior for the session duration.
- **Modular dependencies**: The script delegates configuration, runtime operations, and instruction generation to [`ponytail-config.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-config.js), [`ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-runtime.js), and [`ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-instructions.js) respectively.

## Frequently Asked Questions

### What triggers ponytail-activate.js to execute?

The script runs automatically as a SessionStart hook whenever Claude Code initializes a new conversation session. It does not require manual invocation; the Claude agent executes it based on the hook configuration, making it the effective entry point for all Ponytail functionality.

### Where does Ponytail store its activation state between sessions?

The system persists activation state in a flag file named `.ponytail-active` located in the Claude configuration directory (`$CLAUDE_CONFIG_DIR`). The `setMode` function creates this file during activation, while `clearMode` removes it when deactivating or when the user sets the mode to `"off"`.

### How does the script handle disabled or "off" configurations?

When `getDefaultMode` returns `"off"`, the hook immediately calls `clearMode` to remove any existing activation flag, writes a minimal empty output via `writeHookOutput`, and exits early without generating instructions. This ensures Ponytail imposes zero overhead or behavioral changes when disabled.

### What is the purpose of the status-line nudging feature?

The status-line nudging inspects the user’s [`settings.json`](https://github.com/DietrichGebert/ponytail/blob/main/settings.json) during activation to detect missing status-line configurations. If absent and the user hasn't been previously notified (tracked by `.ponytail-statusline-nudged`), the hook provides a one-time message containing copy-paste ready commands to enable visual Ponytail status indicators in the Claude interface.