On-Disk vs. In-Memory Skill Loading in the i-have-adhd Plugin
The i-have-adhd plugin reads behavioral rules from skills/i-have-adhd/SKILL.md using readFileSync; on-disk loading invokes this read every time the function runs, while in-memory loading caches the result in a module-level constant after the first read, eliminating subsequent filesystem I/O.
The ayghri/i-have-adhd repository provides an editing assistant for users with ADHD, implemented as both a native VS Code extension and an OpenCode plugin. Understanding how this plugin loads its skill rules matters for performance, reliability, and debugging. This article examines the two loading strategies—on-disk versus in-memory—as implemented in the source code.
How On-Disk Skill Loading Works
On-disk skill loading occurs when loadRules() reads the skill file from the filesystem at runtime. In extensions/i-have-adhd.ts, this function is defined at lines 46–64:
// extensions/i-have-adhd.ts
function loadRules(): string {
const content = readFileSync(SKILL_PATH, "utf8");
const rules = stripFrontmatter(content);
return rules;
}
Each invocation of loadRules() executes readFileSync(SKILL_PATH, "utf8"), performing a blocking filesystem read. The SKILL_PATH constant points to skills/i-have-adhd/SKILL.md within the repository. If the file is missing or unreadable, the function throws an error (lines 50–55), propagating the failure to the caller.
This approach ensures the latest version of the rules is always retrieved, but incurs I/O overhead on every call.
How In-Memory Skill Loading Works
In-memory skill loading caches the rules after the first successful read, reusing the cached string for all subsequent operations. The caching happens through a module-level constant declared at line 99 of extensions/i-have-adhd.ts:
// extensions/i-have-adhd.ts
const rules = loadRules(); // Executed once when module is first imported
When the extension initializes, loadRules() runs once, reads SKILL.md from disk, and stores the stripped content in rules. The syncContext() function then references this cached value without additional filesystem access:
// extensions/i-have-adhd.ts
function syncContext(ctx: ExtensionContext): void {
const injected = rulesAreInContext(ctx);
if (enabled && !injected) {
// Uses in-memory `rules` — no disk I/O
pi.sendMessage({
customType: RULES_MESSAGE_TYPE,
content: `${RULES_HEADER}\n\n${rules}`
});
}
}
The rulesAreInContext() check prevents duplicate injection, but the source of truth remains the cached rules string throughout the session.
Key Differences Summarized
| Aspect | On-Disk Loading | In-Memory Loading |
|---|---|---|
| Execution frequency | Every time loadRules() is called |
Once at module initialization |
| Filesystem I/O | Occurs on each invocation | Occurs only on first import |
| Error exposure | Each call can throw read errors | Only the initial call can throw |
| Performance | Higher latency, variable | Near-zero latency after startup |
| Rule freshness | Always reads current file | Fixed at module load time |
OpenCode Plugin Implementation
The .opencode/plugins/i-have-adhd.mjs file implements a similar pattern for the OpenCode runtime. The plugin registers the skill directory and reads SKILL.md once during plugin initialization, aligning with the in-memory caching strategy:
// .opencode/plugins/i-have-adhd.mjs (conceptual)
// Reads SKILL.md at startup, caches for all subsequent requests
const skillRules = fs.readFileSync(skillPath, "utf-8");
This mirrors the extension's design: favor single-read caching over repeated filesystem access.
Toggle Behavior and Session Management
Users enable or disable ADHD mode through commands that affect the enabled flag, not the loading mechanism:
> /i-have-adhd # Enables mode, uses cached `rules` for injection
> stop adhd # Disables mode, cached `rules` remains in memory
The hooks/always-on.mjs file ensures the skill file exists and is readable, but does not alter the caching logic. Whether enabled or disabled, the rules constant remains populated after the first module load.
Summary
- On-disk skill loading reads
skills/i-have-adhd/SKILL.mdviareadFileSync()on everyloadRules()call, ensuring fresh content at the cost of repeated I/O. - In-memory skill loading executes
loadRules()once at module initialization, storing the result in therulesconstant for zero-overhead reuse. - The
ayghri/i-have-adhdextension uses in-memory loading as its production strategy, with on-disk loading available as the underlying mechanism. - The OpenCode plugin (
.opencode/plugins/i-have-adhd.mjs) follows the same pattern, reading the skill file once at startup.
Frequently Asked Questions
What happens if SKILL.md is deleted after the plugin starts?
The in-memory caching protects against this scenario. Since rules is populated at module initialization, subsequent syncContext() calls use the cached string without filesystem access. The plugin continues functioning normally until restarted, at which point loadRules() would fail.
Can I force the plugin to reload rules from disk without restarting VS Code?
The source code does not expose a reload command. The rules constant is initialized once via const rules = loadRules() and never reassigned. To refresh rules, you must reload the window or restart the extension host, triggering a new module evaluation.
Does in-memory loading consume significant RAM?
No. The rules string contains the stripped content of SKILL.md—typically a few kilobytes of markdown. This memory footprint is negligible compared to the extension's overall resource usage and is preferable to repeated filesystem calls.
Why does the OpenCode plugin use the same loading strategy as the extension?
Both implementations prioritize performance and reliability. Reading from disk once at startup eliminates file-locking issues, reduces latency during active sessions, and ensures consistent rule application. The unified approach simplifies maintenance across the native extension and OpenCode runtime environments.
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 →