# Architectural Design of the Multi-Platform Extension System in i-have-adhd

> Explore the architectural design of the i-have-adhd multi-platform extension system. Learn how a single-source-of-truth skill definition supports multiple AI models like Claude Code, Codex, and Gemini.

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

---

**The i-have-adhd extension system uses a single-source-of-truth skill definition with runtime-specific manifests and pluggable injection strategies to support Claude Code, Codex, Pi, OMP, OpenCode, Qwen, Kimi, and Gemini.**

This repository implements a unified "skill" architecture that governs ADHD-friendly response rules across multiple LLM-assistant runtimes. The multi-platform extension system separates concerns into skill source, runtime-specific plugins, context compatibility, always-on hooks, and state persistence—enabling consistent behavior without duplicating rule logic.

## Core Architectural Concerns

The architectural design of the multi-platform extension system spans five distinct layers:

| Concern | Location | Purpose |
|---------|----------|---------|
| **Skill source** | [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) | Single source of truth for all ADHD-friendly rules |
| **Runtime plugin manifests** | `.claude-plugin/`, `.codex-plugin/`, [`qwen-extension.json`](https://github.com/ayghri/i-have-adhd/blob/main/qwen-extension.json), [`kimi.plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/kimi.plugin.json), [`gemini-extension.json`](https://github.com/ayghri/i-have-adhd/blob/main/gemini-extension.json) | Platform-specific discovery and command registration |
| **Pi/OMP extension logic** | [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) | Toggle commands, state persistence, rule injection |
| **Context compatibility** | [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) | Safe context inspection to prevent duplicate injections |
| **Always-on activation** | `hooks/always-on.mjs`, `.opencode/plugins/i-have-adhd.mjs` | Automatic rule prepending via flag files |

## Skill Source: The Single Source of Truth

All runtimes consume the same markdown file at [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). Each implementation strips the front-matter before injection, ensuring rule updates propagate to every platform simultaneously.

This design eliminates version drift—change one file, affect all runtimes.

## Runtime-Specific Extension Points

### Claude Code and Codex

The [`.claude-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.claude-plugin/plugin.json) and [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json) manifests register the `/i-have-adhd` slash command and expose the skill directory to the runtime's search path.

### Pi and OMP

The [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) file contains the full extension implementation for these runtimes:

```typescript
// extensions/i-have-adhd.ts
// Core command handler that toggles mode and persists state
await pi.runCommand("/i-have-adhd on");   // enable rules
await pi.runCommand("/i-have-adhd off");  // disable rules

```

The file defines `RULES_MESSAGE_TYPE` for custom message injection and uses `pi.appendEntry` to save state to the session manager under the key `i-have-adhd-state`.

### OpenCode

The `.opencode/plugins/i-have-adhd.mjs` plugin implements both command registration and a transformer for always-on mode:

```javascript
// .opencode/plugins/i-have-adhd.mjs
// Config callback adds skills folder to search path
export function config(api) {
  api.addSkillPath('./skills');
}

```

## Context Compatibility Layer

Before injecting rules, the Pi/OMP extension verifies whether the rule set already exists in context. The [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) module provides two critical helpers:

- `contextMessages(sessionManager)` — safely extracts message history
- `latestMarkerIsActive(messages, activeMarker, disabledMarker)` — detects rule presence

```typescript
import { contextMessages, latestMarkerIsActive } from "./context-compat";

function rulesAreInContext(ctx) {
  const msgs = contextMessages(ctx.sessionManager);
  return latestMarkerIsActive(msgs, "i-have-adhd-rules", "i-have-adhd-disabled");
}

```

This prevents duplicate rule injection and enables clean toggling between states.

## Always-On Activation Mechanism

Users can opt into persistent rule application through flag files. When present, hooks automatically prepend the rule set to every system prompt.

### Claude Code / Codex

```bash

# Create flag file in Claude's config directory

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

```

The `hooks/always-on.mjs` script checks for this file at session start:

```javascript
// hooks/always-on.mjs
const flagPath = path.join(os.homedir(), '.claude', '.i-have-adhd-always');
if (fs.existsSync(flagPath)) {
  // Prepend SKILL.md content to system prompt
}

```

### OpenCode

```bash

# Create flag file in OpenCode's config directory

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

```

The OpenCode transformer in `.opencode/plugins/i-have-adhd.mjs` performs the same check on every turn.

## State Persistence and Restoration

For Pi and OMP, session state survives across restarts. The extension:

1. Saves toggle state via `pi.appendEntry('i-have-adhd-state', payload)`
2. Restores on session start via `getSavedState()` in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts)
3. Re-applies the appropriate mode (enabled, disabled, or always-on)

Claude Code and Codex rely on filesystem flags rather than session storage, matching their hook-based architecture.

## Execution Flow: How Pieces Fit Together

1. **Discovery** — Runtime loads its manifest and adds `skills/` to the search path
2. **Command registration** — `/i-have-adhd` becomes available as a slash command
3. **Rule injection** — Two paths exist:
   - **On-demand**: User runs command → `loadRules()` strips front-matter → injects `RULES_MESSAGE_TYPE`
   - **Always-on**: Flag file exists → hook/transformer prepends rules automatically
4. **Context sync** — `rulesAreInContext()` checks for existing markers before injection
5. **State restoration** — Previous session state re-applied on startup

## Summary

- **Single source of truth**: [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) governs all platforms
- **Pluggable runtime adapters**: Each LLM assistant uses its own manifest and injection strategy
- **Context-aware injection**: [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) prevents duplicate rule application
- **Filesystem-based always-on**: Flag files enable persistent activation without code changes
- **Session state persistence**: Pi/OMP store toggle state; Claude/Codex use flags exclusively

## Frequently Asked Questions

### How does the system prevent the same rules from being injected twice?

The Pi/OMP extension calls `rulesAreInContext()` before injection, which uses `latestMarkerIsActive()` from [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) to scan message history for `"i-have-adhd-rules"` or `"i-have-adhd-disabled"` markers. If found, injection is skipped.

### What file enables always-on mode for Claude Code?

Create `~/.claude/.i-have-adhd-always`. The `hooks/always-on.mjs` script detects this file at session start and prepends the full rule set to every system prompt automatically.

### How is state persisted in the Pi/OMP runtime?

The extension calls `pi.appendEntry('i-have-adhd-state', payload)` in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts). The `getSavedState()` function retrieves this entry on session startup, enabling mode restoration across restarts.

### Which runtimes are currently supported by this extension system?

According to the repository source code, the system supports Claude Code, Codex, Pi, OMP, OpenCode, Qwen, Kimi, and Gemini through their respective manifest files and extension hooks.