How Always-On Injection Works in i-have-ADHD Across Node, Shell, and PowerShell Harnesses
The i-have-adhd repository implements always-on injection through environment-specific session-start hooks—Node.js modules for JavaScript-based runtimes, POSIX shell scripts for minimal containers, and PowerShell for Windows—each loading the ADHD ruleset when the opt-in flag file exists.
The open-source project ayghri/i-have-adhd delivers consistent ADHD behavioral modifications across multiple AI coding assistants by adapting its always-on injection mechanism to the interpreter capabilities of each runtime harness. When a user opts in by creating the hidden flag file, the system selects the appropriate script to inject rules from skills/i-have-adhd/SKILL.md without requiring Node.js on every platform.
Node.js Harnesses: Claude Code, Codex, and npm-Based Runtimes
Claude Code, Codex, Pi, OMP, and OpenCode all utilize the same Node.js implementation for always-on injection, as they execute within JavaScript-capable environments.
Hook Implementation in always-on.mjs
The primary hook resides in hooks/always-on.mjs. It imports Node's fs, os, and path modules to resolve the flag file at $CLAUDE_CONFIG_DIR/.i-have-adhd-always (defaulting to ~/.claude/.i-have-adhd-always). When the flag exists, the script reads skills/i-have-adhd/SKILL.md, strips the leading YAML front-matter using regex, and writes the cleaned rules to stdout.
Error resilience is built into the Node implementation: any error—whether a missing flag file, missing skill file, or unexpected exception—triggers process.exit(0), ensuring the session start never fails due to hook errors.
Manifest-Driven Execution
Each Node-based harness references the hook through hooks/hooks.json, which points to always-on.mjs. Claude Code's plugin runtime invokes the script directly with Node, enabling cross-platform support for macOS, Linux, and Windows without shell-specific translation. Pi and OMP load the identical module through their npm-based entry points and TypeScript extensions, while OpenCode reads opencode.json to execute the same script under Node.
POSIX Shell Fallback for Minimal Environments
When Node.js is unavailable—as in minimal Linux containers or Git Bash on Windows—the harness falls back to hooks/always-on.sh.
Pure POSIX Compatibility
This implementation uses pure POSIX-compatible sh syntax. It determines the script's location using the absolute path substitution via $0 (provided by Claude Code in hooks.json) to compute script_dir and locate SKILL.md at ../skills/i-have-adhd/SKILL.md relative to the hook's directory.
Front-Matter Stripping with awk
The shell script implements a two-pass awk routine that removes leading --- … --- blocks only when a closing delimiter exists, mirroring the regex behavior of the Node version. It outputs a banner and the cleaned rule body using printf for consistent formatting across different shell implementations.
PowerShell Fallback for Windows
For pure Windows environments without Node, hooks/always-on.ps1 provides native PowerShell support.
The script follows the same logical flow as the Node and shell versions: it checks for the flag file, resolves the skill file path relative to $MyInvocation.MyCommand.Path, strips front-matter with a regular expression, and writes the rules to the console. This ensures always-on injection works in locked-down Windows environments where only PowerShell is available.
Opt-In Flag and Cross-Platform Consistency
All harnesses share the identical opt-in mechanism. Create the hidden flag file to activate always-on mode:
# POSIX/Linux/macOS
mkdir -p "${HOME}/.claude"
touch "${HOME}/.claude/.i-have-adhd-always"
# Windows PowerShell
$claudeDir = "$env:USERPROFILE\.claude"
New-Item -ItemType Directory -Path $claudeDir -Force
New-Item -ItemType File -Path "$claudeDir\.i-have-adhd-always" -Force
Once active, every session start invokes the appropriate hook, printing a banner like:
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.
The system guarantees consistent rule content across platforms while allowing each runtime to use the most reliable interpreter available.
Summary
- Node.js harnesses (Claude Code, Codex, Pi, OMP, OpenCode) use
hooks/always-on.mjswithprocess.exit(0)error handling and YAML front-matter regex stripping. - POSIX shell fallback (
hooks/always-on.sh) uses$0path resolution and two-passawkfront-matter removal for minimal environments. - PowerShell fallback (
hooks/always-on.ps1) uses$MyInvocation.MyCommand.Pathfor native Windows support without Node. - All implementations read from
skills/i-have-adhd/SKILL.mdand check for$CLAUDE_CONFIG_DIR/.i-have-adhd-always(default~/.claude/.i-have-adhd-always). - The
hooks/hooks.jsonmanifest directs each harness to the appropriate script based on runtime capabilities.
Frequently Asked Questions
What file triggers always-on injection in i-have-adhd?
The hidden flag file .i-have-adhd-always within the Claude configuration directory triggers the injection. By default, the system looks for this file at ~/.claude/.i-have-adhd-always, though it respects the $CLAUDE_CONFIG_DIR environment variable when set. All harness implementations check for this file's existence before loading rules from skills/i-have-adhd/SKILL.md.
Why does the Node hook use process.exit(0) on errors?
The process.exit(0) call in hooks/always-on.mjs ensures that session startup never fails due to hook issues. If the flag file is missing, the skill file is unreadable, or an unexpected exception occurs, the hook exits cleanly with code 0, allowing the AI assistant to start normally without the ADHD ruleset rather than crashing the session.
How does the POSIX shell version strip YAML front-matter without regex?
The hooks/always-on.sh script uses a two-pass awk routine that tracks whether it is inside a front-matter block (delimited by ---). It skips content between opening and closing delimiters only when both exist, effectively stripping the YAML header while preserving the markdown content—functionally equivalent to the regex approach in the Node version but compatible with POSIX awk implementations.
Which harness implementations share the same hook code?
Claude Code, Codex, Pi, OMP, and OpenCode all execute the same hooks/always-on.mjs script because they run on Node.js-based platforms. The Pi and OMP extensions reference this module through their TypeScript entry points, while OpenCode loads it via opencode.json, but the injection behavior and error handling remain identical across all JavaScript-capable runtimes.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →