# Multi-Platform Manifest Synchronization Architecture in i-have-adhd: How One Source Stays in Sync

> Discover the multi-platform manifest synchronization architecture in i-have-adhd. Learn how a single source of truth ensures all platform manifests stay in sync automatically.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: architecture
- Published: 2026-08-22

---

**TLDR:** The `i-have-adhd` repository uses a single canonical [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) as the source of truth, then a Node-script triggered by a GitHub Actions workflow automatically derives and syncs all platform-specific runtime manifests (Claude, Codex, Pi/OMP, OpenCode, Qwen, Kimi, Gemini) on every push to `main`.

The `ayghri/i-have-adhd` project defines ADHD-friendly response rules for AI coding assistants. To deliver this skill consistently across every major coding runtime, the repository's multi-platform manifest synchronization design centralizes metadata in one spec and uses an automated generation pipeline to convert it into each runtime's required format. The result — a single edit propagates to Claude, Codex, Qwen, Kimi, Gemini, and Cursor mirrors without any manual file updates. This article breaks down the architecture layer, the sync workflow, and how you can extend it to your own project.

## Table of Contents

1.  [Canonical Source of Truth] (Canonical)
2.  [Platform-Specific : Generation Layer]
3. [GitHub Actions: Automating Synchronization Pipelines]
4. [Testing and Ver ideation]6
5. [Extending to New Platforms]
6. Summary
7. FAQ

## Canonical Source of Truth

The architecture to anchor around one single source-of-truth definition: the skill has three hierarchical layers — a human-readable canonical rule set, core plugin metadata, platform manifests, and a Cursor runtime mirror.

