How to Add a New Runtime Platform to i-have-adhd from Scratch
Adding a new runtime platform to i-have-adhd requires creating a manifest JSON file, optionally implementing a TypeScript extension module, configuring persistent hooks in hooks/hooks.json, and validating the integration through the repository's test suite.
The i-have-adhd repository supports multiple AI runtimes—including Claude, Codex, Pi, OMP, OpenCode, Qwen, Kimi, and Gemini—through a unified extension architecture. Adding a new runtime platform follows a predictable pattern that ties together manifest declarations, optional runtime-specific code, and hook-based automation to integrate seamlessly with the existing skill system.
Define the Runtime Manifest
Every runtime platform begins with a declarative manifest that identifies the plugin and points to the shared skills directory.
Choose a Runtime Identifier
Select a short, lowercase identifier (e.g., myruntime) that will serve as the prefix for configuration files and JSON keys throughout the repository.
Create the Extension JSON
Create a <runtime>-extension.json file at the repository root, following the structure of qwen-extension.json. This file declares the plugin metadata and skill location.
{
"name": "i-have-adhd",
"version": "0.2.0",
"description": "ADHD-friendly output shaping for MyRuntime: action first, numbered steps, no tangents, visible progress.",
"skills": "skills"
}
Key requirements for this manifest:
- The
namefield must remain i-have-adhd to identify the plugin. - The
versionshould match the repository version specified inpackage.json(0.2.0as of the current codebase). - The
skillsproperty points to the./skills/directory containing the prompt templates.
Add the Plugin Descriptor (If Required)
Some runtimes (Kimi, Gemini) utilize a *.plugin.json format instead of or in addition to the extension JSON. Duplicate the structure from kimi.plugin.json or gemini-extension.json and adapt the runtime-specific fields.
{
"name": "i-have-adhd",
"version": "0.2.0",
"description": "Shape output for MyRuntime: lead with the next action, number steps, suppress tangents, restate state, make wins visible.",
"license": "MIT",
"homepage": "https://github.com/ayghri/i-have-adhd",
"skills": "./skills/",
"interface": {
"displayName": "I Have ADHD",
"shortDescription": "ADHD-friendly output shaping for MyRuntime CLI"
}
}
Implement Runtime-Specific Code
Not all runtimes require custom code, but those with unique integration points (like Pi or OMP) need a TypeScript extension module.
Create the Extension Entry Point
Add a TypeScript file under extensions/ that exports runtime-specific helpers. Use extensions/i-have-adhd.ts as the reference implementation for Pi/OMP integration.
// extensions/myruntime.ts
export const myruntime = {
// Insert runtime-specific initialization or helper functions here.
};
For minimal runtimes that only need manifest-based skill loading, you can export an empty object or omit this file entirely.
Register in package.json
If you created an extension module, register it in package.json under a runtime-specific key. For Pi and OMP, this appears as:
"pi": {
"extensions": ["./extensions/i-have-adhd.ts"]
}
For a new runtime, add a corresponding top-level key:
"myruntime": {
"extensions": ["./extensions/myruntime.ts"]
}
Configure Persistent Hooks
For runtimes requiring "always-on" background behavior, register persistent hooks in the central registry.
Register in hooks.json
Add an entry to hooks/hooks.json that maps your runtime identifier to an execution script.
{
"runtime": "myruntime",
"command": "always-on.mjs"
}
Create the Hook Script
Implement the corresponding script in the hooks/ directory. The script should import your extension module if runtime-specific logic is required.
// hooks/always-on.mjs
import { myruntime } from '../extensions/myruntime.ts';
export default async function () {
// Runtime-specific initialization or monitoring logic.
}
Validate the Integration
Before publishing, verify that your runtime integrates correctly with the build system and test suite.
Update Documentation
Add the new runtime to the Runtime entry points table in AGENTS.md (lines 44–51) and include a brief description in the Repository map section (lines 33–35). If you created a *.plugin.json file, ensure the interface.displayName value appears in any UI-facing documentation.
Add Unit Tests
Create a test file under tests/ that validates manifest loading and extension exports. Follow the patterns established in tests/test_opencode_plugin.py and tests/test_omp_package.py to verify JSON schema compliance and module structure.
Run the Verification Suite
Execute the repository's validation commands to ensure no regressions:
python3 -m unittest discover -s tests -v
python3 scripts/run_evals.py validate
bun scripts/check_context_compat.ts
If your runtime requires dedicated CI validation, add a workflow file under .github/workflows/ (e.g., myruntime-load-check.yml) modeled after plugin-load-check.yml or pi-load-check.yml.
Publish the Runtime
For plugin-based runtimes (Claude, Codex, Kimi, Gemini), publish the new manifest to the respective marketplace using the runtime's CLI tools (e.g., claude plugin or codex plugin commands) as referenced in the Tune it section of README.md. Ensure the manifest files are committed to the repository root before distribution.
Summary
- Manifest creation involves adding a
<runtime>-extension.json(and optionally a<runtime>.plugin.json) to declare metadata and skills location. - Extension modules in
extensions/provide runtime-specific TypeScript glue code when native integration is required. - Hook registration in
hooks/hooks.jsonenables persistent background behavior for supported runtimes. - Validation requires updating
AGENTS.md, adding tests undertests/, and passing the full verification suite includingcheck_context_compat.ts. - Publication follows runtime-specific marketplace workflows while maintaining the repository's structural conventions.
Frequently Asked Questions
What is the difference between -extension.json and .plugin.json files?
The -extension.json format serves as the base manifest used by most runtimes including Qwen and Gemini, declaring essential metadata like name, version, and skills. The .plugin.json format (seen in kimi.plugin.json) provides additional marketplace-specific metadata such as license, homepage, and interface display properties required by certain runtime ecosystems. You should provide both if your target runtime supports the plugin marketplace model.
Do I need to write TypeScript code for every new runtime?
No. Many runtimes—including Qwen and Gemini—require only the manifest JSON files to load the skills directory. You only need to create a TypeScript extension module (in extensions/) if your runtime requires custom initialization, API adapters, or runtime-specific helper functions, as implemented for Pi and OMP in extensions/i-have-adhd.ts.
How do I ensure my new runtime passes the repository's integrity checks?
Run the three-tier validation suite: python3 -m unittest discover -s tests -v for Python-based manifest tests, python3 scripts/run_evals.py validate for evaluation logic, and bun scripts/check_context_compat.ts for TypeScript compatibility. Additionally, create a runtime-specific test file following the patterns in tests/test_opencode_plugin.py to verify your JSON manifests parse correctly and your extension exports the expected object shape.
Where does the runtime identifier appear in the codebase beyond the manifest files?
The runtime identifier appears in four critical locations: the root manifest filename (<runtime>-extension.json), the hooks/hooks.json runtime field for persistent activation, the package.json key for extension registration (if using TypeScript modules), and the CI workflow filename (e.g., .github/workflows/<runtime>-load-check.yml) for automated testing. Consistent naming across these files ensures the build system recognizes your platform.
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 →