# How the Pi Runtime Architecture Manages i-have-adhd State Persistence

> Discover how the Pi runtime architecture manages i-have-adhd state persistence by storing and restoring the enabled state across sessions. Learn about session manager entries and lifecycle hooks.

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

---

**The Pi runtime persists the i-have-adhd mode across sessions by storing a custom entry in the session manager that records the enabled state, then restores it via lifecycle hooks when sessions start or trees rebuild.**

The **ayghri/i-have-adhd** repository implements a Pi extension that maintains user preference for ADHD-friendly formatting across conversation turns and runtime restarts. Understanding how the **Pi runtime architecture** handles this **state persistence** reveals the design patterns used for session-scoped feature flags in the Pi ecosystem.

## Defining the State Entry Structure

The extension declares a **custom entry type** named `i-have-adhd-state` (stored as the constant `STATE_ENTRY_TYPE`) to represent the persistence schema. This entry carries a simple interface recording the boolean flag `enabled`【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L22-L36】.

When the user toggles the mode via commands like `/pi i-have-adhd on` or `/pi i-have-adhd off`, the `setEnabled` function triggers persistence by calling `pi.appendEntry(STATE_ENTRY_TYPE, { enabled })`【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L73-L77】. The `appendEntry` method writes this entry into the current session’s branch, which Pi later commits to its session tree—the on‑disk or in‑memory structure that survives across restarts.

## Restoring State from the Session Tree

On session initialization or whenever Pi rebuilds the session tree (for example, after a restart), the `restoreState` function executes. It invokes `getSavedState`, which walks the session branch using `ctx.sessionManager.getBranch()` to locate and extract the latest `enabled` value from the custom entry【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L81-L95】.

If the lookup returns no saved entry, the extension falls back to a hierarchy of defaults:

- The `adhd` flag supplied at Pi launch via `pi.getFlag("adhd")`
- The `alwaysOn` flag defined in [`i-have-adhd.json`](https://github.com/ayghri/i-have-adhd/blob/main/i-have-adhd.json) (loaded via `loadConfig`)
- The presence of a sentinel file named `.i-have-adhd-always` on the filesystem【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L62-L66】【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L62-L68】

## Synchronizing Context Without Re-injection

To avoid flooding the model with duplicate instructions on every turn, the extension uses `syncContext` to verify whether the rule-set marker is already present in the model’s context via `rulesAreInContext`. When the mode is enabled but the marker is missing, the extension injects the ADHD-friendly rules via `pi.sendMessage` using `customType: RULES_MESSAGE_TYPE`. Conversely, if the mode is disabled, it injects a disabled notice. This conditional logic ensures the rules remain synchronized without redundant re-injection【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L34-L48】【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L98-L110】.

## Lifecycle Hooks Driving Persistence

The extension registers three Pi runtime events that orchestrate state persistence and synchronization:

- **`session_start`** – Triggers `restoreState` when a new session begins, ensuring the previous toggle state is active immediately.
- **`session_tree`** – Also invokes `restoreState` when Pi reconstructs the session tree, handling scenarios where the runtime restarts but the session tree is reloaded.
- **`session_compact`** – Runs `syncContext` after Pi compacts the session history, guaranteeing the rule-set marker remains current after history truncation【/cache/repos/github.com/ayghri/i-have-adhd/main/extensions/i-have-adhd.ts#L37-L40】.

## Implementation Example

When a user enables the mode, the extension persists the state explicitly:

```typescript
enabled = true;
pi.appendEntry("i-have-adhd-state", { enabled: true });

```

On a subsequent request or after a runtime restart, Pi restores the flag automatically:

```typescript
const saved = getSavedState(ctx);   // reads from sessionManager.getBranch()
enabled = saved ?? false;           // respects defaults if entry absent

```

The rule set is injected only once per session window:

```typescript
if (enabled && !rulesAreInContext(ctx)) {
  pi.sendMessage({ 
    customType: "i-have-adhd-rules", 
    content: RULES_HEADER + "\n\n" + rules 
  }, { triggerTurn: false });
}

```

## Key Files in the Architecture

- **[`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts)** – Core extension logic defining `STATE_ENTRY_TYPE`, persistence methods, and lifecycle hook registrations.
- **[`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts)** – Helper utilities including `contextMessages` and `latestMarkerIsActive` for detecting rule presence.
- **[`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md)** – Source document containing the ADHD-friendly rules injected when the mode is active.
- **[`package.json`](https://github.com/ayghri/i-have-adhd/blob/main/package.json)** – Declares the Pi runtime entry point in the `"pi"` field, loading the extension into the runtime.
- **[`scripts/check_pi_extension.py`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_pi_extension.py)** – Validates that the extension loads correctly and that state handling conforms to Pi’s persistence contract.

## Summary

- The Pi runtime architecture stores i-have-adhd state as a **custom session entry** (`i-have-adhd-state`) via `pi.appendEntry()`, ensuring durability across turns.
- **State restoration** occurs through `getSavedState` walking the session branch, with fallback defaults from CLI flags, JSON configuration, or sentinel files.
- **Context synchronization** prevents redundant rule injection by checking `rulesAreInContext` before calling `pi.sendMessage`.
- **Lifecycle hooks** (`session_start`, `session_tree`, `session_compact`) automate recovery and maintenance of the mode state without user intervention.
- The implementation in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) demonstrates the canonical pattern for session-scoped persistence in Pi extensions.

## Frequently Asked Questions

### Where does the Pi runtime physically store the i-have-adhd state?

The state is stored within Pi's **session tree** as a custom entry type. Specifically, the extension writes to the current session branch using `pi.appendEntry(STATE_ENTRY_TYPE, { enabled })`, which Pi persists in its internal session tree representation (either on‑disk or in‑memory depending on the runtime configuration) and retrieves later via `ctx.sessionManager.getBranch()`.

### How does the extension prevent the ADHD rules from being injected repeatedly?

The `syncContext` function checks `rulesAreInContext` (defined in [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts)) to detect whether the rule-set marker already exists in the model's context. Only if the mode is enabled and the marker is absent does it inject the rules via `pi.sendMessage`, ensuring the instructions appear exactly once per relevant session window.

### What happens if no previous state exists when Pi starts?

If `getSavedState` finds no `i-have-adhd-state` entry in the session branch, the extension evaluates a fallback chain: first the `adhd` launch flag (`pi.getFlag("adhd")`), then the `alwaysOn` setting in [`i-have-adhd.json`](https://github.com/ayghri/i-have-adhd/blob/main/i-have-adhd.json), and finally the presence of a `.i-have-adhd-always` sentinel file. If none are present, the mode defaults to disabled.

### Why are there two different hooks for restoring state (`session_start` and `session_tree`)?

The `session_start` hook handles fresh sessions, while `session_tree` triggers when Pi rebuilds the session tree (for example, after a runtime restart that reloads the conversation history). Registering both ensures the i-have-adhd mode is restored whether the user starts a new conversation or resumes an existing one after a restart.