Custom Entry Types Used for State Tracking in the Pi Extension: i-have-adhd Source Analysis

The Pi extension in the ayghri/i-have-adhd repository defines three custom entry types—i-have-adhd-state, i-have-adhd-rules, and i-have-adhd-disabled—to persist session state, inject behavioral rules, and manage mode transitions across conversation branches.

The i-have-adhd skill for Pi requires persistent state management to track whether ADHD-friendly mode is enabled across sessions. According to the source code in extensions/i-have-adhd.ts, the extension employs custom entry types to store boolean flags, rulesets, and mode transition notices directly within the conversation context. This design ensures that state survives session restarts without requiring external databases or storage mechanisms.

The Three Custom Entry Types Defined in extensions/i-have-adhd.ts

At lines 22 through 24 of extensions/i-have-adhd.ts, the extension defines three distinct string constants that serve as identifiers for custom session entries. Each type serves a specific function in the state tracking lifecycle.

i-have-adhd-state: Persisting the Enabled Flag

The i-have-adhd-state entry type persists the boolean enabled value that indicates whether ADHD-friendly mode is currently active. When users toggle the mode, the extension calls pi.appendEntry('i-have-adhd-state', { enabled }) at lines 57-58 to write this state to the current session branch. This entry is read back on session restore to remember whether ADHD-friendly mode was active, ensuring continuity across conversation restarts.

i-have-adhd-rules: Injecting Behavioral Guidelines

The i-have-adhd-rules custom entry holds the injected ruleset that modifies the model’s behavior while ADHD mode is on. It is dispatched using pi.sendMessage() with the custom type identifier defined at line 23, ensuring the rules appear in the conversation context as a custom message. This entry allows the behavioral constraints to persist within the context window without triggering unnecessary AI turns, as configured via triggerTurn: false.

i-have-adhd-disabled: Handling Mode Deactivation

When ADHD mode is disabled, the extension writes an i-have-adhd-disabled entry (defined at line 24) to carry the "ADHD mode off" notice. This custom entry allows the extension to cleanly remove the rules from the conversation by superseding previous rule injections, preventing stale behavioral instructions from persisting in the context after the user has turned off the feature.

How State Restoration Works Across Sessions

The extension implements a recovery mechanism in restoreState() that queries historical entries to reconstruct the previous configuration. On session initialization, the code iterates over the session branch retrieved via ctx.sessionManager.getBranch() and filters for entries where entry.type === "custom" and entry.customType === STATE_ENTRY_TYPE (lines 69-72). If a matching i-have-adhd-state entry is found, the code extracts the saved enabled boolean value (lines 75-77) and applies it to the current session, overriding the default configuration only when explicit state exists.

Practical Implementation Examples

The following code examples from extensions/i-have-adhd.ts demonstrate how these custom entry types function in production:

Toggling Mode and Persisting State

When users enable or disable ADHD mode, the setEnabled() function persists the change using the state entry type:

// Toggle the mode and persist the state
function setEnabled(nextEnabled: boolean, ctx: ExtensionContext): void {
  enabled = nextEnabled;
  // Persist the new state using the custom entry type
  pi.appendEntry('i-have-adhd-state', { enabled } satisfies AdhdModeState);
  updateStatus(ctx);
  syncContext(ctx);
  ctx.ui.notify(`ADHD mode ${enabled ? "enabled" : "disabled"}`, "info");
}

Restoring Saved State on Startup

The extension checks for existing state entries when initializing a session:

function restoreState(ctx: ExtensionContext): void {
  const savedState = getSavedState(ctx); // looks for 'i-have-adhd-state' entries
  const enabledByDefault = pi.getFlag("adhd") === true || existsSync(alwaysOnFlag);
  enabled = savedState ?? enabledByDefault;
  updateStatus(ctx);
  syncContext(ctx);
}

Injecting Rules and Disabled Notices

The extension uses pi.sendMessage() with custom types to manage conversation context:

// When ADHD mode is enabled and the rules are not yet in context
pi.sendMessage(
  { customType: 'i-have-adhd-rules', content: `${RULES_HEADER}\n\n${rules}`, display: false },
  { triggerTurn: false },
);

// When ADHD mode is disabled and a rules message is still present
pi.sendMessage(
  { customType: 'i-have-adhd-disabled', content: DISABLED_NOTICE, display: false },
  { triggerTurn: false },
);

Supporting Files and Architecture

The state tracking system relies on auxiliary utilities defined in related files:

  • extensions/context-compat.ts: Provides helper functions contextMessages() and latestMarkerIsActive() used by the extension to determine whether rule messages are currently present in the conversation context. These utilities support the logic that decides when to inject new entries or remove stale ones.
  • skills/i-have-adhd/SKILL.md: Contains the actual rule content that gets injected via the i-have-adhd-rules entry type, defining the specific behavioral modifications applied when ADHD mode is active.

Summary

  • Three custom entry typesi-have-adhd-state, i-have-adhd-rules, and i-have-adhd-disabled—enable the Pi extension to track and persist ADHD mode configuration across sessions.
  • State persistence uses pi.appendEntry() at lines 57-58 of extensions/i-have-adhd.ts to write boolean flags to the session branch.
  • State restoration queries the session branch via ctx.sessionManager.getBranch() and filters for entries matching the custom type constants defined at lines 22-24.
  • Rules injection and mode transition notices use pi.sendMessage() with custom type identifiers to manipulate conversation context without triggering unwanted AI turns.

Frequently Asked Questions

How does the Pi extension restore ADHD mode after a session restart?

The extension calls restoreState() on initialization, which iterates through entries in ctx.sessionManager.getBranch() looking for items where entry.type === "custom" and entry.customType === "i-have-adhd-state". If found, it extracts the saved enabled boolean value at lines 75-77 and applies it to the current session, ensuring continuity with the previous conversation state.

What is the difference between i-have-adhd-rules and i-have-adhd-state entries?

The i-have-adhd-state entry type stores configuration metadata (the enabled/disabled boolean flag) using pi.appendEntry(), while i-have-adhd-rules contains the actual behavioral instructions sent via pi.sendMessage() to modify the AI's responses. Rules entries appear in the conversation context as visible messages, whereas state entries serve as hidden metadata for persistence logic.

Where are the custom entry type constants defined in the source code?

All three custom entry type string constants are defined at lines 22-24 of extensions/i-have-adhd.ts. Line 22 defines the state entry type, line 23 defines the rules entry type, and line 24 defines the disabled notice type. These constants are referenced throughout the extension to ensure consistent type checking when appending or retrieving entries from the session branch.

Can the extension track state without using custom entry types?

According to the implementation in ayghri/i-have-adhd, the extension relies specifically on custom entry types because they integrate directly with Pi's session management system. Without them, the extension would lose the ability to query historical session data via ctx.sessionManager.getBranch() and could not automatically restore the ADHD mode flag when conversations resume.

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 →