How i-have-adhd Manages Session-Persistent State in Pi and OMP

The i-have-adhd extension persists ADHD mode across Pi/OMP sessions by storing state in a custom session entry, restoring it via lifecycle hooks, and synchronizing ruleset injection only when needed.

The ayghri/i-have-adhd extension ensures consistent ADHD-friendly formatting across conversation restarts, tree reconstructions, and message compaction. According to the source code, this works through a lightweight persistence layer that avoids redundant ruleset injections while maintaining correct contextual state.

Storing Session State with Custom Entries

When a user toggles ADHD mode, the extension creates a custom session entry that travels with the conversation history.

In extensions/i-have-adhd.ts (lines 55-58), the toggle handler calls:

pi.appendEntry(STATE_ENTRY_TYPE, { enabled });

Here STATE_ENTRY_TYPE equals "i-have-adhd-state". This entry type is opaque to the runtime but retrievable by the extension on demand. Unlike ephemeral flags or process memory, this entry survives session serialization and tree reconstruction.

Restoring State on Session Start

The extension registers two hooks to ensure state restoration: session_start and session_tree. Both trigger restoreState(ctx) as implemented in extensions/i-have-adhd.ts (lines 66-80).

The restoration logic follows a priority chain:

  1. Search saved state – Walk ctx.sessionManager.getBranch() for entries matching STATE_ENTRY_TYPE
  2. Use persisted value – If found, set enabled to the stored boolean
  3. Fall back to CLI/file flags – Otherwise check --adhd flag or always-on marker file
function restoreState(ctx: ExtensionContext) {
  const saved = getSavedState(ctx);  // scans session branch
  enabled = saved ?? (pi.getFlag("adhd") || existsSync(alwaysOnFlag));
  syncContext(ctx);                  // triggers ruleset sync
}

This design prioritizes explicit user choice (the toggle) over environment configuration while still respecting system defaults.

Detecting Context Presence with Compatibility Helpers

Before injecting rules, the extension must determine whether they're already in the model's context window. The rulesAreInContext(ctx) helper in extensions/i-have-adhd.ts delegates to utilities in extensions/context-compat.ts.

Context extraction (context-compat.ts, lines 12-34):

export function contextMessages(sessionManager: SessionManager) {
  // Handles both buildSessionContext (newer) and buildContextEntries (legacy)
  if ("buildSessionContext" in sessionManager) {
    return sessionManager.buildSessionContext();
  }
  return sessionManager.buildContextEntries();
}

Marker scanning (context-compat.ts, lines 41-60):

export function latestMarkerIsActive(
  messages: ContextMessage[],
  activeType: string,
  disabledType: string
): boolean | undefined {
  // Scans reverse-chronologically for most recent marker
}

This dual-utility approach abstracts Pi/OMP runtime version differences, letting the extension run across multiple platform generations.

Synchronizing Context After Restoration and Compaction

The syncContext(ctx) routine in extensions/i-have-adhd.ts (lines 18-33) performs conditional injection based on current state and context analysis:

Condition Action
Enabled, rules absent Inject RULES_MESSAGE_TYPE with header + SKILL.md content
Disabled, stale rules present Inject DISABLED_MESSAGE_TYPE to neutralize previous instructions

This prevents duplicate rule stacking—a common failure mode in extension-based prompting—while allowing clean deactivation.

The session_compact hook ensures rules survive model-side context compression:

pi.on("session_compact", async (_evt, ctx) => syncContext(ctx));

Lifecycle Hook Registration

The extension wires three hooks in extensions/i-have-adhd.ts (lines 19-22):

  • session_startrestoreState – Initial session load
  • session_treerestoreState – Tree-based reconstruction
  • session_compactsyncContext – Post-compaction repair

This coverage handles all standard Pi/OMP session transitions without requiring explicit user action.

Summary

  • State persistence relies on pi.appendEntry("i-have-adhd-state", { enabled }) creating durable session metadata
  • Restoration walks ctx.sessionManager.getBranch() during session_start and session_tree hooks
  • Context detection uses version-compatible helpers from context-compat.ts to check for existing rules
  • Synchronization conditionally injects or neutralizes rules via syncContext, triggered by restoration or session_compact
  • CLI and file flags provide fallback defaults when no saved state exists

Frequently Asked Questions

Where is the ADHD mode state actually stored?

The state lives in the Pi/OMP session manager as a custom entry of type "i-have-adhd-state". This entry is created via pi.appendEntry() when users toggle the mode, and retrieved by scanning ctx.sessionManager.getBranch() during session restoration. The storage mechanism is native to the Pi/OMP runtime, not external files or environment variables.

What happens if the rules are already in the context window?

The extension skips injection to prevent duplication. The rulesAreInContext() helper uses latestMarkerIsActive() from context-compat.ts to scan context messages for the most recent i-have-adhd-rules or i-have-adhd-disabled marker. Only when the marker is absent or stale does syncContext() perform injection.

How does the extension handle different Pi/OMP runtime versions?

Through abstraction in extensions/context-compat.ts. The contextMessages() function detects whether the session manager exposes buildSessionContext (newer runtimes) or buildContextEntries (legacy), calling the appropriate method. This lets i-have-adhd operate across runtime generations without version-specific branches in the main logic.

Can ADHD mode be enabled by default without toggling?

Yes. If no saved session state exists, restoreState() falls back to two alternative signals: the CLI flag --adhd or the presence of an always-on marker file referenced in hooks/hooks.json. These provide automatic enablement for users who want persistent ADHD-friendly formatting across all sessions.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →