Skip to content

Sync and Share

FieldValue
TypeSkill Resource
Source~/.copilot/skills/skill-forge/references/sync-and-share.md
DescriptionNot specified

Source Content

Sync and Share

How to move skills between tools, share them with teams, and keep copies in sync.

The reality

All three tools (Claude Code, Codex, GitHub Copilot) read the same SKILL.md format (name + description frontmatter, plus optional references/, scripts/, assets/). So “conversion” is rarely a rewrite — the real work is doing the copy safely:

  1. Validate the skill is portable (required frontmatter, name matches folder, no dead links).
  2. Normalize frontmatter to the target tool’s dialect when asked (--strict).
  3. Clean-copy the whole folder, excluding __pycache__/, *.pyc, .DS_Store, .git/, etc.

A plain cp -r skips none of that — it can install a skill under the wrong id and carries build junk into a teammate’s repo. Always go through scripts/skill_sync.py.

Install locations

Each tool keys a skill by its folder name, so each destination gets <base>/<skill-name>/.

ToolGlobal skills directoryNotes
Claude Code~/.claude/skills/<name>/May not exist yet; sync creates it. Project skills also load from <repo>/.claude/skills/.
Codex~/.codex/skills/<name>/~/.codex/skills/.system/ is reserved — never sync into it.
Copilot~/.copilot/skills/<name>/The source of truth; a real git repo.
Team / project folder<path>/<name>/Any folder passed with --dir, e.g. a shared documentation repo.

Frontmatter dialects

Extra keys are harmless — every tool ignores frontmatter it does not recognize — so the default is to preserve every key exactly. Pass --strict only when a destination should not see foreign keys.

name and description are required everywhere and never dropped.

Claude Code

Recognizes name, description, license, allowed-tools, metadata, compatibility. Uses description for triggering; does not read a triggers: list.

Codex

Recognizes name, description, license, metadata. Codex’s own skill-creator uses metadata.short-description for a terse label. Does not read triggers:.

Copilot

Recognizes name, description, license, metadata, and a triggers: list. This is the only dialect that reads triggers:.

Generic (--dir folders)

Defaults to the universal core — name, description, license, metadata. Override with --tool claude|codex|copilot when a --dir copy is destined for a specific tool.

Commands

list

Show every skill in a source tree with the first sentence of its description.

Terminal window
python3 scripts/skill_sync.py list [--source DIR]

validate

Check that skill folders are well-formed and portable. Exits non-zero if any errors are found, so it works as a CI gate.

Terminal window
python3 scripts/skill_sync.py validate <skill-dir>... [--target claude|codex|copilot|generic]

What it checks:

  • SKILL.md present with valid --- frontmatter.
  • Required keys name and description present.
  • name is a valid slug (^[a-z0-9][a-z0-9-]*$, ≤ 64) and equals the folder name.
  • description non-empty (warning if over ~1024 chars).
  • Relative reference links resolve to existing files.
  • Frontmatter keys foreign to the target dialect (warning).

sync

Validate, then clean-copy skills to one or more destinations. A skill that fails validation for any target dialect is skipped with its errors printed — never partially copied.

Terminal window
python3 scripts/skill_sync.py sync <name-or-path>... \
[--all] [--to claude,codex,copilot] [--dir PATH]... \
[--tool DIALECT] [--strict] [--force] [--dry-run] [--source DIR]

Selecting skills:

  • Positional <name-or-path> — bare skill name (resolved under --source) or a path to a skill folder. Repeatable.
  • --all — every skill in --source. Usually paired with a single --to.
  • --source DIR — where bare names are resolved. Default: ~/.copilot/skills.

Choosing destinations (at least one required):

  • --to TOOLS — comma-separated tool names: claude,codex,copilot. Each maps to that tool’s global skills directory.
  • --dir PATH — an arbitrary destination folder; the skill lands in <PATH>/<name>/. Repeatable.

