# i‑Have‑ADHD Extension Hooks: session_start, session_tree, and Full Lifecycle Registration

> Discover the i-have-adhd extension's registered hooks: session_start, session_tree, session_compact, and input. Learn about its full lifecycle registration for enhanced productivity.

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

---

**The i‑have‑adhd extension registers four Pi‑coding‑agent hooks: `session_start`, `session_tree`, `session_compact`, and `input`, plus a global `SessionStart` command for always‑on mode.**

The i‑have‑adhd extension for Pi‑coding‑agent manages ADHD‑friendly response rules across conversation lifecycles by hooking into key session events. Understanding which hooks this extension registers helps developers debug state synchronization issues, extend the plugin, or build similar extensions that persist user preferences across session restores and compactions.

## session_start Hook: Restoring State on Session Creation

The **`session_start`** hook fires at the beginning of any new session or when a session is restored from storage. In [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) lines 193‑194, the extension restores the saved ADHD‑mode state—or falls back to the default/always‑on flag—and immediately updates the UI status bar.

This hook ensures users don't lose their preferred mode between conversations. The implementation checks persistent storage for a previous toggle state, then calls the internal `updateStatus()` method to reflect the current mode in the interface.

**Code location:** [`extensions/i-have-adhd.ts:193‑194`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts#L193-L194)

## session_tree Hook: Handling Tree Rebuilds

The **`session_tree`** hook triggers whenever the session tree is rebuilt, which occurs after resume operations or when the context is cleared. Lines 199‑200 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) execute identical restoration logic to `session_start`.

Tree rebuilds can orphan extension state because the entire conversation structure is reconstructed from serialized data. By re‑registering this hook separately from `session_start`, the extension handles edge cases where a session persists but its tree representation changes mid‑conversation.

**Code location:** [`extensions/i-have-adhd.ts:199‑200`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts#L199-L200)

## session_compact Hook: Re‑injecting Rules After Summarization

The **`session_compact`** hook responds to session compaction events where older messages are summarized to conserve context window space. Lines 207‑208 of [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) re‑inject the ADHD rules if the mode remains enabled.

This is critical because compaction drops custom metadata markers that the extension uses to track whether rules are active. Without this hook, users would silently lose ADHD‑friendly formatting after their conversation grows long enough to trigger automatic summarization.

**Code location:** [`extensions/i-have-adhd.ts:207‑208`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts#L207-L208)

## input Hook: Command Detection and Mode Toggling

The **`input`** hook runs on every user message and serves two purposes in lines 193‑221:

- **Legacy command detection:** Recognizes `/skill:i-have-adhd` to enable the mode
- **Stop phrase handling:** Detects "stop adhd mode" or "normal mode" to disable it, optionally returning a confirmation response

Unlike the other hooks that manage state persistence, `input` provides the interactive control surface. The hook parses message content before it reaches the main agent loop, allowing immediate mode switches without polluting the conversational context with command syntax.

**Code location:** [`extensions/i-have-adhd.ts:193‑221`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts#L193-L221)

## Global SessionStart Command: Always‑On Mode

Beyond the extension's own hooks, the repository declares a **global `SessionStart` command** in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) lines 4‑13. This command executes a Node script that imports `hooks/always-on.mjs` when the environment variable `CLAUDE_PLUGIN_ROOT` or `PLUGIN_ROOT` points to the plugin directory.

The script checks for the hidden flag file `.i-have-adhd-always`. If present, it triggers the extension to start with ADHD‑mode enabled regardless of previous session state. This provides system‑level configuration for users who always want ADHD‑friendly responses.

**Code location:** [`hooks/hooks.json:4‑13`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json#L4-L13)

## Hook Execution Order and Interaction

The hooks execute in predictable sequences depending on user actions:

| Scenario | Hooks Fired | Result |
|----------|-------------|--------|
| New conversation | `SessionStart` (global) → `session_start` | Always‑on check, then state restoration |
| Restore from storage | `session_start` | Previous mode restored |
| Tree rebuild after clear | `session_tree` | Mode re‑applied to fresh tree |
| Long conversation compaction | `session_compact` | Rules re‑injected after summarization |
| User types toggle command | `input` | Immediate mode change |

## Working with the Hook System Programmatically

Enable ADHD mode from another plugin using the ExtensionAPI:

```typescript
// Assuming `pi` is the ExtensionAPI instance
pi.sendMessage({
  customType: "i-have-adhd-enabled",
  content: "ADHD mode activated",
  display: false,
});

```

Manually emit a session‑start hook for testing:

```typescript
await pi.emit("session_start", {});

```

Check whether rules are currently active in context:

```typescript
import { contextMessages, latestMarkerIsActive } from "./context-compat";

const haveRules = latestMarkerIsActive(
  contextMessages(ctx.sessionManager),
  "i-have-adhd-rules",
  "i-have-adhd-disabled"
);

```

Toggle via built‑in command:

```typescript
// In chat
/i-have-adhd on   // enable
/i-have-adhd off  // disable

```

## Key Source Files

| File | Purpose |
|------|---------|
| [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) | Core extension; registers `session_start`, `session_tree`, `session_compact`, `input` |
| [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) | Global `SessionStart` command declaration |
| `hooks/always-on.mjs` | Flag‑file check implementation |
| [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) | Helper utilities: `contextMessages`, `latestMarkerIsActive` |
| [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) | Actual ADHD‑friendly rule definitions |

## Summary

- **Four lifecycle hooks:** `session_start`, `session_tree`, `session_compact`, and `input` manage state across the full session lifecycle
- **Persistence guarantee:** `session_start` and `session_tree` ensure mode survives restores and rebuilds
- **Compaction safety:** `session_compact` re‑injects rules after context summarization
- **Interactive control:** `input` handles real‑time command and phrase detection
- **System‑level override:** Global `SessionStart` command enables always‑on mode via `.i-have-adhd-always` flag file
- **Implementation files:** All hooks defined in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) with global command in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json)

## Frequently Asked Questions

### What is the difference between session_start and SessionStart hooks?

`session_start` (lowercase) is the extension‑internal hook registered in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) that restores saved state. `SessionStart` (capitalized) is the global framework command declared in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) that runs external scripts before any extension loads. The global command checks for always‑on mode; the internal hook handles per‑session state restoration.

### Why does the extension need both session_start and session_tree?

`session_start` fires on session creation or restore, while `session_tree` fires when the conversation tree is rebuilt without creating a new session. Tree rebuilds occur after context clears or certain resume operations that preserve session metadata but reconstruct the message structure. Separate hooks ensure state synchronization in both cases.

### How does session_compact prevent rule loss?

Session compaction summarizes older messages to save context window space, which strips custom metadata markers the extension uses to track active rules. The `session_compact` hook detects this operation and re‑injects the ADHD rule set from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) if the mode remains enabled, ensuring continuous formatting without user intervention.

### Can I trigger these hooks manually for testing?

Yes. Use `await pi.emit("session_start", {})` or similar with the ExtensionAPI instance. The `input` hook accepts raw message objects, and `session_compact` can be simulated by calling the compaction API directly. However, `SessionStart` (global) requires actual framework initialization and cannot be triggered from within an active session.