# How the i-have-adhd Extension Tracks Its Ruleset in Context

> Learn how the i-have-adhd extension tracks its ruleset by injecting custom messages and maintaining session state for an ADHD-friendly experience. Discover its context tracking mechanism.

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

---

**The i-have-adhd extension tracks its ruleset by injecting custom-typed messages into the conversation context and maintaining a persistent session state entry, ensuring the ADHD-friendly guidelines appear only when the mode is active.**

The `ayghri/i-have-adhd` repository implements an AI assistant extension that dynamically modifies model behavior to support users with ADHD. Unlike static system prompts, this extension requires sophisticated context tracking to insert, preserve, and remove its ruleset as conversations evolve and users toggle the feature.

## Loading the Ruleset from Disk

When the extension initializes, it reads the human-readable ADHD guidelines from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). The `loadRules` function in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) (lines 46-64) handles this by stripping YAML front-matter and loading the raw Markdown content into memory.

This approach separates the behavioral rules from the implementation logic, allowing modification of the ADHD guidelines without changing the extension code. The loaded content is stored alongside `RULES_HEADER` for consistent formatting when injected.

## Persisting Mode State Across Sessions

To survive session tree rebuilds and IDE restarts, the extension stores the on/off flag in a custom session entry of type `i-have-adhd-state`. The `getSavedState` function and `pi.appendEntry` calls (lines 66-78 and 55-57) manage this persistence layer.

This state entry acts as the source of truth for whether ADHD mode should be active, independent of the conversation context itself. When the session restarts or the tree rebuilds, the extension reads this entry to determine the initial mode before syncing the context.

## Detecting Rules in the Current Context

Before injecting duplicate rules, the extension must verify whether the ruleset is already present. The `rulesAreInContext` helper (lines 90-96) delegates this check to `latestMarkerIsActive` in [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) (lines 41-60).

This utility scans the current session messages to find the most recent custom marker of type `i-have-adhd-rules` versus `i-have-adhd-disabled`. By walking the message list and comparing timestamps, the system determines whether an active rules injection currently exists in the context window, preventing redundant entries that would waste tokens.

## Synchronizing Context with syncContext

The core `syncContext` routine (lines 118-143) orchestrates the injection and removal of rules based on the current state. This function evaluates two conditions: whether ADHD mode is enabled in state, and whether rules are already present in context.

If the mode is **enabled** but rules are **not** in context, the extension calls `pi.sendMessage` with a custom message:

```typescript
if (enabled && !injected) {
  pi.sendMessage(
    { customType: "i-have-adhd-rules", content: `${RULES_HEADER}\n\n${rules}`, display: false },
    { triggerTurn: false },
  );
}

```

Conversely, if the mode is **disabled** while rules remain in context, it sends a disabling marker:

```typescript
else if (!enabled && injected) {
  pi.sendMessage(
    { customType: "i-have-adhd-disabled", content: DISABLED_NOTICE, display: false },
    { triggerTurn: false },
  );
}

```

The `display: false` parameter ensures these system messages remain invisible to the user while remaining visible to the model.

## Manual Toggle and Command Interface

Users can manually trigger mode changes via the `/i-have-adhd` command. The extension registers this handler in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts):

```typescript
pi.registerCommand("i-have-adhd", {
  description: "Toggle ADHD-friendly output for this session",
  handler: async (args, ctx) => {
    const arg = args.trim().toLowerCase();
    if (arg === "" || 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");
  },
});

```

This command interface allows explicit control over the session state, immediately triggering `syncContext` to update the conversation rules.

## Lifecycle Hooks for Context Consistency

The extension hooks into session lifecycle events to maintain ruleset integrity. It restores the saved state during `session_start` and `session_tree` events, ensuring the mode persists across workspace changes.

During `session_compact` events—when the context window is compressed and historical messages may be truncated—the extension re-synchronizes the rules. This ensures that if the custom marker is lost during compaction, the system re-injects it to maintain consistent model behavior throughout long conversations.

## Summary

- **Source Files**: The extension loads rules from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and manages logic in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) with context detection in [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts).
- **State Management**: Uses `i-have-adhd-state` session entries to persist the toggle state across session rebuilds.
- **Context Detection**: The `rulesAreInContext` function scans for `i-have-adhd-rules` or `i-have-adhd-disabled` markers to avoid duplicate injections.
- **Dynamic Injection**: The `syncContext` function injects rules when enabled or removal notices when disabled using `pi.sendMessage` with custom types.
- **Lifecycle Awareness**: Hooks into `session_start`, `session_tree`, and `session_compact` to maintain ruleset presence as the conversation evolves.

## Frequently Asked Questions

### How does the extension know if ADHD mode is enabled after a restart?

The extension stores the on/off flag in a custom session entry of type `i-have-adhd-state` using `pi.appendEntry`. When the session restarts or the tree rebuilds, the `getSavedState` function reads this persistent entry to determine the current mode before syncing the context.

### What happens to the ruleset during session compaction?

During `session_compact` events, the extension re-evaluates context via `syncContext`. If the compaction removed the `i-have-adhd-rules` marker, the system detects its absence through `rulesAreInContext` and re-injects the ruleset to ensure continuous ADHD-friendly behavior without user intervention.

### Can users toggle ADHD mode mid-conversation?

Yes. Users can execute the `/i-have-adhd [on|off]` command at any point. The command handler calls `setEnabled`, which updates the persistent state and immediately triggers `syncContext` to either inject the rules or send a disabled notice, updating the model's behavior for subsequent turns.

### Where are the actual ADHD-friendly rules stored?

The human-readable guidelines reside in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) as Markdown content. The `loadRules` function reads this file at extension startup, strips the YAML front-matter, and stores the content for injection into the model context when ADHD mode activates.