Controlling the copy:

  • --tool DIALECT — frontmatter dialect for --dir targets. Default: generic.
  • --strict — drop frontmatter keys the target dialect does not recognize.
  • --prompt — also write <name>.prompt.md (a paste-into-ChatGPT prompt) into each --dir share. Ignored for --to tool targets.
  • --force — overwrite an existing destination. Without it, existing destinations are reported as EXISTS and left untouched.
  • --dry-run — print planned actions and would-be-stripped keys; write nothing.

prompt

Flatten a skill into one self-contained message a person can paste into ChatGPT (or any chat LLM) that has no agent, filesystem, or way to run scripts. Every text reference the skill ships is inlined (not just the ones SKILL.md links).

Terminal window
python3 scripts/skill_sync.py prompt <name-or-path> [--source DIR] [--out FILE]

remove

Clean up deleted skill copies from destination directories. Run this after merging or deleting a skill from the source tree to propagate the deletion to Claude, Codex, and any team folders.

Terminal window
python3 scripts/skill_sync.py remove <name>... \
[--to claude,codex,copilot] [--dir PATH]... [--dry-run]

The remove command:

  • Takes skill names (not paths) from the source tree’s .copilot/skills/ registry.
  • Removes matching folders from each --to tool target and --dir folders.
  • Exits 0 on success, 1 if a skill name is invalid or removal fails.

Used in the post-commit hook to propagate deleted skills:

Terminal window
python3 "$SYNC" remove "${gone[@]}" --to claude,codex "${DRYFLAG[@]}"

Recipes

Share only certain skills with a team folder

Terminal window
python3 scripts/skill_sync.py sync technical-writing docs-that-teach \
--dir ~/Code/maryland/documentation --strict --prompt
python3 scripts/skill_sync.py sync adr \
--dir ~/Code/maryland/documentation --strict --prompt

--prompt drops a <name>.prompt.md in each folder for teammates on ChatGPT; drop it if everyone on the team uses an agent.

Install one skill in every tool

Terminal window
python3 scripts/skill_sync.py sync css --to claude,codex,copilot --force

Convert one skill to Codex format and install it

Terminal window
python3 scripts/skill_sync.py sync agile-product-owner --to codex --strict --force

--strict drops the Copilot-only triggers: block Codex does not use.

Propagate the whole library to Claude Code

Terminal window
python3 scripts/skill_sync.py sync --all --to claude --dry-run # preview
python3 scripts/skill_sync.py sync --all --to claude --force # do it

Remove deleted skills after a consolidation

Terminal window
# After merging skill-creator + skill-sync into skill-forge and deleting the source dirs:
python3 scripts/skill_sync.py remove skill-creator skill-sync --to claude,codex --force

Junk that is never copied

Build and editor noise so destinations stay reviewable: Directories: __pycache__, .git, .hg, .svn, .pytest_cache, .mypy_cache, .ruff_cache, .venv, venv, node_modules, .idea, .vscode. Files: *.pyc, *.pyo, *.pyd, .DS_Store, *.swp, *.swo, Thumbs.db, *.egg-info, .coverage.

This is the main reason to never hand-copy: cp -r would install machine-specific cruft into every teammate’s folder.

Workflow

  1. See what’s availablepython3 scripts/skill_sync.py list.
  2. Dry-run first — add --dry-run to any sync to see exactly what would be written.
  3. Sync — drop --dry-run. Add --force to overwrite existing destinations.
  4. Confirm — the command prints one line per destination.

Rules that keep copies trustworthy

  • Validate before writing, always. A skill with a name/folder mismatch or a dead reference is skipped with an explanation — never partially copied.
  • Never hand-copy. cp -r drags junk and skips validation; route every move through the script.
  • Preserve by default, strip on purpose. Keep all frontmatter unless the user wants a clean single-tool copy, then use --strict.
  • Source of truth is ~/.copilot/skills/. Edit skills there and sync outward; do not edit a downstream copy and sync backward, or the tools will drift.