# How Pi and OMP Extensions Differ from Standard Plugin Manifests in i-have-adhd

> Discover how i-have-adhd Pi and OMP extensions use executable TypeScript modules for runtime commands, differing from static JSON plugin manifests. Learn the key distinctions.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: deep-dive
- Published: 2026-08-29

---

**Pi and OMP extensions are executable TypeScript modules that register runtime commands and session hooks, while standard plugin manifests are static JSON files containing only metadata with no executable logic.**

The *i-have-adhd* repository by ayghri demonstrates a hybrid plugin architecture that supports multiple AI coding runtimes. Understanding how **Pi and OMP extensions** contrast with standard plugin manifests is essential for developers targeting the Pi coding-agent framework or Open-Model-Plugin (OMP) runtime versus traditional hosts like Codex or Claude. The fundamental distinction lies in executable behavior versus declarative configuration.

## What Are Pi and OMP Extensions?

### Runtime-Level TypeScript Modules

**Pi and OMP extensions** provide runtime-level JavaScript/TypeScript code that actively registers commands, flags, and event handlers for the active session. In [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json), these are declared under custom keys `pi` and `omp` pointing to TypeScript files:

```json
{
  "name": "i-have-adhd",
  "pi": {
    "extensions": ["./extensions/i-have-adhd.ts"],
    "skills": ["./skills"]
  },
  "omp": {
    "extensions": ["./extensions/i-have-adhd.ts"]
  }
}

```

The Pi or OMP runtime reads these entries, loads the referenced `.ts` file from the `extensions/` directory, and executes its default export to hook into the session lifecycle.

### Session Lifecycle Hooks

The extension file [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) exports a default function receiving an `ExtensionAPI` instance. This API exposes methods like `registerFlag()`, `registerCommand()`, and `on()` for event handling:

```typescript
import { getAgentDir, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";

export default function iHaveAdhdExtension(pi: ExtensionAPI) {
  // Register a runtime flag (Pi only)
  pi.registerFlag("adhd", {
    description: "Start with ADHD-friendly output enabled",
    type: "boolean",
    default: false,
  });

  // Register a slash command that toggles the mode
  pi.registerCommand("i-have-adhd", {
    description: "Toggle ADHD-friendly output for this session",
    handler: async (args, ctx) => { /* implementation */ },
  });

  // Hook into session events
  pi.on("input", async (event, ctx) => { /* handle input */ });
  pi.on("session_start", async (_event, ctx) => restoreState(ctx));
}

```

According to the source code, these hooks allow the extension to directly manipulate conversations, inject rule messages, and react to user input in real-time.

## What Are Standard Plugin Manifests?

### Static JSON Configuration Files

