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

The /i-have-adhd command is registered in Pi via the pi.registerCommand() method defined in 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 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. 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.

// 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 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.
// 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 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 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 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. 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 (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 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →