# Understanding the i-have-adhd Pre-Send Check for Output Cleanup

> Discover the i-have-adhd pre-send check. Learn how this hook automatically cleans output by stripping YAML front-matter and adding a formatted banner to responses.

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

---

**The i-have-adhd pre-send check is a conditional hook that strips YAML front-matter from the ruleset file and injects a formatted banner into every response when users opt in via a flag file.**

The `ayghri/i-have-adhd` repository implements a specialized pre-send hook that activates at the start of every Claude Code session. This i-have-adhd pre-send check for output cleanup ensures that users receive a clean, metadata-free version of the ADHD-friendly ruleset by processing the [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) file before it reaches the interface.

## How the Pre-Send Check Works

The hook operates through a three-stage pipeline that validates user consent, processes the content, and formats the output.

### Opt-In Detection via Flag File

The pre-send check only executes when a user explicitly creates an opt-in flag. The hook looks for `.i-have-adhd-always` in the Claude configuration directory (default: `~/.claude/.i-have-adhd-always`).

In the POSIX shell implementation at [`hooks/always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.sh), the detection uses a simple file test:

```sh
[ -f "$flag_path" ] || exit 0

```

The Node.js version at `hooks/always-on.mjs` performs the same check using the filesystem module:

```javascript
const flagPath = path.join(claudeDir, ".i-have-adhd-always");
if (!fs.existsSync(flagPath)) process.exit(0);

```

If the flag file is absent, the hook exits silently and allows normal operation.

### Front-Matter Stripping Logic

Once activated, the hook loads [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and removes any leading YAML front-matter blocks. The cleanup logic specifically targets content between opening and closing `---` delimiters.

The Node implementation uses a regex pattern to detect and remove these blocks:

```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)+$/, "");

```

The POSIX `sh` version uses `awk` for two-pass detection to ensure the closing delimiter exists before stripping:

```sh
body=$(awk '
  NR == FNR {
    if (NR == 1 && $0 ~ /^---[[:space:]]*$/) { in_fm = 1; next }
    if (in_fm && $0 ~ /^---[[:space:]]*$/)   { in_fm = 0; closed = 1 }
    next
  }
  FNR == 1 { strip = closed }
  strip && FNR == 1 && $0 ~ /^---[[:space:]]*$/ { skipping = 1; next }
  skipping && $0 ~ /^---[[:space:]]*$/          { skipping = 0; next }
  !skipping { print }
' "$skill_path" "$skill_path")

```

If the closing `---` delimiter is missing, the hook preserves the entire file unchanged to prevent data loss.

### Cross-Runtime Implementation

To support Claude Code across different environments, the i-have-adhd pre-send check is implemented in three distinct runtimes:

- **Node.js** (`hooks/always-on.mjs`): JavaScript implementation for Node-based environments
- **POSIX Shell** ([`hooks/always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.sh)): Bourne shell script for Unix-like systems
- **PowerShell** (`hooks/always-on.ps1`): Windows PowerShell implementation mirroring the same logic

Each implementation resolves the [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) path relative to the hook script location, avoiding dependencies on environment variables.

## Implementation Details by Runtime

### Node.js Implementation (always-on.mjs)

Located at `hooks/always-on.mjs`, the Node version handles path resolution and regex-based cleanup:

```javascript
// Resolve flag file
const flagPath = path.join(claudeDir, ".i-have-adhd-always");
if (!fs.existsSync(flagPath)) process.exit(0);

// Load SKILL.md and strip front-matter
const body = fs.readFileSync(skillPath, "utf8")
  .replace(/^---[^\S\r\n]*\r?\n[\s\S]*?\r?\n---[^\S\r\n]*(?:\r?\n|$)/, "")
  .replace(/(?:\r?\n)+$/, "");

// Write banner + cleaned rules
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`
);

```

### POSIX Shell Implementation (always-on.sh)

The [`hooks/always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.sh) script provides a lightweight alternative using standard Unix utilities:

