# How the /i-have-adhd Command Is Registered in Pi: Extension API Deep Dive

> Discover how the /i-have-adhd command registers in Pi using the Extension API. Learn how pi.registerCommand() enables ADHD-friendly responses by managing rulesets.

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

---

**The `/i-have-adhd` command is registered in Pi via the `pi.registerCommand()` method defined in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), which binds the slash command to a handler that toggles ADHD-friendly response rules by injecting or removing the ruleset from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) via state management APIs.**

The `ayghri/i-have-adhd` repository provides a Pi extension that dynamically modifies assistant output style for ADHD accessibility. Understanding the `/i-have-adhd` command registration requires analyzing how the Pi extension API exposes user-facing slash commands and manages conversation state. The implementation centers on a single registration call that configures metadata, usage patterns, and stateful handler logic.

## The Registration Entry Point in extensions/i-have-adhd.ts

According to the ayghri/i-have-adhd source code, the command registration occurs at **line 187** inside [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts). During extension initialization, the code invokes the global `pi` runtime object to expose the command to the Pi user interface.

The registration uses the `pi.registerCommand()` method with two arguments: the command identifier string (`"i-have-adhd"`) and a configuration object containing the handler implementation and metadata.

```typescript
// extensions/i-have-adhd.ts (line 187)
pi.registerCommand("i-have-adhd", {
  description: "Toggle ADHD-friendly response mode",
  usage: "/i-have-adhd [on|off]",
  handler: async (input) => {
    // Handler implementation detailed below
  },
});

```

## Anatomy of the Command Configuration Object

The configuration object passed to `pi.registerCommand()` defines three required properties that control how Pi interprets and displays the slash command.

### Metadata and Usage Strings

- **`description`**: Provides the help text displayed in Pi’s command palette UI ("Toggle ADHD-friendly response mode").
- **`usage`**: Defines the expected argument pattern (`"/i-have-adhd [on|off]"`), which Pi uses for input validation and autocomplete hints.

### The Handler Implementation

The `handler` function receives the full command string as its `input` parameter and executes the toggle logic. The implementation performs three critical operations:

1. **Alias Normalization**: Converts the alternative invocation `/skill:i-have-adhd` into `/i-have-adhd on` to ensure consistent state management.
2. **State Injection**: When enabling, it loads the ruleset from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and calls `pi.addState(STATE_ENTRY_TYPE, rules)` to inject behavioral instructions into the conversation context.
3. **State Removal**: When disabling via `/i-have-adhd off`, it calls `pi.removeState(STATE_ENTRY_TYPE)` to strip the ruleset and restore default response formatting.

```typescript
// Handler logic inside pi.registerCommand (simplified)
handler: async (input) => {
  // Normalize alias: "/skill:i-have-adhd" becomes "/i-have-adhd on"
  if (input === "/skill:i-have-adhd") input = "/i-have-adhd on";

  if (input === "/i-have-adhd off") {
    // Disable ADHD mode
    pi.removeState(STATE_ENTRY_TYPE);
    ctx.ui.notify("ADHD mode disabled.", "info");
  } else {
    // Enable ADHD mode
    const rules = await loadRulesFromSkill();
    pi.addState(STATE_ENTRY_TYPE, rules);
    ctx.ui.notify("ADHD mode enabled.", "info");
  }
}

```

## State Management Architecture

The extension uses **Pi’s state API** to persist the ADHD ruleset across conversation turns. The `STATE_ENTRY_TYPE` constant identifies the specific state entry containing the loaded skill content.

- **`pi.addState()`**: Dynamically injects the contents of [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) into the conversation state, causing Pi to apply the ADHD-friendly formatting rules to all subsequent responses.
- **`pi.removeState()`**: Clears the state entry, effectively uninstalling the behavioral modifications without reloading the extension.

This approach allows the toggle to take effect immediately without requiring a session restart.

## Supporting Infrastructure

### Plugin Manifest (plugin.json)

The [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) file at the repository root declares the extension entry point and metadata required for Pi to load the plugin. It identifies [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) as the primary extension file containing the `pi.registerCommand()` call.

### Skill Definition (SKILL.md)

The actual behavioral modifications—the specific instructions that reshape Pi’s output for ADHD accessibility—reside in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). The handler loads this file asynchronously via `loadRulesFromSkill()` and passes the content to `pi.addState()`.

### Always-On Hooks (hooks/always-on.mjs)

The repository includes `hooks/always-on.mjs`, which implements the `.i-have-adhd-always` flag. This hook checks for persistent user preferences and can automatically trigger the equivalent of `/i-have-adhd on` at session initialization, bypassing the need for manual command invocation.

## Summary

- **`pi.registerCommand()`** in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) (line 187) creates the user-facing `/i-have-adhd` slash command.
- The **handler function** toggles ADHD mode by calling `pi.addState()` to inject rules or `pi.removeState()` to remove them.
- **Rules are sourced** from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and loaded dynamically when enabling the mode.
- The command supports the **`/skill:i-have-adhd` alias**, which normalizes to the "on" state.
- **Always-on functionality** is implemented separately in `hooks/always-on.mjs` using the `.i-have-adhd-always` flag.

## Frequently Asked Questions

### What file contains the /i-have-adhd command registration?

The registration is defined in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) at line 187, where the code calls `pi.registerCommand("i-have-adhd", { ... })` to bind the command name to its handler and metadata.

### How does the command toggle ADHD mode on and off?

The handler checks the input string. If it matches `/i-have-adhd off`, it calls `pi.removeState(STATE_ENTRY_TYPE)` to strip the ruleset. For any other valid input (including the alias), it loads [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and calls `pi.addState(STATE_ENTRY_TYPE, rules)` to inject the behavioral instructions into the conversation context.

### What is the difference between /i-have-adhd and /skill:i-have-adhd?

`/skill:i-have-adhd` is an alias that the handler normalizes to `/i-have-adhd on`. Both commands enable ADHD mode, but the alias provides a namespaced alternative that some Pi configurations recognize for skill-specific invocations.

### How does the always-on functionality work without typing the command?

The `hooks/always-on.mjs` file monitors for the `.i-have-adhd-always` flag in user settings. When this flag is present, the hook automatically executes the state injection logic at session start, effectively enabling ADHD mode before the user sends the first message.