Opening this before the PR, as CONTRIBUTING asks for new hooks and behaviour changes.
Problems observed in daily use (Claude Code 2.1.260)
- Subagents never see the rules. The SessionStart hook injects the ruleset into the main conversation only. Every Agent-tool subagent answers in default style. Measured on 14 days of my own transcripts: 26 subagent runs, 0 carried the ruleset.
- Forked sessions skip the hook. Since Claude Code 2.1.214 a forked session (
/fork, /branch, --fork-session) reports SessionStart source fork, not resume. The matcher startup|resume|clear|compact does not fire for it.
- The hook is compactable and node-dependent. Its output lives in conversation context, so it is summarised away on compaction and re-sent uncached every turn. It also silently does nothing when
node is not on PATH (launchd, bare tmux).
- Always-on is a hidden flag file. Users have to know about
~/.claude/.i-have-adhd-always; there is no visible switch.
Proposed changes (all opt-in, no existing behaviour removed)
- Add a
SubagentStart hook using the same launcher; it emits hookSpecificOutput.additionalContext. Skips agent_type: fork, which inherits the parent conversation.
- Add
fork to the SessionStart matcher.
- Ship
output-styles/i-have-adhd.md with the same body as SKILL.md (test-enforced equality, keep-coding-instructions: true). Claude Code resolves it as i-have-adhd:i-have-adhd. When a user selects it, the SessionStart hook stands down so the rules are not injected twice.
- Declare a
userConfig option always_on (boolean, default false) in plugin.json; Claude Code exports it to the hook as CLAUDE_PLUGIN_OPTION_ALWAYS_ON. Add I_HAVE_ADHD_ALWAYS_ON=1 for Codex. The flag file keeps working. A new .i-have-adhd-off file wins over all of them.
Default behaviour after the change is identical to today: install does nothing until the user invokes the skill or turns always-on on.
Verification so far
- 60 unit tests across node, sh and PowerShell runtimes, including banner byte-equality across runtimes.
- Live probe on 2.1.260: with
outputStyle: "i-have-adhd:i-have-adhd" the model quotes the ruleset from its system prompt; the bare name i-have-adhd does not resolve.
Happy to split further or drop any part. Working branch: https://github.com/ahma/i-have-adhd (branch opus5-ux). Drafted with Claude Code on behalf of @ahma, who reviews and submits.
Opening this before the PR, as CONTRIBUTING asks for new hooks and behaviour changes.
Problems observed in daily use (Claude Code 2.1.260)
/fork,/branch,--fork-session) reports SessionStart sourcefork, notresume. The matcherstartup|resume|clear|compactdoes not fire for it.nodeis not on PATH (launchd, bare tmux).~/.claude/.i-have-adhd-always; there is no visible switch.Proposed changes (all opt-in, no existing behaviour removed)
SubagentStarthook using the same launcher; it emitshookSpecificOutput.additionalContext. Skipsagent_type: fork, which inherits the parent conversation.forkto the SessionStart matcher.output-styles/i-have-adhd.mdwith the same body asSKILL.md(test-enforced equality,keep-coding-instructions: true). Claude Code resolves it asi-have-adhd:i-have-adhd. When a user selects it, the SessionStart hook stands down so the rules are not injected twice.userConfigoptionalways_on(boolean, default false) inplugin.json; Claude Code exports it to the hook asCLAUDE_PLUGIN_OPTION_ALWAYS_ON. AddI_HAVE_ADHD_ALWAYS_ON=1for Codex. The flag file keeps working. A new.i-have-adhd-offfile wins over all of them.Default behaviour after the change is identical to today: install does nothing until the user invokes the skill or turns always-on on.
Verification so far
outputStyle: "i-have-adhd:i-have-adhd"the model quotes the ruleset from its system prompt; the bare namei-have-adhddoes not resolve.Happy to split further or drop any part. Working branch: https://github.com/ahma/i-have-adhd (branch
opus5-ux). Drafted with Claude Code on behalf of @ahma, who reviews and submits.