```sh

# Detect opt‑in flag

[ -f "$flag_path" ] || exit 0

# Strip leading YAML front-matter

body=$(awk '
  NR == FNR {
    if (NR == 1 && $0 ~ /^---[[:space:]]*$/) { in_fm = 1; next }
    if (in_fm && $0 ~ /^---[[:space:]]*$/)   { in_fm = 0; closed = 1 }
    next
  }
  FNR == 1 { strip = closed }
  strip && FNR == 1 && $0 ~ /^---[[:space:]]*$/ { skipping = 1; next }
  skipping && $0 ~ /^---[[:space:]]*$/          { skipping = 0; next }
  !skipping { print }
' "$skill_path" "$skill_path") || exit 0

# Emit banner + cleaned rules

printf 'ADHD MODE ACTIVE (always‑on). The ruleset below applies to every response. "stop adhd mode" turns it off for this session; delete %s to turn always‑on off for good.\n\n%s\n' \
  "$flag_path" "$body"

```

### PowerShell Implementation (always-on.ps1)

The `hooks/always-on.ps1` file provides equivalent functionality for Windows environments, performing the same front-matter detection and banner injection pattern.

## Hook Configuration and Registration

The pre-send check is registered through [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json), which declares the `SessionStart` hook that triggers the cleanup script. This configuration ensures the hook runs automatically at the beginning of every Claude Code session when the flag file is present.

The hook script resolves the [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) file path relative to its own location, ensuring portability across different installation directories without requiring specific environment variables.

## Testing and Validation

The repository includes comprehensive tests in [`tests/test_always_on_hooks.py`](https://github.com/ayghri/i-have-adhd/blob/main/tests/test_always_on_hooks.py) that verify two critical behaviors:

- **Opt-in validation**: Confirms the hook only fires when `$CLAUDE_CONFIG_DIR/.i-have-adhd-always` exists
- **Front-matter stripping**: Validates that YAML blocks delimited by `---` are correctly removed while preserving the ruleset body

These tests ensure consistent behavior across all three runtime implementations.

## Summary

- The **i-have-adhd pre-send check** is a `SessionStart` hook that runs at the beginning of every Claude Code session when users create the opt-in flag file.
- It **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) by detecting opening and closing `---` delimiters, preserving the file unchanged if the closing delimiter is absent.
- The hook is implemented in **three runtimes** (Node.js, POSIX `sh`, and PowerShell) to ensure cross-platform compatibility.
- It **injects a banner** informing users that ADHD mode is active and providing instructions to disable it for the current session or permanently.
- All functionality is validated by [`tests/test_always_on_hooks.py`](https://github.com/ayghri/i-have-adhd/blob/main/tests/test_always_on_hooks.py), which verifies both the opt-in mechanism and the output cleanup logic.

## Frequently Asked Questions

### How do I enable the i-have-adhd pre-send check?

Create an empty file named `.i-have-adhd-always` in your Claude configuration directory (typically `~/.claude/`). The hook automatically detects this file at session start and begins injecting the cleaned ruleset into every response. Remove the file to disable the always-on mode permanently.

### What happens if the SKILL.md file has unclosed front-matter delimiters?

The hook implements safety checks to prevent data loss. In the POSIX implementation, the `awk` script verifies that a closing `---` delimiter exists before stripping any content. If the closing delimiter is missing, the `closed` variable remains false, and the entire file contents are preserved and passed through unchanged.

### Can I temporarily disable ADHD mode for a single session without deleting the flag file?

Yes. The banner injected by the pre-send check includes instructions to type "stop adhd mode" to disable the mode for the current session. This allows you to suppress the ruleset injection temporarily while keeping the `.i-have-adhd-always` flag file in place for future sessions.

### Where is the pre-send hook configured to run automatically?

The hook registration is defined in [`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json), which declares the `SessionStart` event that triggers the appropriate script (`always-on.mjs`, [`always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/always-on.sh), or `always-on.ps1`) based on your runtime environment. This configuration ensures the i-have-adhd pre-send check executes automatically without manual intervention once the opt-in flag is present.