# How the i-have-adhd Skill Maintains State Across Conversation Turns in Claude Code

> Discover how the i-have-adhd skill maintains state across conversation turns by storing and restoring custom session entries in Claude Code. Learn to keep ADHD-friendly rules active throughout your chat.

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

---

**The i-have-adhd skill maintains state across conversation turns by storing a custom session entry with type `i-have-adhd-state` whenever the user toggles the mode, then re-reading that entry during session restoration to ensure ADHD-friendly rules persist throughout the conversation.**

The `ayghri/i-have-adhd` repository implements a Claude Code extension designed to support users with ADHD by injecting specialized rules into the conversation context. To provide a seamless experience, the skill must maintain state across conversation turns, remembering whether ADHD-friendly mode is enabled or disabled even when the underlying session tree is rebuilt or compacted. This persistence is achieved through a custom session entry system integrated with Claude Code's extension lifecycle hooks.

## How State Persistence Works in the i-have-adhd Extension

The extension leverages Claude Code's session manager to store and retrieve state using custom entry types that survive across turns.

### Storing the ADHD Mode State

When a user toggles the mode using the `/i-have-adhd` command (or its alias `/skill:i-have-adhd`), the handler invokes `setEnabled` to persist the change. According to the source code in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) at lines 175-177, the extension appends a custom entry:

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

```

This inserts a custom entry with type `i-have-adhd-state` into the session manager's branch, storing the boolean `enabled` flag for later retrieval.

### Retrieving State on Session Restoration

On every turn that could affect the mode—including session start, tree rebuild, or compaction—the extension executes `restoreState`. As implemented in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) lines 81-95, the `getSavedState` function iterates over `ctx.sessionManager.getBranch()` to locate entries where `type` is `"custom"` and `customType` matches `i-have-adhd-state`. When found, it extracts the stored `enabled` value to determine the current mode status.

## Initialization and Fallback Logic

Beyond session storage, the extension implements a hierarchical fallback system for determining the initial state when no previous session entry exists.

### Fallback Sources for Initial State

After attempting to retrieve the saved state, `restoreState` evaluates three additional sources in order of precedence, as shown in lines 61-71 and 162-169 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts):

- The `adhd` flag passed to the runtime via `pi.getFlag("adhd")`
- The optional `alwaysOn` field in the user configuration file [`i-have-adhd.json`](https://github.com/ayghri/i-have-adhd/blob/main/i-have-adhd.json)
- The presence of a sentinel file `.i-have-adhd-always` in the workspace

The final `enabled` value determined from this cascade is used to update the UI status and ensure the ruleset is properly injected into the conversation context.

## Synchronizing Context Across Turns

Maintaining state requires more than just storage; the extension must ensure the conversation context reflects the current mode without redundant injections that could clutter the context window.

### The syncContext Mechanism

The helper function `syncContext`, located at lines 34-48 and 135-149 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), checks whether the ADHD ruleset is already present using `rulesAreInContext`. If the mode is enabled but the rules are missing, it injects them once; if disabled while rules remain present, it injects a "disabled" notice. This mirrors Claude Code's built-in `SessionStart` hook behavior, ensuring rules survive across turns without re-injection on every request.

## Event Hooks for Session Lifecycle

To maintain state across the entire conversation lifecycle, the extension registers specific event listeners that trigger restoration logic.

### Registering Session Event Listeners

As defined at lines 237-240 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), the extension registers listeners for three critical events: `session_start`, `session_tree`, and `session_compact`. Each listener invokes either `restoreState` or `syncContext`, ensuring the stored `enabled` flag is consulted and context updates are applied whenever Claude Code creates a new turn or performs session compaction.

## Summary

- The i-have-adhd skill stores state using custom session entries with type `i-have-adhd-state` via `pi.appendEntry()` in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts).
- State retrieval occurs through `getSavedState()`, which scans `ctx.sessionManager.getBranch()` for previously stored entries during restoration events.
- The extension implements a three-tier fallback system checking runtime flags, JSON configuration, and sentinel files to determine the initial enabled state.
- Context synchronization through `syncContext()` prevents duplicate rule injections while ensuring rules persist across conversation turns.
- Event listeners for `session_start`, `session_tree`, and `session_compact` ensure state consistency throughout the session lifecycle.

## Frequently Asked Questions

### Where is the i-have-adhd state stored in Claude Code?

The state is stored as a custom entry in the session manager's branch with type `i-have-adhd-state`, created using `pi.appendEntry()` in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) when the user toggles the mode, and retrieved via `getSavedState()` during session restoration events.

### What happens to the ADHD rules when the session is compacted or rebuilt?

The extension listens for `session_tree` and `session_compact` events to trigger `restoreState` and `syncContext`, ensuring the rules are reinjected if the mode is enabled but the rules are missing from the reconstructed context, or a disabled notice is added if appropriate.

### Can the i-have-adhd skill be enabled by default without running a command?

Yes, the skill supports three fallback mechanisms for default enabling: passing the `--adhd` runtime flag, setting `alwaysOn: true` in [`i-have-adhd.json`](https://github.com/ayghri/i-have-adhd/blob/main/i-have-adhd.json), or creating a `.i-have-adhd-always` sentinel file in the workspace root.

### How does the extension prevent duplicate rule injections?

The `syncContext` helper checks `rulesAreInContext()` before injecting, ensuring the ADHD ruleset appears exactly once when enabled and inserting a "disabled" notice when turned off, avoiding redundant context modifications across conversation turns.