How the i-have-adhd Skill Maintains State Across Conversation Turns in Claude Code
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 at lines 175-177, the extension appends a custom entry:
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 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:
- The
adhdflag passed to the runtime viapi.getFlag("adhd") - The optional
alwaysOnfield in the user configuration filei-have-adhd.json - The presence of a sentinel file
.i-have-adhd-alwaysin 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, 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, 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-stateviapi.appendEntry()inextensions/i-have-adhd.ts. - State retrieval occurs through
getSavedState(), which scansctx.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, andsession_compactensure 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 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, 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →