I run Cursor, Claude Code, and Codex in parallel. Each one supports custom skills — small instruction files that tell the AI how to do something specific. Over time I built a library of them: a code review pipeline, a changelog generator, a release notes writer, a few documentation helpers.
The problem: each tool reads skills from its own directory. Cursor reads .cursor/skills/. Claude Code reads .claude/skills/. Codex reads .agents/skills/. There is no shared state. Skills I built in Cursor simply weren’t there when I ran the same task in Claude Code or Codex. No error, no warning — just generic output where the configured behavior should have been.
The failure mode is silent substitution, not a crash.
TLDR
- Each AI coding tool reads custom skills from its own config directory — there is no shared state by default
- Without a sync system, skills drift the moment you improve one in a single tool
- A 30-line rsync script treats
.cursor/as the source of truth and mirrors it to.codex/and.claude/ - The SKILL.md format used is an open standard already supported by 20+ tools — not a personal hack
Why the tools diverge
Cursor reads skills from .cursor/skills/. Claude Code reads from .claude/skills/. Codex reads from .agents/skills/. Each tool looks in its own directory. There is no shared path, no discovery protocol across tools, no warning when a skill is missing from one context but present in another.
The natural outcome: skills accumulate in whichever tool you edit most. Cursor has the best editing experience for markdown files, so improvements happened there first. .cursor/ became the de facto source of truth before any deliberate decision was made. The other directories stayed empty or fell behind.
Manual copying doesn’t fail catastrophically. It drifts. You copy a skill once, then update it in Cursor and forget to copy it again. Two weeks later the Claude Code version is subtly wrong and you don’t notice until the output diverges.
The fix in one command
bash .scripts/sync-cursor-skills-to-tool-skills.sh
First run output:
synced -> /path/to/.codex/skills
synced -> /path/to/.claude/skills
synced -> /path/to/.codex/agents
synced -> /path/to/.claude/agents
synced -> /path/to/.codex/commands
synced -> /path/to/.claude/commands
Six lines. Each confirms one destination directory was synchronized. The full skill library — now present in all three tools from a single run.
What’s in the library
The .cursor/ directory holds three artifact types:
.cursor/skills/— skill directories, each a subdirectory with aSKILL.mdfile. Examples:review-pr,write-changelog,write-release-notes,generate-docs,summarize-diff..cursor/agents/— agent files for multi-step workflows:review-agent.md,release-agent.md,docs-agent.md..cursor/commands/— slash command files:deploy-preview.md,sync-skills.md.
Each skill follows the SKILL.md open standard. Minimum viable frontmatter:
---
name: write-changelog
description: Generates a changelog entry from a git diff or list of commits. Use when preparing a release and you need a structured, human-readable summary of what changed.
---
The name field must match the parent directory name exactly — that is a hard requirement of the spec, enforced during skill discovery.
How the script works
The full script — 29 lines:
#!/usr/bin/env bash
# Mirror shared AI artifacts from .cursor/ into .codex/ and .claude/ (repo root).
# Uses rsync --delete so destinations match the source (extra files in targets are removed).
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SRC_ROOT="${ROOT}/.cursor"
if [[ ! -d "${SRC_ROOT}" ]]; then
echo "error: missing source directory: ${SRC_ROOT}" >&2
exit 1
fi
for artifact in skills agents commands; do
src="${SRC_ROOT}/${artifact}"
if [[ ! -d "${src}" ]]; then
echo "error: missing source directory: ${src}" >&2
exit 1
fi
for tool_root in "${ROOT}/.codex" "${ROOT}/.claude"; do
dest="${tool_root}/${artifact}"
mkdir -p "${dest}"
rsync -a --delete "${src}/" "${dest}/"
echo "synced -> ${dest}"
done
done
Three details worth noting:
--delete is load-bearing. Without it, skills removed from Cursor remain in the targets forever. The destinations become an accumulation, not a mirror. The flag is what makes this a source-of-truth propagation instead of a one-way append.
Self-location. The script resolves the repo root from its own path using $(dirname "${BASH_SOURCE[0]}"). Run it from anywhere in the repo and it finds the right directories.
Early exit on missing source. set -euo pipefail plus explicit directory checks mean the script prints a clear error and stops if .cursor/ or any subdirectory is missing. No silent partial sync.
The open standard underneath
The reason this works across tools isn’t rsync — it’s that Cursor, Claude Code, and Codex all read the same file format from their respective config directories. SKILL.md is an open standard governed at agentskills.io, supported as of April 2026 by 20+ tools: Claude Code, Codex, Gemini CLI, GitHub Copilot, JetBrains Junie, Goose, Roo Code, Amp, and more.
The format is the portability layer. The script is just propagation.
This isn’t an isolated personal setup. The context-engineering-intro repo has 13.2k stars and uses the same .claude/commands/ structure. Vercel launched a skills CLI in January 2026 as the ecosystem-scale install path for the same format. Packmind sells a SaaS product targeting the exact same fragmentation problem at team scale. The problem is recognized. The format is settled.
A solo developer doesn’t need the SaaS version. One rsync script and a shared directory structure covers the same ground.
The Codex gap
Codex auto-discovers skills from .agents/skills/ — not .codex/skills/. The official Codex skills docs confirm this. The sync script currently mirrors to .codex/skills/, which means skills land in the right place for configuration storage but not for Codex auto-discovery.
Skills in .codex/skills/ can still be invoked explicitly. But Codex won’t surface them automatically when a task matches their description.
The fix is one additional target in the sync loop:
for tool_root in "${ROOT}/.codex" "${ROOT}/.claude" "${ROOT}/.agents"; do
That single change adds .agents/skills/, .agents/agents/, and .agents/commands/ as sync targets, putting skills where Codex’s scanner expects them.
The self-referential detail
The sync command itself is part of the library it manages.
.cursor/commands/sync-skills.md is a slash command. Once the initial sync runs, all three tools have it. From inside Cursor, Claude Code, or Codex, you can type:
/sync-skills
The command prompts the AI to run the bash script and confirm the six output lines. The sync system maintains itself without leaving the tool.
FAQ
Do I need all three tools for this to work?
No. Drop any target from the script. If you only use Cursor and Claude Code, remove .codex and .agents from the loop. Two lines.
What is a SKILL.md file and how is it different from a Cursor .mdc rule?
A SKILL.md is procedural — it teaches the AI how to do something specific and is loaded on demand when a task matches its description. A Cursor .mdc rule is declarative and always-on — applied to every interaction in its scope. Neither replaces the other. Rules set standards; skills teach workflows. The Cursor forum thread on skills vs rules confirms both coexist and neither is deprecated.
Does Codex auto-discover skills from .codex/skills/?
No — see the Codex gap section above. Add .agents to the sync targets to fix this. The Claude Code agent skills docs describe how Claude Code handles its own discovery, which does work correctly with .claude/skills/.
Should I commit .codex/ and .claude/ to the repo?
Depends on your workflow. If the repo is shared or you want skills available after clone, commit them. If the repo is personal and you always run the sync after setup, .gitignore the targets and treat sync as a post-clone step.
What happens when I delete a skill from .cursor/skills/?
The deletion propagates to both targets on the next sync run. rsync --delete makes the destinations exact mirrors, not accumulations.
Is the SKILL.md format proprietary to Cursor or Anthropic?
No. It is an open standard governed at agentskills.io, supported by 20+ tools as of April 2026.
Takeaway
.cursor/ was already the source of truth — improvements happened there first because the editing experience is better. The sync script formalizes that in 30 lines. The SKILL.md open standard means the approach stays portable as new tools are added.
One source of truth, one sync command. If you’re copying prompt files by hand, you’ve already lost — not because it fails, but because it drifts.
