How to Integrate i-have-adhd with a Custom Agent Harness: Best Practices for 2024
The best way to integrate i-have-adhd with a custom agent harness is to load the TypeScript extension (for Pi/OMP harnesses) or the OpenCode plugin, register the adhd flag and /i-have-adhd command, and hook into session lifecycle events to synchronize the ruleset context.
Integrating i-have-adhd with a custom agent harness allows you to add an ADHD-friendly response layer to any OpenAI-style agent that follows the extension contract used by Pi, OMP, OpenCode, Claude Code, and Codex. The repository provides a clean, reusable architecture that separates the ruleset from the runtime logic, making integration straightforward across different harness types.
Core Integration Components
The i-have-adhd integration consists of three primary parts that work together to inject ADHD-friendly formatting rules into your agent's system prompt.
1. SKILL.md: The Ruleset Source of Truth
All behavioral rules live in a single human-readable file: skills/i-have-adhd/SKILL.md. This markdown file contains the complete instruction set that the model must follow when ADHD mode is active.
Both the TypeScript extension and the OpenCode plugin read from this file. Keeping rules in one location ensures consistency across all harness integrations.
2. TypeScript Extension for Pi/OMP Harnesses
The extensions/i-have-adhd.ts module provides full runtime control for Pi-compatible harnesses. It manages the enabled state, injects rules as system messages, and exposes user-facing controls.
Key functions in extensions/i-have-adhd.ts:
loadRules()(lines 46-64): ReadsSKILL.mdand strips YAML front-matter to extract the pure ruleset.syncContext()(lines 18-33): Ensures rules appear in the active context only whenenabledis true.setEnabled()(lines 55-61): Toggles the mode, persists state to the session manager, updates UI status, and notifies the user.pi.registerCommand("i-have-adhd", …)(lines 69-91): Exposes the/i-have-adhdslash command with subcommands (on,off, status check).
The extension stores state using a custom session entry keyed as i-have-adhd-state, ensuring the mode survives session reloads.
3. OpenCode Plugin for Minimal Integration
For OpenCode-based harnesses, .opencode/plugins/i-have-adhd.mjs provides a lighter alternative with always-on support.
Key features:
rulesetBody()(lines 38-43): MirrorsloadRules()— readsSKILL.mdand removes YAML front-matter.experimental.chat.system.transform(lines 59-78): Appends the ruleset to every system prompt when the flag file exists (~/.config/opencode/.i-have-adhd-always).
This plugin requires no interactive commands — the mode activates automatically based on filesystem state.
Integration Steps for Custom Harnesses
Follow this sequence when adding i-have-adhd support to your own agent harness.
Step 1: Load the Extension or Plugin
For Pi-based harnesses:
import { createPiAgent } from '@earendil-works/pi-coding-agent';
import iHaveAdhdExtension from './extensions/i-have-adhd';
async function main() {
const pi = await createPiAgent({ /* your Pi config */ });
// Install the i-have-adhd extension
iHaveAdhdExtension(pi);
await pi.start();
}
main();
For OpenCode harnesses:
import { OpenCode } from '@opencode-ai/sdk';
import iHaveAdhdPlugin from './.opencode/plugins/i-have-adhd.mjs';
async function run() {
const oc = new OpenCode({
plugins: [iHaveAdhdPlugin],
});
await oc.chat({ /* your chat config */ });
}
run();
Step 2: Register the Flag and Command
The extension automatically registers:
- The
adhdboolean flag for CLI opt-in (--adhd) - The
/i-have-adhdslash command for runtime toggling
Custom harnesses must ensure their command parser and flag system expose these to users.
Step 3: Hook Session Lifecycle Events
For state persistence, your harness should invoke the extension's helpers at these session events:
| Event | Extension Helper | Purpose |
|---|---|---|
session_start |
restoreState() |
Read persisted i-have-adhd-state entry |
session_tree |
syncContext() |
Inject or remove rules based on current state |
session_compact |
syncContext() |
Maintain ruleset position after context compaction |
The TypeScript extension subscribes to these events automatically when initialized with iHaveAdhdExtension(pi).
Step 4: Implement Always-On Mode (Optional)
For harnesses preferring automatic activation without user commands:
# Create the flag file in your harness's config directory
touch ~/.config/your-harness/.i-have-adhd-always
When this file exists, the OpenCode plugin's experimental.chat.system.transform hook prepends the ADHD ruleset to every system prompt. Reference hooks/always-on.mjs for Claude Code's implementation of the same pattern.
Programmatic Control for Testing
Automated tests can manipulate the integration directly:
// Toggle mode by writing to session state
pi.appendEntry('i-have-adhd-state', { enabled: true });
// Manually inject ruleset (bypasses normal flow)
pi.sendMessage(
{ customType: 'i-have-adhd-rules', content: '...' },
{ triggerTurn: false }
);
This approach matches how setEnabled() persists state internally (lines 55-61 in extensions/i-have-adhd.ts).
File Reference Map
| File | Purpose | Integration Role |
|---|---|---|
skills/i-have-adhd/SKILL.md |
Markdown ruleset | Source of truth; loaded by all integrations |
extensions/i-have-adhd.ts |
TypeScript extension | Full-featured integration for Pi/OMP |
.opencode/plugins/i-have-adhd.mjs |
OpenCode plugin | Lightweight always-on support |
hooks/always-on.mjs |
Claude Code script | Reference implementation for custom hooks |
tests/test_always_on_hooks.py |
Test suite | Validates behavior across runtimes |
Harness Compatibility Matrix
| Harness Type | Recommended Integration | Entry Point |
|---|---|---|
| Pi/OMP | TypeScript extension | extensions/i-have-adhd.ts |
| OpenCode | JavaScript plugin | .opencode/plugins/i-have-adhd.mjs |
| Claude Code | always-on hook | hooks/always-on.mjs |
| Custom OpenAI-style | Adapt plugin pattern | Copy .opencode/plugins/i-have-adhd.mjs structure |
Summary
- Single source of truth: All rules live in
skills/i-have-adhd/SKILL.md— never duplicate them in your harness. - Two integration paths: Use the TypeScript extension for interactive control (Pi/OMP) or the OpenCode plugin for always-on simplicity.
- State persistence: The
i-have-adhd-statesession entry and flag file mechanisms ensure mode survival across sessions. - Command + flag surface: Expose
/i-have-adhdfor users and--adhdfor CLI scripts to match upstream conventions. - Hook lifecycle events:
restoreState()andsyncContext()keep context synchronized automatically.
Frequently Asked Questions
How do I enable i-have-adhd permanently without typing commands?
Create an always-on flag file in your harness's configuration directory. For OpenCode, this is ~/.config/opencode/.i-have-adhd-always. The plugin's experimental.chat.system.transform hook detects this file and prepends the ADHD ruleset to every system prompt automatically.
Can I use i-have-adhd with a custom harness that isn't Pi or OpenCode?
Yes. The OpenCode plugin pattern in .opencode/plugins/i-have-adhd.mjs provides a minimal, portable reference. Copy its structure: read SKILL.md via rulesetBody(), strip the YAML front-matter, and inject the result into your system prompt using your harness's equivalent transform hook.
What happens if the SKILL.md file changes during a running session?
The extension reads SKILL.md fresh on each syncContext() call via loadRules() (lines 46-64). Ruleset updates take effect on the next context synchronization, typically at the start of a new user turn or session event.
How does state persist across session restarts?
The TypeScript extension writes to a custom session entry i-have-adhd-state using pi.appendEntry(). When the harness restarts, restoreState() reads this entry and reconstructs the previous enabled state before the first user interaction.
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 →