# How the Always-On Mechanism Works in i-have-adhd: A Technical Deep Dive

> Uncover the technical workings of the always-on mechanism in I-Have-ADHD. Learn how this feature injects rules into every session for consistent AI assistance.

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

---

**The always-on mechanism injects the full i-have-adhd ruleset into every Claude/Codex session by checking for a `.i-have-adhd-always` flag file at startup, then stripping YAML front-matter from [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) and writing the processed rules to stdout via a SessionStart hook.**

The always-on mechanism in ayghri/i-have-adhd provides persistent ADHD-friendly formatting across all AI coding sessions without requiring manual activation commands. This feature operates through a lightweight SessionStart hook architecture that detects user opt-in status via filesystem flags and dynamically injects behavioral rules before the model generates responses. Understanding this implementation reveals how cross-platform shell scripts and Node.js modules collaborate to ensure seamless session customization.

## Opt-In Flag Detection System

The always-on mechanism uses a simple filesystem-based toggle to respect user consent. The hook checks for a hidden flag file named `.i-have-adhd-always` inside the Claude configuration directory, defaulting to `~/.claude` unless overridden by the `CLAUDE_CONFIG_DIR` environment variable.

In `hooks/always-on.mjs`, the flag path is constructed using Node.js path utilities:

```javascript
const claudeDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), ".claude");
const flagPath = path.join(claudeDir, ".i-have-adhd-always");

```

