# How the i‑have‑adhd Skill Manages Restating Context Across Multiple User Messages

> Discover how the i-have-adhd skill maintains context across conversations. Learn how it injects rules to enable LLMs to restate steps automatically.

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

---

**The skill persists an enabled flag in the session tree and injects a hidden rules message (`customType: i-have-adhd-rules`) into the model context on every turn, allowing the LLM to automatically restate the current step by following the persistent instructions in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md).**

The `ayghri/i-have-adhd` repository implements a Pi/OMP runtime extension that solves the problem of restating context across multiple user messages for users with ADHD. Rather than manually tracking conversation state in code, the system leverages persistent session entries and non-display system prompts to ensure the model continuously summarizes progress (e.g., "step 3 of 5 done") throughout long interactions.

## Persisting the ADHD Mode Flag

The extension maintains session continuity by storing the enabled state in a custom session entry. When a user toggles the skill via commands like `/i-have-adhd`, "on", "off", or stop phrases such as "stop adhd mode", the system records the mode using a **custom session entry** of type `i-have-adhd-state` (defined as `STATE_ENTRY_TYPE` in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts)).

The `getSavedState()` function scans the session tree for the latest entry of this type, while `restoreState()` invokes this check whenever a session starts or restores. This guarantees that restating context across multiple user messages resumes correctly even after interruptions or browser reloads.

## Loading and Injecting Hidden Rules

The actual restatement logic resides in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md), which contains the human-readable rule "Restate state every turn". The `loadRules()` function in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) loads this file and strips its front-matter to extract the raw instructions.

When ADHD mode is enabled and the rules are not already present in the model’s context, `syncContext()` injects a custom message with the following properties:

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

```

The `display: false` flag ensures the user never sees the raw ruleset, while `customType: "i-have-adhd-rules"` creates a marker that the runtime can detect later.

## Detecting Active Rules with Context Markers

To avoid duplicate injections and to verify that restating context across multiple user messages remains active, the system uses context markers. The `latestMarkerIsActive()` function in [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) walks the list of context messages returned by the runtime:

```typescript
function latestMarkerIsActive(
  messages: readonly ContextMessageMarker[],
  activeType: string,
  disabledType: string,
) {
  let active = false;
  for (const message of messages) {
    if (message.role !== "custom" && message.type !== "custom_message") continue;
    if (message.customType === activeType) active = true;
    else if (message.customType === disabledType) active = false;
  }
  return active;
}

```

This helper returns `true` only if the most recent marker corresponds to the rules message and no subsequent "disabled" marker exists. The `rulesAreInContext()` function wraps this logic, feeding it the array from `contextMessages()` to determine whether the rules are still visible to the model.

## Automatic State Restatement via Persistent Rules

The skill itself does not programmatically generate "step X of Y" strings. Instead, it relies on the **persistent presence of the rules** in the model context. Because the `i-have-adhd-rules` message remains injected across turns, the LLM honors rule 5 ("Restate state every turn") and automatically includes a state summary in each response.

When the user issues a stop phrase like `stop adhd mode` or `normal mode`, the system calls `setEnabled(false)`, which injects a disabling marker (`customType: "i-have-adhd-disabled"`). This marker appears after the rules message in the context array, causing `latestMarkerIsActive()` to return `false` and ending the restatement behavior.

## Lifecycle Hooks and Session Events

The extension registers for three critical events in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) to ensure restating context across multiple user messages remains consistent:

1. **session_start**: Triggers `restoreState()` to check the `i-have-adhd-state` entry
2. **session_tree**: Re-evaluates the session tree structure to locate persistent state markers
3. **session_compact**: Ensures the ruleset marker survives context window compression

These hooks, combined with the runtime registration in [`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json), guarantee that the mode and rule presence are re-evaluated whenever the session is restarted, reconstructed, or compacted.

## Summary

- **Session persistence**: The enabled flag is stored as a custom session entry (`i-have-adhd-state`) and restored via `getSavedState()` on startup.
- **Hidden rules injection**: `syncContext()` 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 injects them as a non-display message with `customType: "i-have-adhd-rules"`.
- **Marker-based detection**: `latestMarkerIsActive()` in [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) verifies rule presence by scanning for the most recent context marker.
- **LLM-driven restatement**: The model automatically restates state because the persistent rules remain visible in its context until a disabled marker is injected.
- **Lifecycle management**: Hooks for `session_start`, `session_tree`, and `session_compact` ensure continuity across session interruptions.

## Frequently Asked Questions

### How does the skill know whether to restate the context?

The extension checks whether the most recent context marker is of type `i-have-adhd-rules` using `latestMarkerIsActive()` in [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts). If this function returns `true`, the rules are present in the model's context window, and the LLM will follow the instruction to restate state every turn.

### What happens when the user disables ADHD mode?

When the user types "stop adhd mode" or "normal mode", the extension calls `setEnabled(false)`, which injects a new marker with `customType: "i-have-adhd-disabled"` into the context. This marker appears after the rules message, causing `latestMarkerIsActive()` to return `false` and effectively removing the restatement instruction from the model's working context.

### Where are the restatement rules defined?

The rules are defined in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md), specifically rule 5 which states "Restate state every turn". The `loadRules()` function in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) reads this file at runtime, strips the front-matter, and caches the content for injection into the model context.

### Does the skill manually parse the current step from the conversation?

No. The extension does not parse conversation history to extract step numbers. Instead, it relies on the LLM's ability to track state internally while following the persistent rule to restate progress on every turn. The skill only manages the presence or absence of the rules message in the context window; the actual state summary is generated by the model itself.