# How the Multi-Runtime Architecture Supports Concurrent Claude Code, Codex, and Pi Usage

> Discover how the multi-runtime architecture allows concurrent use of Claude Code, Codex, and Pi. Learn about state synchronization and runtime abstraction.

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

---

**The multi-runtime architecture enables concurrent usage by utilizing a single shared TypeScript extension loaded through runtime-specific manifest files, ensuring state synchronization via a unified session manager while abstracting runtime differences through a compatibility layer.**

The **i-have-adhd** repository implements an ADHD-friendly AI assistant behavior that operates seamlessly across multiple AI coding environments. By leveraging a sophisticated multi-runtime architecture, the extension shares a single source of truth between Claude Code, Codex, and Pi without duplicating logic or creating state conflicts. This design ensures that enabling the mode in one runtime instantly propagates to others through shared state persistence.

## Runtime-Specific Manifest Configuration

The architecture uses lightweight JSON manifests to inform each runtime how to locate and load the central extension. Each runtime maintains its own configuration file while pointing to the same TypeScript source.

### Claude Code Plugin Structure

Claude Code loads the extension through [`.claude-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.claude-plugin/plugin.json), which declares the plugin metadata including name, version, and description. When the Claude Code interpreter initializes, it reads [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) and executes the always-on script `hooks/always-on.mjs` to register the extension.

### Codex Plugin Structure

Codex utilizes [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json) to provide metadata for the Codex marketplace. The runtime loads the extension via its generic plugin loader, which scans for files in the `extensions/` directory and initializes the shared TypeScript implementation.

### Pi Extension Declaration

Pi identifies the extension through the `pi.extensions` field in [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json), which points to [`./extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/./extensions/i-have-adhd.ts). The Pi runtime creates a **PiExtensionAPI** object and registers the command and flag handlers defined in the shared source file.

## Shared Extension Core

All three runtimes execute logic from [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), which serves as the single source of truth for ADHD-mode behavior. This central file implements rule loading, state handling, and runtime-agnostic hooks. Because every runtime points to the **same TypeScript source**, the logic for loading ADHD rules, persisting enabled states, and injecting rules into conversations executes only once per session, regardless of which runtime handles the request.

## Session State Synchronization

State consistency across concurrent runtimes relies on a unified session management system that stores configuration as custom entries accessible to all environments.

### Unified Session Management

The extension receives an `ExtensionContext` object that provides access to `ctx.sessionManager`. This manager stores the current mode in a custom entry named `i-have-adhd-state`. Any runtime can invoke `getSavedState()` to retrieve the current configuration, ensuring that toggling the mode in Claude Code immediately reflects in Codex or Pi sessions.

### Context Compatibility Layer

The file [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) abstracts runtime-specific differences in message handling. Functions like `latestMarkerIsActive()` normalize how each runtime marks messages as "active" or "disabled," allowing the extension to determine whether the ADHD ruleset is already present in the model's context without runtime-specific conditional logic.

## Command and Flag Registration

The extension registers a **flag** (`adhd`) and a **command** (`i-have-adhd`) via `pi.registerFlag` and `pi.registerCommand`. While these APIs originate from the Pi runtime specification, Claude Code and Codex expose equivalent functionality through their own UI layers. This allows users to toggle the mode using `/i-have-adhd` in any runtime, with changes propagating instantly through the shared state manager.

## Session Initialization with Always-On Hooks

The file `hooks/always-on.mjs` executes at session start for all supported runtimes. This hook calls `restoreState()`, which reads the saved state from the session manager, checks for the optional always-on file (`.i-have-adhd-always`), or applies the `adhd` flag default. This mechanism guarantees consistent mode restoration regardless of which runtime initiated the session.

## Practical Implementation Examples

The following examples demonstrate how to interact with the extension across different runtimes:

```typescript
// Toggle ADHD mode from any runtime interface
/i-have-adhd          // Toggles current state
/i-have-adhd on      // Forces enable
/i-have-adhd off     // Forces disable

```

```typescript
// Sending a request with automatic rule injection
// The extension handles injection automatically; no manual context management required
await pi.sendMessage({
  content: "Explain how to brew coffee in three steps.",
  // ADHD rules are injected via the extension's background processing
});

```

```typescript
// Disable mode via stop phrase (functional across all runtimes)
if (input === "stop adhd mode") {
  // Extension detects phrase, calls setEnabled(false, ctx)
  // Automatically replies with confirmation text
}

```

## Summary

- **Single Source of Truth**: All runties load [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), eliminating code duplication and version drift.
- **Manifest Isolation**: Runtime-specific JSON files ([`.claude-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.claude-plugin/plugin.json), [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json), [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json)) handle initialization while sharing implementation logic.
- **State Persistence**: The `ctx.sessionManager` stores `i-have-adhd-state` as a custom entry, enabling real-time synchronization between Claude Code, Codex, and Pi.
- **Runtime Abstraction**: [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) provides helper functions like `latestMarkerIsActive()` to normalize differences between runtime APIs.
- **Consistent Initialization**: `hooks/always-on.mjs` ensures mode restoration at session startup across all supported environments.

## Frequently Asked Questions

### How does the extension prevent duplicate rule injections when multiple runtimes are active?

The extension tracks context state using `latestMarkerIsActive()` from [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) to detect whether ADHD markers already exist in the conversation history. Before injecting rules from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md), it checks this state to ensure rules are added only once per session, regardless of which runtime processes the request.

### Can I use different ADHD settings for Claude Code versus Pi simultaneously?

No, the architecture intentionally shares state through `ctx.sessionManager`. When you toggle the mode via `/i-have-adhd` or the `adhd` flag in one runtime, the `i-have-adhd-state` entry updates globally. The `getSavedState()` function retrieves this shared value, ensuring consistent behavior across all connected runtimes.

### What happens if I enable ADHD mode in Claude Code but then switch to Codex mid-session?

The mode persists because `hooks/always-on.mjs` runs at session start for all runtimes and calls `restoreState()`. This function reads the saved state from the session manager, meaning Codex will automatically recognize the enabled state when initialized, maintaining continuity without requiring manual re-enablement.

### Where are the ADHD behavioral rules actually defined?

The rule content resides in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). The extension loads this file when enabled and injects its contents into the model's system context. This separation of rules from runtime logic allows updates to the ADHD guidelines without modifying the multi-runtime architecture components.