How the i-have-adhd Extension Handles Session Persistence in Pi/OMP
The i-have-adhd extension persists ADHD-friendly mode across Pi/OMP sessions by storing state in custom session entries, restoring flags on session start, and synchronizing rules with the model context after compaction.
The ayghri/i-have-adhd repository provides a Pi/OMP extension that maintains consistent ADHD-friendly formatting across conversation restarts and tree reconstructions. Understanding how this extension handles session persistence requires examining its custom session entry system, lifecycle hook implementations, and context synchronization logic in extensions/i-have-adhd.ts and extensions/context-compat.ts.
Storing State with Custom Session Entries
When a user toggles ADHD mode, the extension creates a durable record within the session history. Instead of relying solely on volatile flags, it calls pi.appendEntry() with a custom type identifier.
In extensions/i-have-adhd.ts (lines 55-58), the extension executes:
pi.appendEntry(STATE_ENTRY_TYPE, { enabled });
Here, STATE_ENTRY_TYPE equals the string "i-have-adhd-state", creating a persistent entry that travels with the session branch. This approach ensures that the enabled/disabled state survives across context window compaction and session tree reconstructions, as the entry remains part of the retrievable conversation history.
Restoring State on Session Start
The extension registers the restoreState() function to run on both session_start and session_tree hooks. This guarantees that the ADHD mode flag is correctly initialized whether the user starts a fresh conversation or rebuilds a session tree.
According to lines 66-80 in extensions/i-have-adhd.ts, the restoration process:
- Walks the current session branch using
ctx.sessionManager.getBranch() - Searches for entries matching
STATE_ENTRY_TYPE("i-have-adhd-state") - Extracts the
enabledboolean from the most recent matching entry - Falls back to CLI flags (
--adhd) or the "always-on" marker file if no saved state exists
function restoreState(ctx: ExtensionContext) {
const saved = getSavedState(ctx); // walks sessionManager.getBranch()
enabled = saved ?? (pi.getFlag("adhd") || existsSync(alwaysOnFlag));
syncContext(ctx); // injects rules if needed
}
Once the state is determined, the extension immediately calls syncContext() to align the model's context with the restored setting.
Detecting Rules in the Model Context
To avoid duplicating rule injections, the extension must determine whether the ADHD ruleset is already present in the active context. The helper rulesAreInContext() leverages utilities from extensions/context-compat.ts to inspect the current conversation state.
From context-compat.ts (lines 12-34), the contextMessages() function extracts available messages from the session manager, handling API variations between buildSessionContext and buildContextEntries depending on the runtime version.
Then, latestMarkerIsActive() (lines 41-60) scans these messages for custom markers:
RULES_MESSAGE_TYPE("i-have-adhd-rules") – indicates active rulesDISABLED_MESSAGE_TYPE("i-have-adhd-disabled") – indicates rules were explicitly disabled
This detection mechanism prevents redundant rule injection while ensuring the model respects the most recent toggle state.
Synchronizing Context After Compaction
The syncContext() routine ensures the ADHD rules remain consistent even after the model compacts its context window. This function runs after every state restoration and registers on the session_compact hook.
As implemented in extensions/i-have-adhd.ts (lines 18-33), syncContext() performs conditional injection:
- If enabled and rules absent: Injects a message of type
RULES_MESSAGE_TYPEcontaining the rule header and Markdown content fromskills/i-have-adhd/SKILL.md - If disabled but stale rules present: Injects a
DISABLED_MESSAGE_TYPEmessage instructing the model to ignore previous rules
pi.on("session_compact", async (_evt, ctx) => syncContext(ctx));
This synchronization guarantees that the ADHD-friendly formatting guidelines survive session compaction without corruption or duplication.
Lifecycle Hooks Registration
The extension wires its persistence logic into three specific Pi/OMP lifecycle events defined in extensions/i-have-adhd.ts (lines 19-22):
session_start→ TriggersrestoreState()to load persisted flags when a new conversation beginssession_tree→ TriggersrestoreState()to handle tree-based session reconstruction scenariossession_compact→ TriggerssyncContext()to maintain rule presence after context window management
Through this hook architecture, the extension maintains continuous session persistence across the full lifecycle of a Pi/OMP interaction.
Summary
- The extension stores toggle state using
pi.appendEntry("i-have-adhd-state", { enabled })in the session history (lines 55-58) restoreState()scansctx.sessionManager.getBranch()onsession_startandsession_treehooks to retrieve the saved flag (lines 66-80)context-compat.tsprovidescontextMessages()andlatestMarkerIsActive()to detect whether rules are currently in the model context (lines 12-34, 41-60)syncContext()injects or suppresses rules viaRULES_MESSAGE_TYPEorDISABLED_MESSAGE_TYPEmessages, running on thesession_compacthook (lines 18-33)
Frequently Asked Questions
How does the extension prevent duplicate rule injections?
The extension uses the rulesAreInContext() helper that calls latestMarkerIsActive() from context-compat.ts to scan existing messages. It checks for the most recent i-have-adhd-rules or i-have-adhd-disabled marker before deciding whether to inject new instructions, ensuring the model receives the rules exactly once unless the state changes.
What happens if no previous state exists in the session history?
If restoreState() finds no entries of type STATE_ENTRY_TYPE when walking the session branch, it falls back to alternative activation methods. The extension checks for the CLI --adhd flag using pi.getFlag("adhd") or looks for an "always-on" marker file on disk, allowing users to enable the mode persistently across all new sessions.
Where does the extension retrieve the actual ADHD-friendly rules?
The rule content is loaded from skills/i-have-adhd/SKILL.md and injected into the model context as part of the syncContext() routine. When ADHD mode is enabled and rules are not already present, the extension creates a custom message containing both a rule header and the Markdown-formatted guidelines from this skill file.
Why does the extension listen to the session_compact hook?
The session_compact hook fires when the model's context window is compressed or reorganized. By wiring syncContext() to this event, the extension ensures that ADHD-friendly rules are re-injected into the active context if they were removed during compaction, maintaining consistent formatting behavior throughout long conversations.
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 →