**Standard plugin manifests** describe metadata that the host uses to load the plugin but contain no executable logic. These are plain-JSON files located at specific paths like [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json) or [`.claude-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.claude-plugin/plugin.json). Unlike the Pi/OMP extensions declared in [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json), these manifests require no special keys in the package manifest.

### Declarative Metadata Fields

Standard manifests contain static fields such as `name`, `description`, `interface`, `skills`, and `composerIcon`. For example, [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json) in the i-have-adhd repository contains:

```json
{
  "name": "i-have-adhd",
  "version": "0.2.0",
  "description": "Action-first output for ADHD readers",
  "skills": "./skills/",
  "interface": {
    "displayName": "I Have ADHD",
    "shortDescription": "Action-first output for ADHD readers",
    "defaultPrompt": [
      "Use i-have-adhd for this task.",
      "Make this answer action-first and easy to execute."
    ],
    "composerIcon": "./logo.png"
  }
}

```

The host parses this JSON to register UI information and skill paths, interpreting the fields uniformly without executing any code at load time.

## Key Differences Between Executable Extensions and Static Manifests

### Loading Mechanisms

**Pi and OMP extensions** use a dynamic loading mechanism where the runtime executes the TypeScript module's default export function. The runtime passes an `ExtensionContext` and `ExtensionAPI` object, allowing immediate registration of capabilities.

**Standard manifests** use static parsing. The host reads the JSON file to understand plugin capabilities, presentation details, and skill locations, but never invokes executable logic during this process.

### Runtime-Specific Features

- **Pi extensions** can register **flags** via `pi.registerFlag()` and **commands** via `pi.registerCommand()` interpreted specifically by the Pi coding-agent framework.
- **OMP extensions** use the same extension file structure but are loaded by the OMP loader, which expects the `omp.extensions` entry in [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json).
- **Standard manifests** expose common fields like `interface.capabilities` and `defaultPrompt` that work across all supported runtimes without runtime-specific API exposure.

### Scope of Effect

Executable extensions directly manipulate the conversation state, update UI status, and manage session lifecycle events through the `ExtensionAPI`. They operate at runtime during active sessions.

Standard manifests operate declaratively, influencing only how the host presents the plugin (name, icon, description) and where it locates skill documents. They define *what* the plugin is, while extensions define *how* it behaves.

## Implementation Details in the i-have-adhd Source

The repository structure reinforces this architectural separation. The [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) file implements the executable logic used by both Pi and OMP runtimes, while runtime-specific directories contain static manifests:

| File | Purpose | Type |
|------|---------|------|
| [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) | Implements flags, commands, and session hooks | TypeScript module |
| [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json) | Declares `pi.extensions` and `omp.extensions` | Package manifest |
| [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json) | Static metadata for Codex runtime | JSON manifest |
| [`.claude-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.claude-plugin/plugin.json) | Static metadata for Claude runtime | JSON manifest |

This design allows the i-have-adhd plugin to maintain a single source of truth for executable behavior while adapting its metadata presentation for different host environments.

## Summary

- **Pi and OMP extensions** are executable TypeScript modules that implement session-level behavior through the `ExtensionAPI`.
- **Standard plugin manifests** are static JSON descriptors that provide metadata without executable logic.
- The Pi runtime loads extensions by executing the default export from files listed in [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json) under the `pi` key.
- Standard manifests in [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json) or [`.claude-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.claude-plugin/plugin.json) contain fields like `interface` and `skills` but no code.
- Extensions manipulate runtime behavior directly, while manifests only influence how the host presents and loads the plugin.

## Frequently Asked Questions

### What is the primary purpose of the extensions/i-have-adhd.ts file?

The file serves as the runtime entry point for Pi and OMP loaders. It exports a default function that receives an `ExtensionAPI` object, allowing the plugin to register flags, slash commands, and event listeners that manipulate the coding session in real-time. This is where the plugin implements its ADHD-friendly output logic through active runtime hooks.

### How does the Pi runtime discover and load extensions?

The Pi runtime reads the `pi.extensions` array in [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json), resolves the TypeScript file paths (such as [`./extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/./extensions/i-have-adhd.ts)), and dynamically imports and executes the default export function. This process instantiates the plugin's runtime behavior, including registering flags via `pi.registerFlag()` and commands via `pi.registerCommand()`.

### Can a single plugin support both Pi extensions and standard manifests simultaneously?

Yes. The i-have-adhd repository demonstrates this hybrid approach by including both the executable TypeScript extension for Pi/OMP runtimes and static JSON manifests for Codex and Claude. The [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json) declares the executable extensions while separate directories like `.codex-plugin/` and `.claude-plugin/` contain the standard manifests, allowing the same plugin to function across different AI coding environments.

### What distinguishes Pi flags from capability declarations in standard manifests?

Pi flags are runtime-configurable boolean or typed options registered via `pi.registerFlag()`, allowing users to toggle features during active sessions. Standard manifest capabilities are static declarations in JSON fields like `interface.capabilities` that describe what the plugin can do but offer no interactive runtime configuration or session-level logic execution.