# Skill Sync

> Find every place agent skills live on this machine (Claude Code, Codex, Cursor; user-level and project-level) and bring them into sync, bidirectionally, newest copy wins. Use when the user asks to sync skills between tools, says a skill is missing or stale in one tool, wants to know which tools share a skills directory, or after editing a skill that other tools should see. Reports before it changes anything; backs up anything it overwrites; never deletes.

- Skill: `dreamers-laboratory/skill-sync` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add dreamers-laboratory/skill-sync`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dreamers-laboratory/skill-sync/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: dreamers-laboratory (https://skillmd.com/u/dreamers-laboratory)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/dreamers-laboratory/skill-sync

---


# Skill Sync

Three tools, three skill directories, and a skill edited in one of them silently ages in the other two. This skill finds the directories, shows the drift, and syncs them with the newest copy winning.

All commands run `scripts/skill_sync.py` from this skill's folder. Python 3 only, no dependencies.

## Where skills live

| tool | user-level | project-level |
|---|---|---|
| Claude Code | `~/.claude/skills` | `<repo>/.claude/skills` |
| Codex | `~/.codex/skills` | `<repo>/.codex/skills` |
| Cursor | `~/.cursor/skills` | `<repo>/.cursor/skills` |

The script checks all six, plus any `--store NAME=PATH` you add or `SKILL_SYNC_STORES=name=path:name=path` in the environment. Two paths that resolve to the same directory, which is what a symlink setup looks like, are treated as one store and reported as such. Cursor's own bundled skills (`~/.cursor/skills-cursor`) are never touched.

A skill is a directory containing `SKILL.md`. Anything else in a store is ignored.

## Workflow

1. **Look first.**

   ```bash
   python3 scripts/skill_sync.py status
   ```

   One row per skill, one column per store: `same`, `newest`, `older`, or `missing`, and the decision the sync would make. Read this to the user before doing anything. If two stores are symlinked, say so; there is nothing to sync between them.

2. **Show the plan.**

   ```bash
   python3 scripts/skill_sync.py plan
   ```

   Every copy the sync would make, with the winning store and its timestamp, and every conflict. A conflict is two copies that differ but carry the same modification time; the script will not guess. Ask the user which store is right, or pass `--prefer STORE`.

3. **Apply.**

   ```bash
   python3 scripts/skill_sync.py apply
   ```

   Copies newest over older or missing, preserving file timestamps so the next run sees everything in sync. Every overwritten copy is moved to `~/.skill-sync/backups/<timestamp>/<store>/<skill>` first, and each run appends to `~/.skill-sync/log.jsonl`. Then run `status` again and confirm every row reads `same`.

## Options worth knowing

- `--only NAME` (repeatable) syncs one skill. `--exclude NAME` or `--exclude prefix*` keeps private or tool-specific skills out.
- `--no-project` ignores project-level stores; `--project DIR` points at a repo other than the current one.
- `--prefer STORE` breaks ties. It does not override a clearly newer copy elsewhere.
- `--json` for machine-readable output.

## Rules

- Never run `apply` without showing `plan` or `status` first. The user should see what will move.
- Newest wins is a heuristic, not a truth. If a store looks like a stale snapshot (dozens of `older` rows, one date), say that and consider `--prefer` for the live store instead of trusting timestamps blindly.
- Do not sync skills that contain personal, client, or credential material into a store that syncs to a cloud account unless the user says so. `--exclude` exists for this.
- If a tool does not follow symlinks, keep it as a real directory and let the sync copy into it; do not replace it with a symlink on the user's behalf.
- Report what changed, where the backups are, and any conflict left open.

