How the SessionStart Hook in `hooks/always-on.sh` Enables the i-have-adhd Skill on Startup
The SessionStart hook configured in hooks/hooks.json automatically executes hooks/always-on.sh at the beginning of every Claude Code session, injecting the i-have-adhd ruleset into the system prompt when it detects an opt-in flag file.
The SessionStart hook mechanism allows Claude Code plugins to initialize context before any user interaction occurs. In the ayghri/i-have-adhd repository, this hook implements an "always-on" mode that applies ADHD-focused communication guidelines to every response without requiring manual skill activation commands.
SessionStart Hook Registration in hooks.json
Claude Code discovers the hook through the configuration file hooks/hooks.json, which registers a SessionStart event matcher:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
"hooks": [
{
"type": "command",
"command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/always-on.sh\"",
"timeout": 5,
"statusMessage": "Checking i-have-adhd always-on flag..."
}
]
}
]
}
}
The matcher triggers on four session events—startup, resume, clear, and compact—ensuring the skill activates for new conversations and continued sessions alike. The hook executes hooks/always-on.sh with a five-second timeout, displaying a status message while processing.
The Three-Step Activation Process
The hooks/always-on.sh script performs a conditional three-step validation to determine whether to inject the skill ruleset.
Step 1: Detect the Opt-In Flag
The script first checks for the presence of a sentinel file in the Claude configuration directory:
claude_dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
flag_path="$claude_dir/.i-have-adhd-always"
[ -f "$flag_path" ] || exit 0
If ~/.claude/.i-have-adhd-always does not exist, the script exits silently with code 0, leaving the session unchanged. Creating this empty file serves as the user's explicit opt-in signal to enable the SessionStart hook functionality.
Step 2: Locate the Skill Description
After confirming the flag, the script resolves the relative path to the skill's canonical ruleset:
script_dir=$(dirname -- "$0")
skill_path="$script_dir/../skills/i-have-adhd/SKILL.md"
[ -f "$skill_path" ] || exit 0
This approach uses the script's own location ($0) to find skills/i-have-adhd/SKILL.md without relying on hardcoded absolute paths or additional environment variables. If the markdown file is missing, the hook aborts without error.
Step 3: Strip Frontmatter and Output Rules
The script processes SKILL.md to remove YAML frontmatter and inject the remaining content:
body=$(awk '
NR == 1 && $0 ~ /^---[[:space:]]*$/ { in_fm = 1; next }
in_fm && $0 ~ /^---[[:space:]]*$/ { in_fm = 0; next }
!in_fm { print }
' "$skill_path") || exit 0
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"
The awk command filters out the metadata block between --- delimiters, preserving only the actual rules. The script then prints a banner message followed by the cleaned ruleset, which Claude Code captures and inserts into the session's system prompt. This ensures the i-have-adhd constraints apply to every assistant response until explicitly disabled.
Managing the Always-On Mode
Control the SessionStart hook behavior using these shell commands:
Enable permanently (creates the opt-in flag):
mkdir -p ~/.claude
touch ~/.claude/.i-have-adhd-always
Disable for the current session only:
Type the following in the Claude chat:
stop adhd mode
Disable permanently (removes the opt-in flag):
rm ~/.claude/.i-have-adhd-always
Debug the hook manually:
sh "$(git rev-parse --show-toplevel)/hooks/always-on.sh"
Summary
- The SessionStart hook in
hooks/hooks.jsontriggershooks/always-on.shon every session startup, resume, clear, or compact event. - The script checks for
~/.claude/.i-have-adhd-alwaysas an opt-in mechanism; without this file, the hook exits silently. - Upon validation, the script reads
skills/i-have-adhd/SKILL.md, strips YAML frontmatter usingawk, and injects the ruleset into the active session. - The printed output includes instructions to disable the mode temporarily ("stop adhd mode") or permanently (delete the flag file).
Frequently Asked Questions
What triggers the SessionStart hook to run?
The hook executes when Claude Code detects specific session lifecycle events: startup (new conversation), resume (returning to existing conversation), clear (clearing conversation history), or compact (compressing long conversations). This ensures the i-have-adhd skill remains active across all session transitions.
How do I disable the skill for just one session?
Type stop adhd mode in the chat input. This command disables the ADHD ruleset for the current session only, without deleting the ~/.claude/.i-have-adhd-always flag file. The SessionStart hook will reactivate the skill the next time you start or resume a conversation.
Where is the actual skill ruleset stored?
The canonical ruleset lives in skills/i-have-adhd/SKILL.md relative to the repository root. The hooks/always-on.sh script reads this file, removes the YAML frontmatter block (delimited by ---), and outputs the remaining content as the active ruleset for the session.
What happens if the SKILL.md file is missing?
If hooks/always-on.sh cannot locate skills/i-have-adhd/SKILL.md, it exits with code 0 immediately after the file check ([ -f "$skill_path" ] || exit 0). This silent failure prevents error messages from cluttering the session startup, though the skill will not activate despite the presence of the opt-in flag.
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 →