How the Always-On Mechanism Works for OpenCode: A Deep Dive into Auto-Activated ADHD-Friendly Rules
OpenCode implements always-on activation for the i-have-adhd skill through a flag file that triggers automatic prompt injection at session startup.
The ayghri/i-have-adhd repository provides an AI-assisted workflow designed for users with ADHD. For OpenCode users, the skill can remain permanently active without manual invocation. This article explains exactly how that mechanism works by examining the source code implementation.
What the Always-On Flag Does
OpenCode checks for a sentinel file at ~/.config/opencode/.i-have-adhd-always. When present, the plugin automatically loads the full ADHD ruleset into every conversation without user intervention.
This behavior mirrors Claude Code's SessionStart hook pattern. The flag eliminates friction for users who want the ADHD-friendly response format applied universally.
Step-by-Step: How the Always-On Mechanism Executes
Step 1: Flag Detection at Plugin Load
The .opencode/plugins/i-have-adhd.mjs file registers the skill and checks for the flag file during initialization.
// Simplified from .opencode/plugins/i-have-adhd.mjs
const flagPath = path.join(os.homedir(), '.config', 'opencode', '.i-have-adhd-always');
if (fs.existsSync(flagPath)) {
const rules = await fs.promises.readFile(
path.join(root, 'skills', 'i-have-adhd', 'SKILL.md'),
'utf8'
);
systemPrompt += `\n${rules}`;
}
The plugin uses fs.existsSync() synchronously to check presence, then asynchronously reads skills/i-have-adhd/SKILL.md to obtain the ruleset content.
Step 2: Hook Registration via hooks.json
OpenCode discovers the always-on behavior through hooks/hooks.json:
{
"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(()=>{})\"",
"statusMessage": "Checking i-have-adhd always-on flag..."
}
This hook executes hooks/always-on.mjs whenever the plugin loads. The environment variable fallback (CLAUDE_PLUGIN_ROOT || PLUGIN_ROOT) ensures compatibility across runtime contexts.
Step 3: Banner Display and Prompt Injection
The hooks/always-on.mjs script provides user feedback and confirms activation:
// From hooks/always-on.mjs
console.log("ADHD MODE ACTIVE (always-on) …");
// Mirrors the injection logic from the main plugin
This Node.js implementation parallels the shell (always-on.sh) and PowerShell (always-on.ps1) versions found in the same directory, maintaining cross-runtime consistency.
Enabling and Disabling Always-On Mode
Enable Permanent Always-On
touch ~/.config/opencode/.i-have-adhd-always
Creating this empty file activates automatic loading for all subsequent OpenCode sessions.
Disable for Current Session Only
Enter either command during conversation:
stop adhd mode
or
normal mode
These phrases trigger the plugin's session-level deactivation logic without affecting the persistent flag.
Disable Permanently
rm ~/.config/opencode/.i-have-adhd-always
Removing the flag file prevents automatic activation in future sessions while preserving the skill for manual invocation.
Key Implementation Files
| File | Purpose |
|---|---|
.opencode/plugins/i-have-adhd.mjs |
Core plugin logic; performs flag check and prompt augmentation |
hooks/hooks.json |
Declares the always-on hook for OpenCode's plugin system |
hooks/always-on.mjs |
Node.js runtime script for banner display and confirmation |
skills/i-have-adhd/SKILL.md |
Source content containing all ADHD-friendly formatting rules |
INSTALL.md |
User-facing documentation for OpenCode setup |
The ruleset file (SKILL.md) contains the actual behavioral instructions—structured formatting, chunked responses, and prioritization cues—that OpenCode injects when always-on mode activates.
Summary
- always-on mechanism activation: Create
~/.config/opencode/.i-have-adhd-alwaysto enable automatic loading - trigger point:
.opencode/plugins/i-have-adhd.mjschecks the flag at session start - injection target: Full content of
skills/i-have-adhd/SKILL.mdprepended to system prompt - temporary override:
stop adhd modeornormal modedisables for current session - permanent disablement: Delete the flag file to stop automatic behavior
According to the ayghri/i-have-adhd source code, this architecture intentionally mirrors Claude Code's hook system while adapting to OpenCode's plugin conventions.
Frequently Asked Questions
What file exactly does OpenCode check for always-on mode?
OpenCode checks for ~/.config/opencode/.i-have-adhd-always. The hardcoded path is constructed in .opencode/plugins/i-have-adhd.mjs using path.join(os.homedir(), '.config', 'opencode', '.i-have-adhd-always').
Does the always-on flag affect other Claude Code installations?
No. The flag path is OpenCode-specific. Claude Code uses its own CLAUDE_PLUGIN_ROOT environment variable and separate activation flow. The repository maintains distinct implementations for each platform in separate subdirectories.
Can I customize which rules load in always-on mode?
Not without modifying the source. The plugin always loads the complete skills/i-have-adhd/SKILL.md file. To use partial rules, you would need to fork the repository and edit the file read operation in .opencode/plugins/i-have-adhd.mjs.
Why does the hook use such a complex Node.js command string?
The hooks/hooks.json command dynamically resolves the plugin root path across different installation contexts. It handles both CLAUDE_PLUGIN_ROOT (legacy compatibility) and PLUGIN_ROOT (current OpenCode), converts to file URLs for ES modules, and suppresses errors with .catch(()=>{}) to prevent startup failures.
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 →