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

> Discover how i-have-adhd uses custom entry types like i-have-adhd-state for state tracking in its Pi extension. Learn about session persistence and rule injection.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: source-analysis
- Published: 2026-08-23

---

**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`](https://github.com/ayghri/i-have-adhd/blob/main/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`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts)

At lines 22 through 24 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/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`](https://github.com/ayghri/i-have-adhd/blob/main/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:

```typescript
// 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:

```typescript
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:

```typescript
// 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`](https://github.com/ayghri/i-have-adhd/blob/main/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`](https://github.com/ayghri/i-have-adhd/blob/main/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 types**—`i-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`](https://github.com/ayghri/i-have-adhd/blob/main/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`](https://github.com/ayghri/i-have-adhd/blob/main/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.