Main Architectural Decisions in the i-have-adhd Plugin: A Cross-Runtime Architecture Analysis

The i-have-adhd plugin achieves cross-runtime compatibility by separating declarative rules in Markdown from imperative TypeScript logic, abstracting session-manager APIs through a compatibility layer, and persisting state via custom session entries rather than external storage.

The ayghri/i-have-adhd repository demonstrates a deliberate architectural approach to building LLM extensions that must operate across disparate coding assistant runtimes. The codebase prioritizes runtime agnosticism, declarative configuration, and stateless synchronization to deliver ADHD-friendly output formatting without vendor lock-in. Below is a detailed examination of the main architectural decisions that enable this flexibility.

Separation of Concerns: Declarative Rules vs. Runtime Code

Skill Definitions in Markdown

The plugin stores its behavioral rules outside the codebase in skills/i-have-adhd/SKILL.md. This decision keeps the rule set human-readable, versionable, and localizable without requiring recompilation. The loadRules() function (lines 61-78 in extensions/i-have-adhd.ts) loads this Markdown file at runtime, strips any YAML frontmatter using stripFrontmatter(), and caches the result for injection into the model context.

function loadRules(): string {
  const content = readFileSync(SKILL_PATH, "utf8");
  const rules = stripFrontmatter(content);
  if (!rules) throw new Error("The i-have-adhd rules file is empty");
  return rules;
}

TypeScript Extension Bridge

While rules live in Markdown, the programmatic bridge resides in extensions/i-have-adhd.ts. This module provides the runtime-agnostic integration point for any Pi-compatible assistant (Claude Code, Codex, OMP, etc.). By keeping the extension logic separate from the rule content, the architecture allows updates to the ADHD communication style without touching executable code.

Runtime Agnosticism via Abstraction Layers

The Context Compatibility Layer

To handle differing APIs across coding assistants, the plugin implements extensions/context-compat.ts. This module abstracts session-manager inconsistencies—such as buildSessionContext versus buildContextEntries—behind a unified interface. The same synchronization logic therefore functions identically whether running in Anthropic’s Claude or OpenAI’s Codex environment.

Multi-Manifest Support

Rather than maintaining separate codebases for each runtime, the repository includes multiple manifest files (.claude-plugin, .codex-plugin, qwen-extension.json) alongside the core plugin.json. Each runtime reads its own manifest entry point, yet all share identical core logic in i-have-adhd.ts. This eliminates code duplication while satisfying each platform’s packaging requirements.

State Persistence and Session Management

Custom Session Entries for State

The architecture rejects external databases or file-based state in favor of session entry persistence. Using the STATE_ENTRY_TYPE constant, the plugin stores the ADHD mode toggle directly within the session context via pi.appendEntry() (lines 73-76). This guarantees that the enabled state survives session reloads, compactions, and restarts without dependencies on filesystem access or external storage.

pi.appendEntry(STATE_ENTRY_TYPE, { enabled } satisfies AdhdModeState);

Stateless Context Synchronization

To prevent duplicate rule injection and minimize context bloat, the syncContext function (lines 34-59) implements idempotent synchronization. Before injecting, rulesAreInContext() (lines 5-12) checks existing context messages for RULES_MESSAGE_TYPE or DISABLED_MESSAGE_TYPE markers using latestMarkerIsActive(). Rules are only appended when absent, keeping the model’s context window minimal.

function rulesAreInContext(ctx: ExtensionContext): boolean {
  return latestMarkerIsActive(
    contextMessages(ctx.sessionManager),
    RULES_MESSAGE_TYPE,
    DISABLED_MESSAGE_TYPE,
  );
}

Configuration Architecture and User Experience

Hierarchical Configuration System

The plugin supports three configuration mechanisms in descending precedence:

  1. JSON Configuration: The i-have-adhd.json file supports boolean flags alwaysOn and hideStatus for per-project customization, loaded via loadConfig().
  2. Always-On Flag File: A .i-have-adhd-always file in the project root provides a simple file-based opt-in mechanism that functions even when JSON configuration is absent (lines 15-18).
  3. Startup Flag: The adhd flag registration allows activation at session initialization.

This layered approach accommodates both persistent project settings and temporary, file-based overrides.

Command Interface and Graceful Shutdown

User interaction follows a dual-path design. The /i-have-adhd command (registered at lines 87-88) accepts on, off, or toggle arguments through a handler at lines 87-100. For natural language interaction, the STOP_PHRASES constant recognizes phrases like "stop adhd mode" or "normal mode" in the input listener (lines 21-32), allowing users to exit the mode conversationally without memorizing slash commands.

pi.registerCommand("i-have-adhd", {
  description: "Toggle ADHD-friendly output for this session",
  handler: async (args, ctx) => {
    const arg = args.trim().toLowerCase();
    if (arg === "") setEnabled(!enabled, ctx);
    else if (arg === "on") setEnabled(true, ctx);
    else if (arg === "off" || arg === "stop") setEnabled(false, ctx);
    else ctx.ui.notify("Usage: /i-have-adhd [on|off]", "warning");
  },
});

Visual Feedback Integration

When running in supported agents, the architecture exposes state through ctx.ui.setStatus (lines 20-28). This provides immediate visual confirmation of ADHD mode activation, addressing the accessibility requirement for clear system status indicators.

Summary

  • Declarative/Imperative Separation: Rules live in SKILL.md while logic resides in TypeScript, enabling non-technical updates to behavior.
  • Runtime Abstraction: The context-compat.ts layer normalizes disparate session manager APIs across Claude, Codex, and OMP environments.
  • Session-Native Persistence: State survives restarts via STATE_ENTRY_TYPE entries appended to the session context, eliminating external storage dependencies.
  • Layered Configuration: JSON files, filesystem flags, and startup arguments provide flexible deployment options.
  • Idempotent Injection: The syncContext logic prevents duplicate rule messages, maintaining optimal context window usage.

Frequently Asked Questions

How does i-have-adhd maintain state across session restarts?

The plugin persists the ADHD mode toggle using custom session entries rather than external databases. By calling pi.appendEntry(STATE_ENTRY_TYPE, { enabled }) at lines 73-76, the state becomes part of the session context itself. This approach ensures the configuration survives session compactions and reloads without requiring filesystem write access or separate state management infrastructure.

What architectural pattern enables compatibility with multiple AI coding assistants?

The repository implements an adapter pattern through extensions/context-compat.ts, which abstracts differences between session manager APIs like buildSessionContext and buildContextEntries. Combined with runtime-specific manifest files (.claude-plugin, .codex-plugin) that all point to the shared core logic, this architecture allows the same extension to function across Claude Code, Codex, and other Pi-compatible runtimes without code duplication.

Why are the behavioral rules stored in Markdown rather than compiled TypeScript?

Storing rules in skills/i-have-adhd/SKILL.md separates the what (behavioral guidelines) from the how (implementation logic). This declarative approach allows technical writers, clinicians, or translators to modify ADHD-friendly output patterns without reviewing TypeScript code or triggering rebuilds. The loadRules() function strips frontmatter and validates content at runtime, treating the Markdown file as a configuration asset rather than source code.

How can users configure the plugin without modifying repository code?

The architecture provides three code-free configuration mechanisms: (1) Creating an i-have-adhd.json file with alwaysOn or hideStatus flags; (2) Adding an empty .i-have-adhd-always file to the project root for automatic activation; or (3) Passing the adhd flag at session startup. These options allow per-project customization through filesystem operations alone, requiring no changes to the TypeScript source or rebuilds of the extension.

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 →