*(see [always‑on.mjs line 16‑18](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.mjs#L16-L18))*

If the flag file does **not** exist, the hook exits silently without modifying the session:

```javascript
if (!fs.existsSync(flagPath)) process.exit(0);

```

*(see [always‑on.mjs line 20](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.mjs#L20))*

This early return ensures zero overhead for users who have not opted into the always-on mechanism.

## SessionStart Hook Architecture

The i-have-adhd repository implements the always-on mechanism as a **SessionStart hook** registered in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json). This declarative configuration tells Claude Code (and compatible runtimes) to execute specific scripts before generating the first response in any session.

The architecture provides three platform-specific implementations:

- **Node.js** (`hooks/always-on.mjs`) – Primary implementation for modern environments
- **POSIX Shell** ([`hooks/always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.sh)) – Fallback for Unix-like systems without Node
- **PowerShell** (`hooks/always-on.ps1`) – Native support for Windows environments

All three scripts perform identical logic: check the flag, locate [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md), strip front-matter, and inject the ruleset with a banner message.

## Node.js Hook Implementation

The primary always-on mechanism resides in `hooks/always-on.mjs`, which handles path resolution, file processing, and stdout injection.

### Locating the Ruleset

When the flag is present, the script resolves the canonical skill definition relative to its own location, avoiding untrusted environment variables:

```javascript
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const skillPath = path.join(scriptDir, "..", "skills", "i-have-adhd", "SKILL.md");

```

*(see [always‑on.mjs line 23‑25](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.mjs#L23-L25))*

### Processing SKILL.md

The hook reads the skill file and performs two critical text transformations:

1. **Strip YAML front-matter** – Removes metadata blocks delimited by `---`
2. **Trim trailing newlines** – Ensures clean output formatting

```javascript
const body = fs.readFileSync(skillPath, "utf8")
    .replace(/^---[^\S\r\n]*\r?\n[\s\S]*?\r?\n---[^\S\r\n]*(?:\r?\n|$)/, "")
    .replace(/(?:\r?\n)+$/, "");

```

*(see [always‑on.mjs line 27‑34](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.mjs#L27-L34))*

The regex pattern `^---[^\S\r\n]*\r?\n[\s\S]*?\r?\n---[^\S\r\n]*(?:\r?\n|$)` specifically targets YAML front-matter while preserving the actual content rules.

### Injecting the Ruleset

Finally, the processed rules are written to stdout with an explanatory banner that informs users how to disable the mode:

```javascript
process.stdout.write(
  "ADHD MODE ACTIVE (always‑on). The ruleset below applies to every response. " +
  '"stop adhd mode" turns it off for this session; ' +
  `delete ${flagPath} to turn always‑on off for good.\n\n${body}\n`
);

```

*(see [always‑on.mjs line 36‑40](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.mjs#L36-L40))*

## Cross-Platform Fallback Scripts

To ensure the always-on mechanism works across diverse development environments, the repository includes shell script fallbacks that mirror the Node.js logic.

### POSIX Implementation

The [`always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/always-on.sh) script performs the same flag check using standard shell utilities:

```bash
claude_dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
flag_path="$claude_dir/.i-have-adhd-always"
[ -f "$flag_path" ] || exit 0

```

*(see [always‑on.sh line 9‑14](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.sh#L9-L14))*

The script uses `printf` and `awk` to strip front-matter and output the ruleset, ensuring compatibility with minimal dependencies.

### PowerShell Implementation

Windows environments execute `always-on.ps1`, which implements identical path resolution and string manipulation using PowerShell cmdlets, maintaining feature parity across operating systems.

## Safety and Error Handling

A critical design requirement of the always-on mechanism is that it **never blocks** session initialization. All implementations include defensive programming:

- **Node.js**: Logic wrapped in `try`/`catch` blocks with silent failure
- **Shell scripts**: Explicit `exit 0` commands ensure the process terminates successfully even if file operations fail
- **Graceful degradation**: If [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) is missing or corrupted, the hook exits without crashing the Claude/Codex session

This fail-safe approach ensures that filesystem permissions issues or missing dependencies cannot prevent users from accessing their AI assistant.

## Enabling and Disabling Always-On Mode

Users control the always-on mechanism through simple filesystem commands:

```bash

# Enable always-on permanently

touch ~/.claude/.i-have-adhd-always

# Check status

ls ~/.claude/.i-have-adhd-always

# Disable for current session only (type in chat)

"stop adhd mode"

# Disable permanently

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

```

The `CLAUDE_CONFIG_DIR` environment variable allows customization of the configuration directory location for non-standard installations.

## Summary

- The always-on mechanism uses a **filesystem flag** (`.i-have-adhd-always`) in the Claude config directory to determine whether to activate
- **SessionStart hooks** in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) trigger the injection logic before every session begins
- The **Node.js implementation** in `hooks/always-on.mjs` strips YAML front-matter from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and outputs the ruleset to stdout
- **Cross-platform fallbacks** ([`always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/always-on.sh) and `always-on.ps1`) ensure consistent behavior across Unix and Windows systems
- **Fail-safe design** guarantees that hook failures never prevent session initialization, using `try`/`catch` and explicit `exit 0` commands

## Frequently Asked Questions

### How do I enable the always-on mechanism in i-have-adhd?

Create an empty flag file at `~/.claude/.i-have-adhd-always` (or `$CLAUDE_CONFIG_DIR/.i-have-adhd-always`). The SessionStart hook detects this file at the beginning of every Claude/Codex session and automatically injects the ADHD-friendly ruleset from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md).

### Why does the always-on mechanism strip YAML front-matter from SKILL.md?

The hook removes YAML front-matter (content between `---` delimiters) because the injected ruleset must contain only the behavioral instructions for the AI model, not metadata. The regex pattern in `always-on.mjs` lines 27-34 specifically targets these delimiters to ensure clean injection into the session context.

### Can I temporarily disable always-on mode without deleting the flag file?

Yes. During any active session, typing `"stop adhd mode"` instructs the model to ignore the always-on ruleset for that specific conversation. However, the next new session will re-inject the rules unless you permanently disable the feature by deleting the `.i-have-adhd-always` flag file.

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

The hook is designed to fail silently. Both the Node.js implementation and shell script fallbacks use defensive error handling—`try`/`catch` blocks in JavaScript and explicit `exit 0` commands in shell scripts—to ensure that filesystem errors or missing dependencies never block your ability to start a Claude/Codex session.