How `i-have-adhd-rules` and `i-have-adhd-disabled` Custom Message Types Manage ADHD Mode Context
TL;DR: The i-have-adhd extension uses two custom message types—i-have-adhd-rules to inject ADHD-friendly instructions into the model's context, and i-have-adhd-disabled to remove them—enabling reversible, state-aware control of specialized response formatting.
The i-have-adhd extension, developed by ayghri/i-have-adhd, implements a clean mechanism for conditionally applying ADHD-friendly conversation rules to large language model interactions. Rather than permanently altering system prompts, it leverages custom message types that can be dynamically inserted and removed from the conversation context. This article explains how i-have-adhd-rules and i-have-adhd-disabled function as toggle markers that control when behavioral rules are active.
What Custom Message Types Do in i-have-adhd
Custom message types in this extension serve as stateful markers rather than visible chat messages. They carry metadata that downstream systems interpret to determine whether ADHD mode is currently enabled.
| Custom Type | Purpose | Definition Location |
|---|---|---|
i-have-adhd-rules |
Injects the complete ADHD-friendly rule text into context | extensions/i-have-adhd.ts lines 22–24 |
i-have-adhd-disabled |
Signals rule deactivation, causing the model to ignore previous instructions | extensions/i-have-adhd.ts lines 22–24 |
These types are defined alongside related constants in the extension's entry point:
const RULES_MESSAGE_TYPE = "i-have-adhd-rules";
const DISABLED_MESSAGE_TYPE = "i-have-adhd-disabled";
const STATE_ENTRY_TYPE = "i-have-adhd-state";
The display: false property ensures these messages remain invisible to users while still affecting model behavior.
How the Injection Flow Works
The extension follows a four-stage process to synchronize context state with user preferences.
1. Load Rule Content from SKILL.md
At startup, the extension reads the canonical rule definition from the filesystem:
const rules = loadRules(); // → extensions/i-have-adhd.ts lines 99–100
This loads skills/i-have-adhd/SKILL.md, which contains the complete behavior instructions for ADHD-friendly responses.
2. Detect Current Context State
The latestMarkerIsActive function determines whether rules are currently in effect:
return latestMarkerIsActive(
contextMessages(ctx.sessionManager),
RULES_MESSAGE_TYPE,
DISABLED_MESSAGE_TYPE,
);
This call appears at extensions/i-have-adhd.ts lines 90–96. The helper is implemented in extensions/context-compat.ts and accounts for message ordering—if i-have-adhd-disabled appears after i-have-adhd-rules, the rules are considered inactive regardless of earlier markers.
3. Synchronize Context with User Preference
Based on the detected state and user setting, the extension sends corrective messages:
Enabling ADHD mode (when rules are absent):
pi.sendMessage(
{ customType: RULES_MESSAGE_TYPE, content: `${RULES_HEADER}\n\n${rules}`, display: false },
{ triggerTurn: false },
);
// → extensions/i-have-adhd.ts lines 121–128
Disabling ADHD mode (when rules are present):
pi.sendMessage(
{ customType: DISABLED_MESSAGE_TYPE, content: DISABLED_NOTICE, display: false },
{ triggerTurn: false },
);
// → extensions/i-have-adhd.ts lines 135–140
The triggerTurn: false option prevents these synthetic messages from initiating a new model response.
4. Persist State Across Sessions
To support session restoration, the extension records the current mode:
pi.appendEntry(STATE_ENTRY_TYPE, { enabled } satisfies AdhdModeState);
// → extensions/i-have-adhd.ts line 157
On session start, this i-have-adhd-state entry is read and the appropriate custom messages are re-injected automatically.
Runtime Compatibility: Pi and OMP Support
The extension supports two execution environments with different native APIs. The context-compat.ts module normalizes these differences:
- Pi runtime: Uses
custom entriesfor persistent state - OMP runtime: Uses
custom messagesfor context manipulation
The unified contextMessages helper returns the appropriate data structure for either runtime, enabling the same latestMarkerIsActive logic to work across both.
Validation Through Automated Testing
The test suite in scripts/check_context_compat.ts verifies marker ordering semantics:
assert(
latestMarkerIsActive(
[{ role: "custom", customType: ACTIVE },
{ role: "custom", customType: DISABLED },
{ role: "custom", customType: ACTIVE }],
ACTIVE,
DISABLED,
),
"OMP marker ordering was not preserved",
);
This confirms that rules → disabled → rules sequences resolve to active, while rules → disabled resolves to inactive—matching intuitive expectations for toggle behavior.
Practical Usage Examples
Toggle from Chat Commands
// User sends: "/i-have-adhd on"
setEnabled(true, ctx); // injects i-have-adhd-rules
// User sends: "normal mode"
setEnabled(false, ctx); // injects i-have-adhd-disabled
Programmatic Rule Injection
pi.sendMessage(
{
customType: "i-have-adhd-rules",
content: "ADHD MODE ACTIVE … (your rule text)",
display: false,
},
{ triggerTurn: false },
);
Check Active State
const active = latestMarkerIsActive(
contextMessages(manager),
"i-have-adhd-rules",
"i-have-adhd-disabled",
);
Key Source Files
| File | Responsibility |
|---|---|
extensions/i-have-adhd.ts |
Core extension logic, message dispatch, state management |
extensions/context-compat.ts |
Runtime abstraction, latestMarkerIsActive implementation |
scripts/check_context_compat.ts |
Ordering and compatibility test suite |
skills/i-have-adhd/SKILL.md |
Source content for injected rule text |
scripts/check_pi_extension.py |
Pi-runtime entry count validation |
Summary
i-have-adhd-rulesinjects ADHD-friendly instructions;i-have-adhd-disabledcancels them- Both use
display: falseandtriggerTurn: falseto remain invisible and non-interactive latestMarkerIsActiveenforces last-marker-wins semantics for predictable togglingi-have-adhd-stateenables session persistence without re-prompting users- The
context-compat.tsabstraction supports Pi and OMP runtimes uniformly
Frequently Asked Questions
What happens if multiple i-have-adhd-rules messages exist in context?
The latestMarkerIsActive function examines only the most recent relevant marker. Earlier instances are ignored, so duplicate injections are harmless butunnecessary. The extension checks for existing markers before injecting to avoid redundancy.
Can these custom message types be used with other rule sets?
Yes. The pattern is generic—replace RULES_MESSAGE_TYPE and the content payload in extensions/i-have-adhd.ts lines 22–24 and 121–128 to implement alternative behavioral modes. The toggle mechanism remains identical.
Why use custom types instead of modifying the system prompt?
Custom messages provide reversibility and visibility into state changes. System prompt modifications are harder to track and cannot be selectively removed without complete context reconstruction. The marker approach also integrates cleanly with session persistence mechanisms.
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 →