# How Platform Adapters Load the i-have-adhd Ruleset: Complete Technical Guide

> Discover how platform adapters load the i-have-adhd ruleset. Learn about SKILL.md parsing, state determination, and conversation context synchronization for seamless integration.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: technical-guide
- Published: 2026-09-01

---

**Platform adapters load the i-have-adhd ruleset by reading SKILL.md from the skills directory, determining the initial enabled state from configuration flags and session storage, then synchronizing the rules with the conversation context through message injection.**

The i-have-adhd repository implements a platform adapter pattern that injects a static ADHD-friendly response ruleset into AI model contexts. This guide examines the complete loading pipeline as implemented in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), from file system access to runtime synchronization.

## Phase 1: Reading the Rules File

The adapter begins by loading the canonical ruleset from persistent storage.

### Locating and Parsing SKILL.md

In [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) (lines 14-21), the adapter resolves the path to [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and reads its contents:

```typescript
// From extensions/i-have-adhd.ts
const skillPath = path.join(ctx.extensionPath, 'skills', 'i-have-adhd', 'SKILL.md');
const rawContent = fs.readFileSync(skillPath, 'utf-8');

```

The `stripFrontmatter` helper (lines 52-59) removes any YAML metadata, leaving only the ten plain-text rules:

```typescript
// From extensions/i-have-adhd.ts
function stripFrontmatter(content: string): string {
  // Removes --- delimited YAML blocks from the start of the file
  return content.replace(/^---\n[\s\S]*?\n---\n?/, '').trim();
}

```

If the file is missing or empty, the adapter throws a descriptive error (lines 65-76), halting initialization rather than proceeding with partial state.

## Phase 2: Determining the Initial Enabled State

The adapter evaluates multiple configuration sources to decide whether to activate the ruleset at session start.

### The restoreState Function

The `restoreState` function (lines 61-69) checks four sources in priority order:

1. **Previous session entry** – Looks for `STATE_ENTRY_TYPE` in saved session data
2. **Pi runtime flag** – Checks `pi.getFlag("adhd")` for explicit command-line or environment configuration
3. **alwaysOn configuration** – Reads [`i-have-adhd.json`](https://github.com/ayghri/i-have-adhd/blob/main/i-have-adhd.json) via `loadConfig` for persistent preferences
4. **Sentinel file** – Detects `.i-have-adhd-always` in the workspace root

The resulting boolean is stored in the module-level `enabled` variable, which persists across the session lifetime.

### Hook Registration

The adapter registers for three lifecycle hooks in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json):

```json
{
  "hooks": ["session_start", "session_tree", "session_compact"]
}

```

Each hook triggers `syncContext` to ensure the ruleset state remains consistent as the conversation evolves.

## Phase 3: Synchronizing Rules with Conversation Context

The `syncContext` function (lines 34-59) implements the core injection and removal logic.

### Rule Injection

When `enabled` is `true` and no active rules marker exists, the adapter sends:

```typescript
// From extensions/i-have-adhd.ts, lines 38-45
pi.sendMessage({
  type: RULES_MESSAGE_TYPE,
  content: RULES_HEADER + '\n\n' + strippedRules
});

```

The `RULES_HEADER` constant identifies this message as carrying the ADHD ruleset, while `strippedRules` contains the ten parsed guidelines from SKILL.md.

### Rule Removal

When `enabled` transitions to `false`, the adapter sends a disable marker:

```typescript
// From extensions/i-have-adhd.ts
pi.sendMessage({
  type: DISABLED_MESSAGE_TYPE,
  content: DISABLED_NOTICE
});

```

### Marker Validation

The helper `latestMarkerIsActive` from [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) (referenced at lines 5-11) inspects session marker history to confirm whether rules are currently visible to the model. This prevents redundant injections and ensures only the newest state marker counts.

## User Interaction Mechanisms

### Command Registration

The adapter exposes the `/i-have-adhd` command through `pi.registerCommand`, with `/skill:i-have-adhd` as an alias. The command accepts:

- **No arguments** – Toggles the current state
- **`on`** – Forces rules injection
- **`off`** – Forces rules removal

### Stop Phrases

Input matching `STOP_PHRASES` ("stop adhd mode", "normal mode") automatically triggers disable:

```typescript
// Conceptual usage
User: "Please use normal mode"
→ Adapter detects match → Calls setEnabled(false) → Returns DISABLE_CONFIRMATION

```

### Status UI

When active and `hideStatus` is not configured, the adapter displays a status badge:

```typescript
ctx.ui.setStatus('● ADHD ON');

```

## Configuration Examples

### Runtime Toggle

```bash

# Enable for current session

> /i-have-adhd on

```

### Persistent Activation

Create [`i-have-adhd.json`](https://github.com/ayghri/i-have-adhd/blob/main/i-have-adhd.json) in the agent root:

```json
{
  "alwaysOn": true,
  "hideStatus": false
}

```

Or use the sentinel file approach:

```bash
touch .i-have-adhd-always

```

## Summary

- **File loading**: [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) reads [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and strips YAML frontmatter via `stripFrontmatter`
- **State initialization**: `restoreState` evaluates session history, runtime flags, JSON config, and sentinel files to set the `enabled` boolean
- **Context synchronization**: `syncContext` injects rules via `RULES_MESSAGE_TYPE` or removes them via `DISABLED_MESSAGE_TYPE`, validated by `latestMarkerIsActive` from [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts)
- **User control**: Commands, stop phrases, and configuration files provide multiple interfaces for managing the ruleset lifecycle

## Frequently Asked Questions

### What file contains the actual ADHD response rules?

The rules live in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) as plain Markdown. The adapter loads this file once per session, removes any YAML frontmatter, and injects the content into model context when enabled.

### How does the adapter know whether to enable the rules at startup?

It calls `restoreState`, which checks four sources in order: previous session state, the `adhd` runtime flag, the `alwaysOn` config value, and the presence of `.i-have-adhd-always`. The first positive match determines initial state.

### Can users disable the rules without using a command?

Yes. Saying "stop adhd mode" or "normal mode" triggers automatic detection via `STOP_PHRASES` matching. The adapter then disables the mode and may return the fixed confirmation string `DISABLE_CONFIRMATION`.

### Where is the marker validation logic implemented?

The `latestMarkerIsActive` helper resides in [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts). It inspects session marker history to determine whether the most recent state change is still active in the model's context view.