How the SessionStart Hook Automatically Loads the i-have-adhd Ruleset in Claude Code

The SessionStart hook defined in hooks/hooks.json executes a Node command that checks for an opt-in flag file and, if present, dynamically imports hooks/always-on.mjs to stream the ADHD ruleset into every Claude Code session.

The ayghri/i-have-adhd repository provides a Claude Code plugin that enforces ADHD-friendly response rules through an automatic loading mechanism. When you start a new session, the SessionStart hook runs a validation check before injecting the ruleset from SKILL.md, ensuring the behavior activates only for users who explicitly opt in.

Where the SessionStart Hook Is Defined

The hook declaration lives in hooks/hooks.json at the root of the repository. Claude Code triggers this hook whenever a session begins or when you type the commands startup, resume, clear, or compact. The configuration executes a Node.js one-liner that dynamically imports the loader module:

{
  "type": "command",
  "command": "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(()=>{})\"",
  "timeout": 30,
  "statusMessage": "Checking i-have-adhd always‑on flag..."
}

This command resolves the plugin root using the CLAUDE_PLUGIN_ROOT environment variable (falling back to PLUGIN_ROOT), constructs the absolute path to hooks/always-on.mjs, and imports it via await import(). The trailing .catch(()=>{}) silently consumes any errors, guaranteeing that session initialization never crashes due to plugin issues.

How the Loader Script Validates the Opt-In Flag

The actual ruleset loading logic resides in hooks/always-on.mjs. The script first determines whether you have enabled automatic loading by checking for a specific flag file in your Claude configuration directory:

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

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

If the file ~/.claude/.i-have-adhd-always does not exist (or the path specified by CLAUDE_CONFIG_DIR), the script exits immediately with code 0. This fail-silent approach ensures that the ruleset never loads without explicit user consent, leaving standard Claude Code behavior unchanged for users who have not opted in.

Reading and Streaming the Ruleset

Once the flag file is confirmed, always-on.mjs resolves the path to the ruleset relative to its own location:

const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const skillPath = path.join(scriptDir, "..", "skills", "i-have-adhd", "SKILL.md");
if (!fs.existsSync(skillPath)) process.exit(0);

The script then reads skills/i-have-adhd/SKILL.md, strips the YAML frontmatter using a regular expression, and outputs the cleaned ruleset to stdout along with activation instructions:

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

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`,
);

This output appears at the start of every Claude Code session, ensuring the ADHD-friendly guidelines defined in the repository are immediately visible and active for every response.

Managing the Automatic Ruleset Loading

Enabling always-on mode permanently

Create the flag file to activate automatic loading for all future sessions:

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

Disabling for a single session

Type the command stop adhd mode during your Claude Code session. The SessionStart hook still executes and displays the activation header, but the mechanism respects this temporary override and suppresses the ruleset application for that specific session only.

Permanently disabling automatic loading

Remove the flag file to prevent the SessionStart hook from loading the ruleset in future sessions:

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

When the flag file is absent, hooks/always-on.mjs exits during the initial check, and Claude Code runs without the ADHD-specific ruleset.

Summary

  • The SessionStart hook in hooks/hooks.json launches a Node script at every Claude Code session start or specific command invocation.
  • The script in hooks/always-on.mjs checks for the opt-in flag at ~/.claude/.i-have-adhd-always (or CLAUDE_CONFIG_DIR) before proceeding.
  • If enabled, it reads skills/i-have-adhd/SKILL.md, strips YAML frontmatter, and streams the ruleset to stdout for immediate visibility.
  • All failures are silently caught with .catch(()=>{}) and early process.exit(0) calls to ensure session initialization never crashes.
  • Users control activation through filesystem flags and can temporarily override the behavior with session commands.

Frequently Asked Questions

What triggers the SessionStart hook in Claude Code?

According to the hooks/hooks.json configuration in the ayghri/i-have-adhd repository, the hook executes when a new session begins or when you type the commands startup, resume, clear, or compact. These events trigger the Node command that validates the always-on flag before loading the ruleset.

Where does the i-have-adhd plugin look for the always-on flag file?

By default, the script looks for .i-have-adhd-always inside the directory specified by the CLAUDE_CONFIG_DIR environment variable, or falls back to ~/.claude/ if that variable is unset. This path construction occurs in hooks/always-on.mjs using path.join(os.homedir(), ".claude").

How do I temporarily disable the ruleset without deleting the flag file?

Type stop adhd mode during your Claude Code session. While the SessionStart hook still runs and outputs the initial activation message, the plugin mechanism detects this specific command string and suppresses the ruleset enforcement for the remainder of that session.

What happens if the SKILL.md file is missing when the hook runs?

If skills/i-have-adhd/SKILL.md cannot be found at the resolved path, hooks/always-on.mjs calls process.exit(0) immediately after the file existence check on line 26. This silent failure ensures that the session continues normally without the ruleset, as the plugin assumes the installation is incomplete or corrupted.

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 →