How Platform-Specific Extensions Extend Core Plugin Functionality in the i-have-adhd Pi Agent
Platform-specific extensions in the i-have-adhd repository extend the core Pi Coding Agent framework by decorating the generic ExtensionAPI with runtime-agnostic behavior that loads ADHD rules, persists state, registers commands, and synchronizes context across sessions.
The extensions/i-have-adhd.ts file serves as the primary adapter that bridges the Pi framework's standardized interface to ADHD-specific functionality. This pattern allows the same TypeScript extension to run identically across Claude, Codex, Pi, OMP, and other supported runtimes without platform-specific rewrites.
How the Extension Loads and Applies ADHD Rules
The first responsibility of extensions/i-have-adhd.ts is sourcing the behavioral rules that modify model output.
In skills/i-have-adhd/SKILL.md, the ADHD-friendly response guidelines are stored as a markdown file with YAML front-matter. The extension strips this front-matter and caches the cleaned text for runtime injection.
// From extensions/i-have-adhd.ts
const skillPath = "skills/i-have-adhd/SKILL.md";
const skillContent = await pi.readFile(skillPath);
const rulesText = stripFrontMatter(skillContent);
This separation of concerns—storing rules as data while the extension handles orchestration—lets non-developers tweak behavior without touching code.
Persisting ADHD Mode State Across Sessions
Platform-specific extensions use the ExtensionContext to maintain state that survives individual turns or full session restarts.
The i-have-adhd.ts extension defines a custom session entry type called i-have-adhd-state. This entry integrates with the Pi session manager to remember whether ADHD mode was enabled when the user returns later.
// Custom session entry type for state persistence
interface ADHDState {
enabled: boolean;
timestamp: number;
}
// Restore state when session resumes
pi.on("session_start", async () => {
const saved = await pi.session.getEntry("i-have-adhd-state");
if (saved?.enabled) {
await enableMode();
}
});
Without this persistence layer, users would need to re-enable the mode every time they start a new conversation.
Registering Flags and Slash Commands
The extension surface area expands through pi.registerFlag and pi.registerCommand, which expose ADHD controls to users in two ways:
| Mechanism | Purpose | Example |
|---|---|---|
| Boolean flag | Pre-enable mode at session start | pi.start({ adhd: true }) |
| Slash command | Toggle mode interactively | /i-have-adhd, /i-have-adhd on, /i-have-adhd off |
// Register the startup flag
pi.registerFlag("adhd", {
type: "boolean",
description: "Enable ADHD-friendly output mode",
default: false,
});
// Register interactive toggle command
pi.registerCommand("i-have-adhd", {
handler: async (args) => {
const desired = parseToggleArg(args);
desired ? await enableMode() : await disableMode();
},
});
Both entry points converge on the same internal state machine, ensuring consistent behavior regardless of activation method.
Synchronizing Rules with Model Context
The syncContext helper function in extensions/i-have-adhd.ts manages the actual injection of rules into the model's working memory. This logic delegates marker detection to extensions/context-compat.ts.
// From extensions/context-compat.ts
function latestMarkerIsActive(
context: ExtensionContext,
markerType: string
): boolean {
const messages = getContextMessages(context);
return messages.some(m => m.customType === markerType && m.active);
}
When syncContext detects that ADHD rules are missing, it injects a custom message:
await pi.sendMessage({
customType: "i-have-adhd-rules",
content: rulesText,
display: false, // Hidden from user interface
}, { triggerTurn: false });
If the mode is explicitly disabled, it instead injects a "disabled" notice to suppress previously loaded rules. This bidirectional synchronization prevents stale context from influencing outputs.
Hooking Into Runtime Lifecycle Events
Platform-specific extensions achieve deep integration by subscribing to four core events emitted by the Pi runtime:
input– Validate and potentially block or transform user messagessession_start– Restore saved ADHD state and initialize UIsession_tree– Update status badges when conversation branchessession_compact– Re-inject rules after context window compression
The session_compact handler is particularly critical. When long conversations hit token limits, the runtime summarizes older turns. The extension ensures ADHD rules survive this compaction by detecting the event and re-injecting them into the compressed context.
Providing UI Feedback for Active Mode
When ADHD mode is enabled, updateStatus renders a visual indicator in the agent interface:
- Green status dot
- "ADHD ON" label in the model status bar
- Toast notification on mode toggle
This feedback loop closes the user experience gap, confirming that their command registered and that subsequent responses will follow ADHD-optimized formatting rules.
Extension Architecture Across Runtimes
According to AGENTS.md, the Pi framework maps multiple runtimes—Claude, Codex, Pi itself, and OMP—to standardized entry points. Extensions live in the extensions/ folder and are discovered at runtime based on manifest configuration.
This architecture means extensions/i-have-adhd.ts executes unchanged whether loaded inside Claude Desktop, a Codex CLI session, or a web-based Pi interface. The platform handles transport and rendering; the extension handles behavior.
Summary
- Rule loading:
extensions/i-have-adhd.tsreadsskills/i-have-adhd/SKILL.md, strips front-matter, and caches content for injection - State persistence: Custom
i-have-adhd-statesession entries remember mode status across sessions - User controls:
pi.registerFlag("adhd")for startup activation,pi.registerCommand("i-have-adhd")for interactive toggling - Context sync:
syncContextandlatestMarkerIsActivefromextensions/context-compat.tsensure rules stay present (or properly removed) in model context - Lifecycle hooks: Event handlers on
session_start,session_compact, and others maintain consistent behavior through session mutations - Cross-runtime: Single TypeScript extension runs on Claude, Codex, Pi, OMP, and future platforms without modification
Frequently Asked Questions
What is the Pi Coding Agent framework?
The Pi Coding Agent framework is the runtime foundation that provides ExtensionAPI and ExtensionContext abstractions for building AI agent plugins. It standardizes how extensions register commands, persist state, and manipulate model context across different hosting environments including Claude, Codex, and OpenAI's Platforms.
How does the ADHD extension avoid duplicate rule injection?
The extension uses latestMarkerIsActive from extensions/context-compat.ts to scan the current context messages for existing i-have-adhd-rules markers. Only when this returns false does syncContext inject new rules, preventing wasteful duplication and token consumption.
Can multiple platform-specific extensions run simultaneously?
Yes. The Pi framework supports multiple extensions in the same session, each with isolated state namespaces. Extensions like i-have-adhd.ts use prefixed identifiers (i-have-adhd-state, i-have-adhd-rules) to avoid collision with other registered functionality.
Where is the actual ADHD behavior defined versus where is it loaded?
Behavioral rules live in skills/i-have-adhd/SKILL.md as plain markdown with YAML front-matter—these define what ADHD-friendly output looks like. extensions/i-have-adhd.ts defines how those rules get loaded, when they apply, and how users control them. This separation lets you modify response guidelines without redeploying code.
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 →