How the i-have-adhd Skill Persists Rules Across a Session: A Technical Deep Dive
The i-have-adhd skill persists its rules across a session by storing an i-have-adhd-state entry in the runtime's session manager and synchronizing hidden custom messages into the model's context on every session start, tree replay, or compaction event.
The i-have-adhd skill is a conversational AI extension that enforces ADHD-friendly output formatting for the duration of a chat session. Rather than sending rules with every request, the skill implements a lightweight persistence layer that restores state automatically and injects rules only when necessary. This article examines the implementation in ayghri/i-have-adhd, focusing on how state survives across session boundaries and model context rebuilds.
Session State Storage Mechanism
The skill's persistence begins with a dedicated state entry type. When a user toggles ADHD mode, the extension appends a custom entry to the session branch using pi.appendEntry().
In extensions/i-have-adhd.ts (lines 81-93):
pi.appendEntry(STATE_ENTRY_TYPE, { enabled } satisfies AdhdModeState);
The STATE_ENTRY_TYPE constant resolves to i-have-adhd-state. This entry contains a minimal payload: { enabled: true | false }. The helper function getSavedState() traverses the session branch via ctx.sessionManager.getBranch() to retrieve the most recent value.
Key design decisions in this mechanism:
- Branch-based storage – State travels with the conversation tree, surviving rewinds and replays
- Minimal payload – Only the boolean flag is stored; rules text is loaded from
SKILL.mdon demand - Latest-wins semantics – Multiple entries are possible; the function returns the most recent
Automatic State Restoration
The skill restores its state on three critical lifecycle events: session_start, tree replay, and session_compact. This ensures rules remain active even after context compaction or connection recovery.
In extensions/i-have-adhd.ts (lines 61-70), the restoreState() function:
- Reads any saved
i-have-adhd-stateentry from the session branch - Falls back through a priority chain: saved state →
alwaysOnconfig →.i-have-adhd-alwayssentinel file → defaultfalse - Synchronizes the computed
enabledflag to UI status indicators - Calls
syncContext()to align the model's visible context
pi.on("session_start", async (_event, ctx) => restoreState(ctx));
pi.on("session_compact", async (_event, ctx) => syncContext(ctx));
The sentinel file check allows users to enable ADHD mode persistently across all sessions by creating .i-have-adhd-always in their workspace.
Context Synchronization and Rule Injection
The syncContext() function (lines 34-52) manages the actual presence of rules in the model's incoming messages. It uses latestMarkerIsActive() from extensions/context-compat.ts to detect whether rules are currently injected.
Injection logic:
- When enabled and rules missing: Sends a hidden custom message of type
i-have-adhd-rulescontainingRULES_HEADERand the full rule text - When disabled but rules present: Sends a removal marker of type
i-have-adhd-disabled
if (enabled && !injected) {
pi.sendMessage(
{
customType: RULES_MESSAGE_TYPE,
content: `${RULES_HEADER}\n\n${rules}`,
display: false, // Hidden from user UI
},
{ triggerTurn: false }, // Does not trigger model response
);
}
The display: false and triggerTurn: false options are critical: they make the message invisible to users and prevent it from consuming a turn in the conversation flow. Yet the message persists in context for all subsequent model calls.
Session-Wide Guarantees
Because rules are injected during context construction events—not per request—they survive across multiple turns without re-transmission. The persistence model handles:
- Multi-turn conversations – Rules remain in context indefinitely
- Context compaction –
syncContext()re-injects rules after the context window is rebuilt - Tree navigation – State entries on the active branch determine current mode
- Connection recovery –
session_startrestoration ensures continuity
The skill's own documentation in skills/i-have-adhd/SKILL.md (lines 15-20) confirms this behavior: rules "apply to every response for the rest of the session" until explicitly disabled via "stop adhd mode" or "normal mode" commands.
Command Interface for Manual Control
Users interact with persistence through a registered command that manipulates the state machine:
pi.registerCommand("i-have-adhd", {
description: "Toggle ADHD-friendly output for this session",
handler: async (args, ctx) => {
const arg = args.trim().toLowerCase();
if (arg === "on") setEnabled(true, ctx);
else if (arg === "off" || arg === "stop") setEnabled(false, ctx);
else setEnabled(!enabled, ctx); // Toggle on bare command
},
});
The setEnabled() function updates both the session state entry and triggers immediate context synchronization, ensuring the change takes effect on the next model interaction.
Configuration-Driven Defaults
Optional file-based configuration influences persistence behavior without code changes. The i-have-adhd.json config file supports:
alwaysOn– Default enablement for new sessionshideStatus– Suppress UI status indicators
The sentinel file .i-have-adhd-always provides a zero-config alternative for permanent activation.
Summary
- State storage uses
i-have-adhd-stateentries in the session manager branch, retrieved viagetSavedState() - Restoration occurs automatically on
session_startand compaction throughrestoreState() - Rule injection happens via hidden
i-have-adhd-rulesmessages only when missing from context, managed bysyncContext() - Persistence survives tree replays, compaction, and reconnection without user-visible re-sending
- Manual control through the
i-have-adhdcommand and optionalalwaysOnconfiguration or sentinel file
Frequently Asked Questions
Where is the ADHD mode state physically stored?
The state is stored as a custom entry in the runtime's session manager branch, accessed through ctx.sessionManager.getBranch(). This branch-based storage travels with the conversation tree and survives rewinds, unlike ephemeral memory.
Do the rules get sent with every model request?
No. The rules are injected once as a hidden custom message during context construction (session start, replay, or compaction) and persist in the model's context window. The triggerTurn: false option prevents this injection from triggering a model response.
What happens if I close and reopen my editor?
On the next session start, the restoreState() function reads any saved i-have-adhd-state entry from the session branch. If no state exists, it checks the alwaysOn configuration or .i-have-adhd-always sentinel file before defaulting to disabled.
How do I permanently enable ADHD mode for all sessions?
Create a .i-have-adhd-always file in your workspace, or set "alwaysOn": true in i-have-adhd.json. Either approach causes restoreState() to default to enabled when no explicit session state exists.
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 →