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

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 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, the detection uses a simple file test:

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

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

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 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:

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:

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): 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 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:

// 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 script provides a lightweight alternative using standard Unix utilities:


# 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, 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 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 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 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, 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, which declares the SessionStart event that triggers the appropriate script (always-on.mjs, 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.

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 →