# How the Cursor Mirror Sync Keeps the Canonical SKILL.md in Perfect Sync

> Discover how cursor mirror sync maintains the canonical SKILL.md in perfect sync. Learn about the `ayghri/i-have-adhd` repository's workflow to ensure data integrity and prevent drift.

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

---

**TLDR: The `ayghri/i-have-adhd` repository enforces a canonical [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) as the single source of truth and uses a GitHub Actions workflow that runs `cmp` to fail any pull request where the [`.cursor/skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/.cursor/skills/i-have-adhd/SKILL.md) mirror copy has drifted.**

The `ayghri/i-have-adhd` repository stores the authoritative definition of its ADHD coaching skill in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). However, Cursor-compatible tools and runtimes expect the skill to live in the hidden path [`.cursor/skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/.cursor/skills/i-have-adhd/SKILL.md). Because these are two separate file copies (not a symlink), they can easily diverge — especially on Windows clones or when the repository is downloaded as a ZIP archive. This article explains exactly how the cursor mirror sync mechanism enforces that both files always match.

## Why the Cursor Mirror Copy Exists

The core problem is straightforward: a single skill definition must serve two different consumers.

**The canonical file** ([`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md)) is the human-maintained, authoritative definition of the skill. It's what contributors edit, review, and discuss in pull requests.

**The mirror copy** ([`.cursor/skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/.cursor/skills/i-have-adhd/SKILL.md)) is the file that Cursor-compatible runtimes actually load when the skill is invoked.

Since these are independent copies rather than symlinks, they can diverge. A symlink would solve the problem on Linux and macOS, but Windows clones and ZIP downloads destroy symlinks by default. The project solves this with an automated CI enforcement instead of relying on filesystem features.

## How the Sync Workflow Enforces the Cursor Mirror

The sync mechanism is built around a single GitHub Actions workflow located at [[`.github/workflows/cursor-skill-sync.yml`](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflows/cursor-skill-sync.yml)](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflows/cursor-skill-sync.yml). It works through three stages.

### Stage 1: Trigger Condition

The workflow triggers on two types of events:

- Every pull request that touches either the canonical file [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) or any file inside `.cursor/skills/`
- Any push to the `main` branch

This ensures that even a trivial whitespace change to the canonical skill triggers the sync check.

### Stage 2: The `cmp` Comparison

Once triggered, the job checks out the repository and runs a file comparison with `cmp`:

```bash
cmp skills/i-have-adhd/SKILL.md .cursor/skills/i-have-adhd/SKILL.md \
  || { echo "::error::.cursor copy is out of sync. Run: cp skills/i-have-adhd/SKILL.md .cursor/skills/i-have-adhd/SKILL.md"; exit 1; }

```

If the files differ, `cmp` returns a non-zero exit code. The `||` conditional catches that, prints a clearly formatted error message via GitHub Actions' `::error::` annotation, and exits with status 1 — failing the job.

### Stage 3: Merge Block

Because the workflow fails the check when the comparison fails, GitHub blocks the pull request from being allowed. This forces every contributor to sync the mirror before merging, either manually or with a script. The result is a **single source of truth** with a fully automated consistency check.

## How to Fix a Sync Drift (Manual Workflow)

When the CI check fails, the error message itself tells you the exact fix. From the repository root, run:

```bash

# From the repository root

cp skills/i-have-adhd/SKILL.md .cursor/skills/i-have-adhd/SKILL.md
git add .cursor/skills/i-have-adhd/SKILL.md
git commit -m "Sync Cursor mirror of SKILL.md"

```

After pushing the fix, the workflow will re-run and pass because the byte-level `cmp` now matches.

## The Automated Check in Action

Here is the simplified YAML that CI runs to enforce the mirror relationship:

```yaml

# .github/workflows/cursor-skill-sync.yml

- name: Fail if the .cursor copy differs from SKILL.md
  run: |
    cmp skills/i-have-adhd/SKILL.md .cursor/skills/i-have-adhd/SKILL.md || {
      echo "::error::.cursor copy is out of sync. Run: cp skills/i-have-adhd/SKILL.md .cursor/skills/i-have-adhd/SKILL.md"
      exit 1
    }

```

No custom scripting logic, no hash comparisons — just a single command-line utility that does exactly what it says.

## Key Files in the Sync System

| File | Role | Link |
|------|------|------|
| Canonical skill definition | The single source of truth for the i-have-adhd skill | [[`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md)](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) |
| Cursor mirror copy | The file read by Cursor-compatible runtimes | [[`.cursor/skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/.cursor/skills/i-have-adhd/SKILL.md)](https://github.com/ayghri/i-have-adhd/blob/main/.cursor/skills/i-have-adhd/SKILL.md) |
| Sync workflow | CI job that enforces the mirror relationship | [[`.github/workflows/cursor-skill-sync.yml`](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflows/cursor-skill-sync.yml)](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflows/cursor-skill-sync.yml) |
| Agent guide | Documentation of the overall sync policy | [[`AGENTS.md`](https://github.com/ayghri/i-have-adhd/blob/main/AGENTS.md)](https://github.com/ayghri/i-have-adhd/blob/main/AGENTS.md) |

## Why This Approach Works

This design supports any platform, including Windows where symlinks are problematic. It also gives contributors a deterministic, reproducible error message with the exact command to run — there's no guesswork about how to recover from drift. The result is a canonical ↔ mirror relationship that's robust, auditable, and self-documenting in the CI output.

## Summary

- The cursor mirror sync relies on a single GitHub Actions workflow at [`.github/workflows/cursor-skill-sync.yml`](https://github.com/ayghri/i-have-adhd/blob/main/.github/workflows/cursor-skill-sync.yml)
- The workflow triggers on any PR or push touching either the canonical [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md) or its `.cursor/` copy
- A `cmp` comparison fails the job instantly, prints the exact `cp` command, and blocks the merge
- The design is platform-agnostic because it avoids symlinks entirely
- The human-readable fix is always one command: `cp skills/i-have-adhd/SKILL.md .cursor/skills/i-have-adhd/SKILL.md`

## Frequently Asked Questions

### Does the cursor mirror sync use a symlink or a copy?

The mirror is a separate file copy. The repository deliberately avoids symlinks because they don't survive on Windows filesystems or in ZIP downloads, which would silently break the skill mapping. The workflow uses byte-level comparison instead.

### What happens if I forget to sync the mirror in my pull request?

The CI pipeline fails the check with a specific error message that clearly instructs you to run `cp skills/i-have-adhd/SKILL.md .cursor/skills/i-have-adhd/SKILL.md`. The merge request is blocked until you commit that mirrored file.

### Can I edit the `.cursor/skills/` file directly instead of the canonical one?

No. The canonical path [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) is the only place you should edit. The shadow is automatically enforced to match via the workflow — editing the mirror directly would cause the reverse drift and fail the same check.

### Which events trigger the sync check in CI?

The workflow runs whenever a pull request touches either [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) or any file under `.cursor/skills/`, plus every push to `main`. This guarantees the sync check never misses a change that could create drift.