How the Pi Extension Manages State for i-have-adhd Mode
The Pi extension persists i-have-adhd mode state using custom session entries, restores it automatically on session events, and synchronizes ADHD-friendly rules into the model's context through a marker-based injection system.
The ayghri/i-have-adhd repository implements a robust state management system for its Pi extension that ensures ADHD-friendly conversation rules persist across sessions. This article breaks down exactly how the extension stores, retrieves, and applies its state using Pi's session manager APIs and context injection mechanisms.
State Persistence Through Custom Session Entries
The extension persists the enabled/disabled flag using custom entry types in Pi's session manager branch.
In extensions/i-have-adhd.ts, the extension defines a constant STATE_ENTRY_TYPE with value "i-have-adhd-state". Every state change triggers pi.appendEntry(STATE_ENTRY_TYPE, { enabled }), which stores a minimal JSON object {"enabled":boolean} directly in the session branch.
// Persisting state change to session manager
pi.appendEntry("i-have-adhd-state", { enabled: true });
When restoring state, getSavedState iterates over ctx.sessionManager.getBranch() and extracts the latest enabled value from matching custom entries. If no history exists, the extension falls back to default-on logic checking flags, config files, or a marker file.
Re-hydration on Session Events
The restoreState function handles automatic state recovery when Pi reconstructs sessions or trees.
Registered for session_start and session_tree events, restoreState:
- Retrieves the saved flag via
getSavedState - Determines default activation through
pi.getFlag("adhd"),config.alwaysOn, or.i-have-adhd-alwaysfile presence - Sets the internal
enabledvariable, updates UI status, and callssyncContext
This guarantees consistent behavior whether the user resumes a conversation or starts fresh.
Context Synchronization and Rule Injection
The syncContext function ensures exactly-once rule injection using marker-based detection.
State validation occurs through rulesAreInContext, which scans contextMessages for custom marker types i-have-adhd-rules (present) or i-have-adhd-disabled (explicitly removed).
When enabled and rules missing:
// Injecting ADHD-friendly rules into context
// Sends RULES_MESSAGE_TYPE with header + SKILL.md content
When disabled but rules present:
// Removing rules from model's view
// Sends DISABLED_MESSAGE_TYPE message
The actual rule text loads from skills/i-have-adhd/SKILL.md at runtime.
User-Facing Toggle Commands
Two commands control i-have-adhd mode state:
/i-have-adhd— Toggles viapi.registerCommand, flips flag withsetEnabled/skill:i-have-adhd— Enables without duplicate rules entry
The setEnabled function performs atomic updates:
// Inside setEnabled(enabled, ctx)
// 1. Update internal flag
// 2. Persist with appendEntry
// 3. Refresh UI status
// 4. Re-sync context
// 5. Notify user
Programmatic state inspection is possible:
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
function isAdhdEnabled(ctx: ExtensionContext): boolean {
return ctx.sessionManager.getBranch().some(
entry => entry.type === "custom" &&
entry.customType === "i-have-adhd-state" &&
(entry.data as any)?.enabled === true
);
}
Automatic Disable via Stop Phrases
An input handler monitors for deactivation triggers: "stop adhd mode" or "normal mode". When detected while active, it:
- Calls
setEnabled(false, ctx) - Returns UI-handled response or
- Injects text transformation forcing confirmation:
ADHD mode disabled.
Key Implementation Files
| File | Purpose |
|---|---|
extensions/i-have-adhd.ts |
Core extension: flag handling, state persistence, command registration, context sync |
extensions/context-compat.ts |
Helpers for reading session messages and detecting active/disabled markers |
skills/i-have-adhd/SKILL.md |
Source of ADHD-friendly rule set injected into context |
i-have-adhd.json |
Optional user configuration (alwaysOn, hideStatus) |
.i-have-adhd-always |
Optional file-based flag forcing mode activation |
Summary
- i-have-adhd mode state persists as custom session entries with type
"i-have-adhd-state" - Automatic restoration occurs on
session_startandsession_treeevents viarestoreState - Rule injection uses marker detection (
i-have-adhd-rules,i-have-adhd-disabled) to prevent duplication - Dual command interface provides both toggle and direct-enable paths
- Stop phrase detection enables natural-language deactivation
Frequently Asked Questions
How does the Pi extension store i-have-adhd mode between sessions?
The extension stores state using pi.appendEntry("i-have-adhd-state", { enabled }), which creates a custom entry in Pi's session manager branch. On session restoration, getSavedState iterates the branch to find the latest entry and recover the flag.
What prevents ADHD rules from being injected multiple times?
The rulesAreInContext function checks contextMessages for marker types i-have-adhd-rules or i-have-adhd-disabled. syncContext only injects rules when enabled and markers are absent, or removes them when disabled but markers persist.
Can i-have-adhd mode activate automatically without user commands?
Yes. During restoreState, the extension checks pi.getFlag("adhd"), config.alwaysOn, and .i-have-adhd-always file presence. Any true condition activates the mode automatically on session start.
How do I programmatically check if i-have-adhd mode is currently enabled?
Query the session manager branch directly:
const saved = ctx.sessionManager.getBranch().some(
entry => entry.type === "custom" &&
entry.customType === "i-have-adhd-state" &&
(entry.data as any)?.enabled === true
);
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 →