i-have-adhd Multi-Platform Plugin Architecture: How One Rule Set Powers Claude Code, Codex, Pi, and OMP

The i-have-adhd skill stores ADHD-friendly formatting rules in skills/i-have-adhd/SKILL.md and deploys them across Claude Code, Codex, Pi, and OMP through thin JSON manifests, a shared TypeScript extension, and an optional always-on hook that prepends the rules to every system prompt.

The i-have-adhd repository delivers a consistent, ADHD-friendly response style across multiple AI coding runtimes. Its multi-platform plugin architecture relies on a single source-of-truth skill file consumed by every supported platform. By separating the rule set from runtime-specific registration logic, the project guarantees identical behavior whether you invoke it in Claude Code, Codex, Pi, or OMP.

Three-Layer Architecture Overview

The architecture is divided into three layers that are shared across all platforms:

  • Skill definition – The human-readable rule set stored in skills/i-have-adhd/SKILL.md.
  • Runtime-specific manifest and glue code – Platform files that register the skill and inject the rule set.
  • Always-on hook – Optional flag-based injection that prepends rules to every system prompt.

This design means any edit to skills/i-have-adhd/SKILL.md instantly propagates to every runtime without touching platform-specific code.

Skill Definition: The Single Source of Truth

All platforms read their behavior rules from skills/i-have-adhd/SKILL.md. This file contains the complete ADHD-friendly rule set, including instructions to lead with the next action, number steps, and suppress tangents. Because every runtime loads this file directly—typically via readFileSync(SKILL_PATH)—a single change to the skill definition immediately updates behavior across Claude Code, Codex, Pi, and OMP.

Runtime Manifests and Glue Code

Claude Code and Codex JSON Manifests

Claude Code and Codex rely on minimal JSON manifests. The file .claude-plugin/plugin.json registers the plugin with the Claude Code runtime, while .codex-plugin/plugin.json does the same for Codex and adds UI metadata. Both manifests describe the plugin name, version, and description, and both declare the skills/ directory so the runtime can locate SKILL.md.

Pi and OMP TypeScript Extension

Pi and OMP share a single TypeScript extension at extensions/i-have-adhd.ts. The package.json file declares this extension under the pi and omp fields:

{
  "extensions": [
    "./extensions/i-have-adhd.ts"
  ]
}

The extension registers an adhd flag, an i-have-adhd command, and hooks into the session lifecycle via session_start, session_tree, and session_compact. During initialization, it loads the rule text with readFileSync(SKILL_PATH) and caches it for injection.

You can also interact with the extension programmatically:

import { ExtensionAPI } from '@earendil-works/pi-coding-agent';

export default function (pi: ExtensionAPI) {
  pi.registerCommand('i-have-adhd', {
    description: 'Toggle ADHD-friendly output',
    handler: async (args, ctx) => {
      // same logic as the extension – toggle or force on/off
    },
  });
}

Rule Injection and Session State

On-Demand Toggle

Users can toggle ADHD-friendly formatting at runtime with the /i-have-adhd command. The extension maintains a session-wide state entry called i-have-adhd-state. When toggled on, the extension injects a custom-type message identified by RULES_MESSAGE_TYPE on the next turn, delivering the full rule set to the model.

You can also force a specific state:

/i-have-adhd on
/i-have-adhd off

Always-On Hook

For users who want the rules applied to every turn without running a command, the always-on hook checks for a hidden flag file. Claude Code looks for ~/.claude/.i-have-adhd-always, while the OpenCode plugin uses ~/.config/opencode/.i-have-adhd-always. When the flag exists, hooks/always-on.mjs or .opencode/plugins/i-have-adhd.mjs prepends the rule set to the system prompt automatically. The Pi/OMP extension consults its own alwaysOnFlag to enable the same behavior.

Create the flag to enable always-on mode:


# Claude Code

touch ~/.claude/.i-have-adhd-always

# OpenCode

touch ~/.config/opencode/.i-have-adhd-always

Remove the flag to disable it:

rm ~/.claude/.i-have-adhd-always
rm ~/.config/opencode/.i-have-adhd-always

State Persistence

The extension saves the current mode as a custom entry (i-have-adhd-state) so it survives session reloads. When a new session starts, the restoreState routine reads the saved entry—or the always-on flag—and restores the UI status, displaying an ADHD ON badge if the skill is active.

Cross-Runtime Compatibility

Because i-have-adhd uses the same skill file, the same rule-loading routine, and the same command name across every runtime, behavior is identical regardless of platform. The hooks/hooks.json file registers the always-on command specifically for Claude Code sessions, while the shared TypeScript extension and JSON manifests handle the rest. This unified approach eliminates drift between platforms and simplifies maintenance.

Summary

  • skills/i-have-adhd/SKILL.md is the single source of truth for ADHD-friendly rules, loaded by all runtimes via readFileSync(SKILL_PATH).
  • Claude Code and Codex use lightweight JSON manifests (.claude-plugin/plugin.json and .codex-plugin/plugin.json) to register the skill.
  • Pi and OMP rely on extensions/i-have-adhd.ts, registered in package.json, to handle flags, commands, and lifecycle hooks.
  • Users can toggle rules on demand with /i-have-adhd or enable always-on mode via a hidden flag file read by hooks/always-on.mjs.
  • Session state is preserved through the i-have-adhd-state entry and restored by restoreState across reloads.

Frequently Asked Questions

How does the i-have-adhd plugin maintain a single source of truth across platforms?

The project stores its complete rule set in skills/i-have-adhd/SKILL.md. Every runtime—Claude Code, Codex, Pi, and OMP—loads this file directly using readFileSync(SKILL_PATH). When the skill file is updated, all platforms receive the new rules immediately without requiring individual code changes.

What is the difference between on-demand and always-on rule injection?

On-demand injection requires the user to run /i-have-adhd, which sets the i-have-adhd-state flag and injects the rules as a RULES_MESSAGE_TYPE message on the next turn. Always-on injection relies on a hidden flag file—~/.claude/.i-have-adhd-always for Claude Code or ~/.config/opencode/.i-have-adhd-always for OpenCode—read by hooks/always-on.mjs to prepend the rules to every system prompt automatically.

Which file handles the Pi and OMP extension logic?

The TypeScript file extensions/i-have-adhd.ts contains the shared extension logic for Pi and OMP. It is declared in package.json under the pi and omp fields and manages the adhd flag, the i-have-adhd command, and session lifecycle hooks such as session_start, session_tree, and session_compact.

How is session state preserved when using i-have-adhd?

The extension persists the current mode as a custom i-have-adhd-state entry. When a new session begins, the restoreState function reads this entry—or checks the always-on flag file—and re-applies the previous configuration, including the ADHD ON UI badge.

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 →