# How State Is Restored When a Session Starts or Resumes in the Pi Extension

> Learn how the Pi extension restores state on session start or resume by reading persisted entries and re-injecting rulesets. Get a clear explanation of the process.

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

---

**The Pi extension restores ADHD mode by reading persisted session entries, checking CLI flags or marker files for default-on behavior, and re-injecting the ruleset into the model context whenever a `session_start` or `session_tree` event fires.**

The `ayghri/i-have-adhd` repository provides a Pi extension that maintains ADHD-friendly formatting across conversation sessions. When a session begins or a saved conversation tree reloads, the extension must reconstruct the active state to ensure consistent behavior. This restoration process balances user preferences, default configuration, and the current model context.

## The State Restoration Pipeline

The restoration logic is orchestrated in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) through a four-step pipeline that combines persistence lookup with configuration fallbacks.

### Step 1: Retrieving Saved State from the Session Tree

The `getSavedState` function searches the session history for previous ADHD mode configurations. It traverses the conversation tree via `ctx.sessionManager.getBranch()`, filtering for entries of type `i-have-adhd-state` and returning the most recent `enabled` value.

This check occurs at lines 66-80 in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts). If the user previously toggled the mode during the conversation, that persisted value takes precedence over all other settings.

### Step 2: Evaluating Default-On Conditions

When no saved state exists, `restoreState` (lines 145-150) determines whether ADHD mode should activate by default. The logic checks two sources:

- **CLI Flag**: `pi.getFlag("adhd")` detects if the user launched Pi with the `--adhd` flag
- **Marker File**: The existence of a `.i-have-adhd-always` file in the working directory signals "always-on" behavior

The final enabled status is computed as `enabled = savedState ?? enabledByDefault`, ensuring explicit user choices override default settings.

### Step 3: Synchronizing the UI and Model Context

Once the enabled status is determined, the extension updates the interface and model context through two coordinated operations:

**UI Update**: The `updateStatus(ctx)` function (lines 101-108) sets the status bar indicator to "ADHD ON" when enabled, or clears it when disabled.

**Context Injection**: The `syncContext(ctx)` function (lines 118-143) manages the actual ruleset present in the model's context. It injects the ADHD rules from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) when enabling the mode, or inserts a "disabled" notice when turning it off. To prevent duplication, it uses `latestMarkerIsActive` from [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) (lines 41-60) to detect whether the ruleset marker is already present in the current context.

## Event Hooks That Trigger Restoration

Restoration occurs automatically through two distinct lifecycle hooks registered at lines 219-220 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts):

- **`session_start`**: Fires when a brand-new conversation session initializes
- **`session_tree`**: Fires when an existing session tree is restored from disk, such as after resuming a paused session or syncing across devices

Both events invoke `restoreState`, ensuring the ADHD mode is consistently re-hydrated regardless of whether the user starts fresh or resumes previous work.

## Practical Implementation Examples

The following patterns demonstrate how the restoration logic behaves in different scenarios:

```typescript
// Launch Pi with ADHD mode enabled via CLI flag
// The restoreState function detects pi.getFlag("adhd") === true
pi.run({ flags: { adhd: true } });
// Result: enabled set to true, UI updated, rules injected into context

```

```typescript
// Create an always-on marker file
// This bypasses the need for CLI flags in future sessions
await fs.writeFile('.i-have-adhd-always', '');
// Subsequent sessions will default to enabled unless explicitly toggled off

```

```typescript
// Manual toggle during a session (persists across restarts)
await pi.sendCommand("/i-have-adhd on");
// Extension appends {type: 'i-have-adhd-state', enabled: true} to session tree
// On next session_tree event, getSavedState() reads this entry automatically

```

```typescript
// Checking context synchronization
// Uses latestMarkerIsActive from extensions/context-compat.ts
if (!latestMarkerIsActive(ctx.messages, 'adhd-rules')) {
  await syncContext(ctx); // Injects rules only if missing
}

```

## Summary

- **Persistence First**: The extension checks `i-have-adhd-state` entries in the session tree before applying defaults, preserving explicit user toggles across restarts.
- **Default-On Logic**: ADHD mode activates automatically via the `--adhd` CLI flag or the presence of a `.i-have-adhd-always` marker file when no saved state exists.
- **Dual Event Hooks**: Both `session_start` and `session_tree` events trigger `restoreState`, ensuring consistent behavior for new and resumed sessions.
- **Context Deduplication**: The `latestMarkerIsActive` utility prevents duplicate rule injection by scanning existing context messages before adding the ADHD ruleset.

## Frequently Asked Questions

### What happens if no previous state is saved and no default-on flags are set?

If `getSavedState` returns `undefined` and neither the `--adhd` flag nor the `.i-have-adhd-always` file exists, `restoreState` sets `enabled` to `false`. The UI clears any status indicators and `syncContext` ensures no ADHD rules are present in the model context, effectively running Pi in standard mode.

### How does the extension prevent duplicate rule injection when restoring state?

The `syncContext` function calls `latestMarkerIsActive` from [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) to scan the current context messages for an existing ADHD ruleset marker. If the marker is found, the function skips injection; if missing, it injects the rules. This check runs every time state is restored, preventing accumulation of duplicate instructions in long-running or frequently resumed sessions.

### What is the difference between the `session_start` and `session_tree` events?

The `session_start` event fires exclusively when initializing a completely new conversation session with no prior history. The `session_tree` event fires when Pi loads or reloads an existing conversation tree from storage, which occurs when resuming a paused session, restoring from backup, or syncing across devices. The extension listens to both events at lines 219-220 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) to ensure ADHD state is restored in every possible entry scenario.

### Can I force ADHD mode on for all sessions without manually enabling it each time?

Yes. Create an empty file named `.i-have-adhd-always` in your working directory. The `restoreState` function checks for this file at lines 145-150, and if present, sets `enabledByDefault` to `true`. Alternatively, configure your Pi launcher to always include `flags: { adhd: true }`, which achieves the same result without creating marker files.