Key Differences Between OMP and Pi Extensions in i-have-adhd

The key differences between OMP and Pi extensions in i-have-adhd are limited to the runtime-specific SDK imports and underlying transport layers, while the core business logic, event hooks, and state management remain identical across both platforms.

The ayghri/i-have-adhd repository provides a single ADHD-friendly rule-set extension that runs on both the Pi and OMP agent runtimes. Although end users interact with the same /i-have-adhd toggle and see identical colored status indicators, the implementation relies on different runtime packages to handle command dispatch, session events, and state persistence. These key differences between OMP and Pi extensions are confined entirely to the runtime plumbing layer.

Shared Extension Architecture

Both runtimes load the exact same source file: extensions/i-have-adhd.ts. This file contains the complete extension logic, including loading the SKILL.md rule set, toggling ADHD mode, syncing rules with the conversation context, and persisting the enabled state.

The extension also imports shared compatibility helpers from extensions/context-compat.ts. The latestMarkerIsActive utility located there determines whether the active rule-set marker or the disabled notice is the most recent entry in the context. This helper is reused without modification across both runtimes.

Runtime-Specific SDK Imports

The primary code-level divergence occurs at the import statements inside extensions/i-have-adhd.ts. The Pi build imports from @earendil-works/pi-coding-agent, while the OMP build imports from @earendil-works/omp-agent:

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

// OMP runtime
import { getAgentDir, type ExtensionAPI, type ExtensionContext } from "@earendil-works/omp-agent";

Both packages expose identical type names—ExtensionAPI, ExtensionContext, and getAgentDir—but provide different concrete implementations. Pi wraps a local daemon, whereas OMP wraps a web-socket-based server. The project's package.json declares separate scripts for each runtime, pulling in the respective SDK accordingly. The extension code itself does not change; it simply receives a different injected API instance depending on which agent creator loaded it.

Flag and Command Registration

Both runtimes register the adhd flag using pi.registerFlag("adhd", { … }). The semantics are identical: the flag is read from the CLI or from an "always-on" file. Under the hood, Pi stores the flag in its own flag manager, while OMP stores it in a separate runtime-specific flag store.

Command registration follows the same pattern. Both call pi.registerCommand("i-have-adhd", { … }), and the handler must return an object with { action: "handled" | "continue" | "transform" }. OMP may invoke this handler through a different execution path—such as a web-socket message rather than a local process—but the contract seen by the extension code remains the same.

Event Hooks and Session Lifecycle

The extension listens for four lifecycle events on both platforms:

  • "input" – triggered for every user utterance.
  • "session_start" – fires when a new session begins.
  • "session_tree" – fires when the session tree is restored after a restart.
  • "session_compact" – fires after a session compact operation.

The hook names and semantics are identical because both runtimes call pi.on(event, handler). However, the underlying event emitter differs: Pi uses the Pi daemon, while OMP uses the OMP server. This means the exact timing of events—particularly "session_compact"—can vary slightly between the two.

State Persistence and Context Synchronization

When persisting the enabled state, the extension calls pi.appendEntry(STATE_ENTRY_TYPE, …) on both runtimes. The entry shape—{ enabled: boolean }—is unchanged. Pi writes this entry into its session manager branch, while OMP writes it into its own session manager, but the extension remains unaware of which store is active.

Context synchronization also works identically. The extension uses latestMarkerIsActive from extensions/context-compat.ts to decide whether to inject the rule set or the disabled notice. The underlying context-message list comes from whichever session manager is present, but the algorithm is the same.

Visual output is consistent as well. Both runtimes support ctx.ui.theme.fg("success", "●") and ctx.ui.theme.fg("accent", "ADHD ON"), so the status indicators render the same colored tokens regardless of platform.

The "Always-On" Shortcut

Both implementations check for the file <agent-dir>/.i-have-adhd-always to determine whether ADHD mode should start enabled. The getAgentDir() function resolves to the Pi-specific agent directory when running under Pi, and to the OMP agent directory when running under OMP. Because the extension uses the imported getAgentDir() helper rather than a hard-coded path, the shortcut works transparently on both runtimes.

How to Load the Extension on Pi and OMP

Because the extension is runtime-agnostic, you import the same file but use a different agent creator.

To start the extension under the Pi runtime:

import { createPiAgent } from "@earendil-works/pi-coding-agent";
import iHaveAdhdExtension from "./extensions/i-have-adhd";

const pi = createPiAgent();
pi.loadExtension(iHaveAdhdExtension);
pi.start(); // Starts the Pi daemon and begins listening for commands

To start the extension under the OMP runtime:

import { createOmpAgent } from "@earendil-works/omp-agent";
import iHaveAdhdExtension from "./extensions/i-have-adhd";

const omp = createOmpAgent();
omp.loadExtension(iHaveAdhdExtension);
omp.start(); // Connects to the OMP server, then the same commands work

After loading, the /i-have-adhd command behaves identically. For example:

User: /i-have-adhd on
Agent: ✅ ADHD mode enabled.

The command registration resolves to the appropriate runtime dispatcher, so the user experience does not change.

Summary

  • Both runtimes load the exact same extensions/i-have-adhd.ts file; no source fork exists for either platform.
  • The only code-level differences are the SDK import paths: @earendil-works/pi-coding-agent versus @earendil-works/omp-agent.
  • Flag registration (registerFlag), command registration (registerCommand), and event hooks (on("input"), on("session_start"), etc.) share identical signatures and semantics.
  • State persistence via appendEntry(STATE_ENTRY_TYPE, …), context sync via latestMarkerIsActive, and the .i-have-adhd-always shortcut work unchanged because the injected ExtensionAPI abstracts the store differences.
  • UI theme tokens such as ctx.ui.theme.fg("success", "●") produce identical output on both runtimes.

Frequently Asked Questions

Do the Pi and OMP extensions use different source files?

No. Both runtimes import and execute the same extensions/i-have-adhd.ts file. The repository contains a single extension implementation, and the runtime-specific agent creator—createPiAgent or createOmpAgent—injects the appropriate ExtensionAPI implementation at load time.

What is the exact difference between the Pi and OMP runtime imports?

The Pi build imports { getAgentDir, type ExtensionAPI, type ExtensionContext } from @earendil-works/pi-coding-agent, while the OMP build imports the same identifiers from @earendil-works/omp-agent. The type names are identical, but each package provides a different concrete transport layer: Pi uses a local daemon, and OMP uses a web-socket-based server.

Are the event hooks named differently in OMP and Pi?

No. Both runtimes use the same hook names: "input", "session_start", "session_tree", and "session_compact". The extension attaches listeners with pi.on(event, handler) in both cases. The difference is purely the underlying event emitter—Pi's daemon versus OMP's server—which can affect the precise timing of delivery.

Does the .i-have-adhd-always file work in both runtimes?

Yes. The extension resolves the agent directory by calling getAgentDir(), which returns the Pi agent directory when running under Pi and the OMP agent directory when running under OMP. The code then checks for .i-have-adhd-always at that resolved path, so the "always-on" shortcut functions identically on both platforms.

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 →