# How the Always-On Hook Mechanism Works in i-have-adhd

> Discover how the always-on hook mechanism in i-have-adhd automatically injects ADHD-friendly formatting into Claude sessions. Learn more about this innovative feature for a better AI experience.

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

---

**The always-on hook mechanism automatically injects ADHD-friendly formatting rules into every Claude session by checking for an opt-in flag file and outputting the ruleset to stdout at session start.**

The `i-have-adhd` repository provides a Claude plugin designed to enforce concise, structured responses optimized for users with ADHD. The **always-on hook mechanism** ensures these formatting rules are automatically applied to every conversation without requiring manual activation, creating a seamless experience across all Claude sessions.

## Hook Registration and Event Triggers

The always-on functionality is registered in **[`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json)**, which defines a `SessionStart` event listener. This configuration matches four specific session initiation commands: `startup`, `resume`, `clear`, and `compact`.

When any of these commands trigger, Claude executes a Node.js one-liner that dynamically imports **`hooks/always-on.mjs`**. The hook definition specifies the exact command to run, ensuring the script loads only when the environment variables `CLAUDE_PLUGIN_ROOT` or `PLUGIN_ROOT` are present.

```bash
node -e "(async()=>{const root=process.env.CLAUDE_PLUGIN_ROOT||process.env.PLUGIN_ROOT;
if(root)await import(require('node:url').pathToFileURL(require('node:path')
.join(root,'hooks','always-on.mjs')).href)})().catch(()=>{})"

```

This approach uses `pathToFileURL` from the `node:url` module to correctly resolve file paths across different operating systems before importing the ECMAScript module.

## Execution Flow in always-on.mjs

The **`hooks/always-on.mjs`** script implements the core logic for the always-on hook mechanism. Upon execution, it immediately checks for the existence of an opt-in flag file at `$CLAUDE_CONFIG_DIR/.i-have-adhd-always`, defaulting to `~/.claude/.i-have-adhd-always` if the environment variable is unset.

If the flag file is absent, the script exits silently via `process.exit(0)`, ensuring zero impact on users who have not opted in. This check prevents any performance overhead or blocking behavior for standard Claude sessions.

When the flag is present, the script resolves the absolute path to **[`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md)** relative to its own location, not the current working directory. It reads the file contents, strips any YAML front-matter delimiters (`---`), and constructs the output payload.

## Loading and Injecting the Ruleset

The script outputs a banner message followed by the complete ADHD-friendly ruleset to `stdout`. The output format includes:

```

ADHD MODE ACTIVE (always-on). The ruleset below applies to every response.
"stop adhd mode" turns it off for this session; delete /home/user/.claude/.i-have-adhd-always
to turn always-on off for good.

<rules ...>

```

Claude’s runtime captures this stdout output and prepends it to every response generated during the session. This injection happens at the system level, ensuring the constraints defined in [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md)—such as short paragraphs, bullet points, and structured formatting—are enforced automatically without user intervention.

## Practical Usage: Enable, Disable, and Verify

Users control the always-on hook mechanism through filesystem operations and natural language commands.

**Enable always-on mode permanently:**

```bash
mkdir -p ~/.claude
touch ~/.claude/.i-have-adhd-always

```

**Disable for the current session only:**

Type `stop adhd mode` in any Claude conversation. This command is recognized by the runtime and suppresses the ruleset for that specific session without removing the flag file.

**Disable permanently:**

```bash
rm ~/.claude/.i-have-adhd-always

```

When enabled, every session start displays the activation banner, confirming that the ADHD-friendly formatting rules are active and will apply to all subsequent responses.

## Safety Features and Error Handling

The always-on hook mechanism is designed with fail-safe principles to prevent disruption to Claude sessions. All file path resolutions in `always-on.mjs` are calculated relative to the script’s directory using `__dirname` and `node:path` joins, eliminating dependency on the process working directory.

Any errors encountered during file reading, path resolution, or output generation are caught by the outer try-catch block, which terminates the process with `process.exit(0)`. This guarantees that a corrupted ruleset, missing skill file, or permission error will never prevent a Claude session from starting. The **[`tests/test_always_on_hooks.py`](https://github.com/ayghri/i-have-adhd/blob/main/tests/test_always_on_hooks.py)** file validates this behavior, ensuring the hook exits cleanly both when the flag is absent and when errors occur during execution.

## Summary

- The **always-on hook mechanism** is registered in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) under the `SessionStart` event, triggering on `startup`, `resume`, `clear`, and `compact` commands.
- It executes `hooks/always-on.mjs`, which checks for the opt-in flag at `~/.claude/.i-have-adhd-always` before proceeding.
- When enabled, it reads [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md), strips YAML front-matter, and outputs the rules to stdout for Claude to prepend to responses.
- Users enable the feature by creating the flag file, disable it temporarily with "stop adhd mode", or remove the file for permanent deactivation.
- The implementation includes comprehensive error handling that always exits with code 0, ensuring session start is never blocked.

## Frequently Asked Questions

### What file activates the always-on hook mechanism?

The presence of **`~/.claude/.i-have-adhd-always`** (or `$CLAUDE_CONFIG_DIR/.i-have-adhd-always`) acts as the opt-in flag. The script `hooks/always-on.mjs` checks for this file at runtime; if it exists, the ADHD ruleset is injected into the session.

### How do I disable the always-on hook temporarily?

Type **`stop adhd mode`** in any active Claude session. This natural language command instructs Claude to ignore the always-on ruleset for that specific conversation without deleting the flag file, allowing you to restore the behavior in the next session.

### Where are the ADHD-friendly rules stored?

The source rules are defined in **[`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md)**. The always-on script reads this file dynamically at session start, strips any YAML front-matter, and outputs the content. Modifying this file changes the behavior of all future sessions where the always-on hook is active.

### What happens if the always-on script encounters an error?

The script is wrapped in a try-catch block that calls `process.exit(0)` on any exception. This design ensures that filesystem errors, missing dependencies, or corrupted skill files will never block Claude from starting a session, maintaining system stability even when the hook fails.