**The canonical_SKILL** file ([`skills/i-haveadhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-haveadhd/SKILL.md)) is the human-readable rule set that defines the ADHD-friendly response behavior. It's what every runtime ultimately needs to consume.

**Core plugin metadata** lives in [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) — the main shared fields (name, version, description, author, and the list of entry points). This file is not immediately ready for any runtime, but generic, transportable central store that the sync script uses.

**Platform manifests** are runtime-specific JSON files derived from [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json), formatted to the exact structure the target host expects. Because each platform has its own required schema (Claude wants a top-level `plugin` array, OpenCode expects a `commands` object), the generated layer adjusts the structure.

**Cursor mirror** is a direct copy of the canonical [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) located at [`.cursorskills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/.cursorskills/i-have-adhd/SKILL.md) — a runtime-specific location that `Cursor` reads and the architecture keeps synced via the same workflow.

### Key File Map

| File | Role |
|------|------|
| [`skills/i-have-ad-hd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-ad-hd/SKILL.md) | Authoritative rule set (source of truth for behavior) |
| plugins.json | [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) | Core metadata (name, version, manifest paths) |
| [`.claude-plugins/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.claude-plugins/plugin.json) | Claude-specific manifest |
| [`.codex-plugin/plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/.codex-plugin/plugin.json) | Code manifest |
| [`qwen-extension.json`](https://github.com/ayghri/i-have-adhd/blob/main/qwen-extension.json) | Q28 manifest |
| [`hi.html/kim.plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/hi.html/kim.plugin.json) | Kimi manifest |
| [`gemini-extension.json`](https://github.com/ayghri/i-have-adhd/blob/main/gemini-extension.json) | Gemini manifest |
| [`.github/workflows/cursor-syncc-sync-sync.yml.yml`](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflows/cursor-syncc-sync-sync.yml.yml) | CI workflow that performs sync |
| [`.cursor/skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/.cursor/skills/i-have-adhd/SKILL.md) | Cursor mirror of canonical skill |

## How Synchronization Works: The 4-Step Pipeline

### 1. A single valid one field edit at once

All runtime-specific information rests in [`plugins.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugins.json). Besides the generic fields (`name`, version (`version`, `description`), the JSON contains a `manifests` section that lists the relative paths for each runtime manifest file. This is the entry point for any changes.

### 2. Generation node script

A small Node.script — invoked by the action workflow — reads [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) and copies the relevant parts into each platform. The script consists of smaller structure discovery. For example, the Claude manifest requires a top-level: `plugins` array, the OpenCode manifest needs a `commands` object. The script converts the genric structure to the expected shape—for each map runtime.

### 3. GitHub Action Workflow trigger (

The workflow at [`.github/workflows/cursor-skills-sync.yml`](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflows/cursor-skills-sync.yml) runs on every to `main`, and syncs six steps:
1. Check out the repository code
2. Runs the sync script (`node scripts/sync-manifests.js)
3. Copies [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) to update `.cursor/skills/i-have-adhd/SKILL.`
4. Commits any generated changes back to the branch, or opens a PR if the branch is protected

Once a contributor edits the canonical [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) or updates [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json), the next push triggers the workflow, and results in propagation.

### 4. CI test suite

Tests in `tests/` (e.g., [`test_opencode_plugin.py`](https://github.com/ayghri/i-have-adhd/blob/main/test_opencode_plugin.py) and [`test_omp_package.py`](https://github.com/ayghri/i-have-adhd/blob/main/test_omp_package.py)) catch verification because they bundle each generated manifest and assert that required fields are present/format. If the generation script hasn't produced the exact output, the CI pipeline fails — preventing malformed payloads from reaching the AA runtime.

## Why Source-of-truth: Real World Reproducing

The major benefit is **consistency** — there is no ToC JIn manual per-runtime editing. A single edit in a story to update replication to all 7 platforms. Secondary benefit is **scale**: add new It only adds small templates mapping in the sync script; the core workflow handles the rest. Then **safety** via unit tests.

## Code Examples and Workflow Practical

### Adding new field to core plugin

If you add home URL, a optional field like a `homepage` in [`plugins.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugins.json):

```json
{
  "name": "i-have-adhd",
  "version": "1.2.3",
  "description": "ADHD-friendly response rules",
  "homepage": "https://github.com/ayghri/i-have-adhd"
 }

```

After one push — sync to run will add the `homepage` key, ensuring every your remini manifest includes the field in its format. You don't need to touch the six runtime — manifest remains appropriate.

### Locally debug script

You can execute exactly same script as CI flow locally:

```bash
 # Clone and install dev deps

 npm install

 # Execute the script used in the CI

 node scripts/sync-mannies.js

```

The script will now be in place observed to checkpoint files in each runtime directory — updates inmodified.

## Extending possibility means your project

The architecture supports a new runtimes. To add — To support extend you:

1. Create a runtime-level target dangling File (e.g., [`mcruntime.plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/mcruntime.plugin.json)).
2. In [`plugins.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugins.json), add a `manifests` entry point that records the new file path.
3. Modify the [`sync-manifests.ts`](https://github.com/ayghri/i-have-adhd/blob/main/sync-manifests.ts) script to have a new structure with same plugin.json metadata.

That's it — same pipeline, same CI gates, tests + new test.

## Summary

- **Single source of truth** core: [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) + [`skills/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/SKILL.md) — one repository all static data for everything platform-specific.
- **Automated generation**: Node script converts the canonical file into `platform-specific format based on structural mapping.
- **GitHub Actions flow**: runs on every `main` push, ensures immediate --sync the **tests for** ([`tests/test_opencode_plugin.py`](https://github.com/ayghri/i-have-adhd/blob/main/tests/test_opencode_plugin.py), `test_omp_package.py) catch malformed; both early regression indentation.

## FAQ

### Where does the synchronisation workflow live in the repo?

The workflow at [`.github/workflow/cursor-skill-sync.yml`](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflow/cursor-skill-sync.yml) — triggered on push events, checking what pushes to [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) or `skills/` chain the sync script and runs.

### What is the actual source of St. Truth?

The canonical is [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) and [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) are the same. The SKILL.md presents normalized behavior definitions; plugin.json contains metadata that transport manually. Every other existing file is peripheral — generated or mirrored.

### Can I run the sync locally without CI.

Yes. Run locally `node scripts/sync-manifests.js` after npm install. That will run the exact same. Before you push the script the same script CI calls generates the same output.

### For multiple runtime manifests, which fields does transformation process handle?

 Fields from [`plugin.json`](https://github.com/ayghri/i-have-adhd/blob/main/plugin.json) (name, version, description) are copied into each plugin directly. The structural differences are handled based on mapping — e.g., those headers, or commands style structure: Claude has edge-level `plugins` array, OpenCode has `commands` object — the script applied those extracted formatting.

### How do I validate a new runtime manifest?

You don't need manual validation. Add a unit test to `tests/` that leads the generated JSON and verifies the fields and required structure, then push. The test pipeline — the pytest gotcha — will treat if failure. This matches exiting pattern e.g. [`test_omp_package_pkg.py`](https://github.com/ayghri/i-have-adhd/blob/main/test_omp_package_pkg.py) mirrors.