How to Sync AI Skills Across Claude Code, Cursor, and Codex Without Losing Your Mind
You have the same code review skill in 3 directories. They've drifted apart. Here are 5 approaches - from manual scripts to full automation - ranked by effort and reliability.
If you use more than one AI coding tool - and 70% of developers do - you have a sync problem. Your code review skill in Claude Code says “check for null handling first.” The same skill in Cursor says “start with security checks.” They drifted apart three weeks ago and you didn't notice. Now your AI gives different feedback depending on which editor you opened this morning.
This guide covers 5 approaches to keeping AI skills synchronized across tools, from the simplest (copy-paste) to the most robust (dedicated tooling). Each approach includes real code you can use today, honest pros and cons, and guidance on when it's the right choice.
Approach 1: Manual Copy-Paste
The simplest approach: edit your skill in one tool's directory, then manually copy the file to each other tool's directory. No automation, no scripts, just you and your file manager. This is how most developers start because it requires zero setup. You make a change to your code review skill in ~/.claude/commands/code-review.md, then copy it to ~/.cursor/rules/code-review.md and ~/.codex/skills/code-review.md.
The problem isn't the first sync - it's the 47th. After a few weeks, you'll edit a skill in Cursor, forget to copy it to Claude, then edit the Claude version independently. Now you have two divergent copies and no idea which one is “correct.” With 15 skills across 3 tools, that's 45 files to track. Manual copy-paste scales linearly with pain.
| 1 | # The manual workflow |
| 2 | # 1. Edit the skill |
| 3 | vim ~/.claude/commands/code-review.md |
| 4 | |
| 5 | # 2. Copy to other tools (you'll forget step 2 eventually) |
| 6 | cp ~/.claude/commands/code-review.md ~/.cursor/rules/code-review.md |
| 7 | cp ~/.claude/commands/code-review.md ~/.codex/skills/code-review.md |
| 8 | cp ~/.claude/commands/code-review.md ~/.windsurf/skills/code-review.md |
| Pros | Cons |
|---|---|
| Zero setup required | Guaranteed drift over time |
| Works with any tool | No versioning or history |
| No dependencies | Scales terribly (N skills x M tools) |
| Good for 1-3 skills | No way to detect which copy is newest |
When to use:You have fewer than 5 skills and use 2 tools. You're just starting to build your skill library and don't want to invest in tooling yet.
Approach 2: Shell Alias / Sync Script
One step up from manual: write a shell script that copies skills from a single source directory to all tool directories. You designate one folder as the “source of truth” (e.g., ~/skills/) and the script distributes files to each tool. Run the script after every edit - or better, bind it to an alias so sync-skills does the job in one command.
This approach introduces the critical concept of a single source of truth. You never edit files in tool directories directly - you edit the source and run the sync. It's manual in the sense that you have to remember to run the command, but at least when you do run it, all tools update simultaneously.
| 1 | #!/bin/bash |
| 2 | # sync-skills.sh - copy skills from source to all tool directories |
| 3 | # Usage: sync-skills.sh [--dry-run] |
| 4 | |
| 5 | SOURCE_DIR="$HOME/skills" |
| 6 | DRY_RUN=false |
| 7 | [ "$1" = "--dry-run" ] && DRY_RUN=true |
| 8 | |
| 9 | TARGETS=( |
| 10 | "$HOME/.claude/commands" |
| 11 | "$HOME/.cursor/rules" |
| 12 | "$HOME/.codex/skills" |
| 13 | "$HOME/.windsurf/skills" |
| 14 | ) |
| 15 | |
| 16 | # Create target dirs if they don't exist |
| 17 | for target in "${TARGETS[@]}"; do |
| 18 | mkdir -p "$target" |
| 19 | done |
| 20 | |
| 21 | count=0 |
| 22 | for skill in "$SOURCE_DIR"/*.md; do |
| 23 | [ -f "$skill" ] || continue |
| 24 | filename=$(basename "$skill") |
| 25 | |
| 26 | for target in "${TARGETS[@]}"; do |
| 27 | if [ "$DRY_RUN" = true ]; then |
| 28 | echo "[dry-run] $skill -> $target/$filename" |
| 29 | else |
| 30 | cp "$skill" "$target/$filename" |
| 31 | count=$((count + 1)) |
| 32 | fi |
| 33 | done |
| 34 | done |
| 35 | |
| 36 | if [ "$DRY_RUN" = false ]; then |
| 37 | echo "Synced $count files to ${#TARGETS[@]} tool directories." |
| 38 | fi |
| 1 | # Add to your .zshrc or .bashrc |
| 2 | alias sync-skills="bash ~/scripts/sync-skills.sh" |
| 3 | alias ss="sync-skills" # even shorter |
| 4 | |
| 5 | # Usage |
| 6 | vim ~/skills/code-review.md # edit the source |
| 7 | ss # sync to all tools |
| Pros | Cons |
|---|---|
| Single source of truth | Must remember to run the script |
| One-command sync | One-directional (source to targets only) |
| Easy to customize | No format conversion (MDC vs MD) |
| Works offline, no dependencies | No versioning or change tracking |
When to use:You have 5-15 skills and want simple automation. You're comfortable editing in a central directory and don't need bidirectional sync.
Approach 3: Symbolic Links (ln -s)
Instead of copying files, create symbolic links from each tool's directory back to a single source file. When you edit the source, every tool sees the change instantly - no sync command needed. The tool directories contain symlinks, not real files, so there's only ever one actual copy of each skill.
This is the most elegant approach for solo developers on a single machine. It's truly zero-maintenance after setup: edit once, changes propagate everywhere. The downsides are cross-platform issues (Windows handles symlinks differently) and the fact that some tools may not follow symlinks correctly in all cases.
| 1 | #!/bin/bash |
| 2 | # setup-skill-symlinks.sh - create symlinks from tool dirs to source |
| 3 | # Run once to set up, then never think about syncing again |
| 4 | |
| 5 | SOURCE_DIR="$HOME/skills" |
| 6 | |
| 7 | declare -A TARGETS=( |
| 8 | ["claude"]="$HOME/.claude/commands" |
| 9 | ["cursor"]="$HOME/.cursor/rules" |
| 10 | ["codex"]="$HOME/.codex/skills" |
| 11 | ["windsurf"]="$HOME/.windsurf/skills" |
| 12 | ) |
| 13 | |
| 14 | for tool in "${!TARGETS[@]}"; do |
| 15 | target="${TARGETS[$tool]}" |
| 16 | mkdir -p "$target" |
| 17 | |
| 18 | for skill in "$SOURCE_DIR"/*.md; do |
| 19 | [ -f "$skill" ] || continue |
| 20 | filename=$(basename "$skill") |
| 21 | link_path="$target/$filename" |
| 22 | |
| 23 | # Remove existing file/link |
| 24 | [ -e "$link_path" ] && rm "$link_path" |
| 25 | |
| 26 | # Create symlink |
| 27 | ln -s "$skill" "$link_path" |
| 28 | echo "Linked: $link_path -> $skill" |
| 29 | done |
| 30 | done |
| 31 | |
| 32 | echo "Done. All tool directories now point to $SOURCE_DIR." |
| 33 | echo "Edit files in $SOURCE_DIR - changes appear in all tools instantly." |
| 1 | # Verify symlinks are working |
| 2 | ls -la ~/.claude/commands/ |
| 3 | # code-review.md -> /Users/you/skills/code-review.md |
| 4 | # test-writer.md -> /Users/you/skills/test-writer.md |
| 5 | |
| 6 | # Adding a new skill automatically |
| 7 | touch ~/skills/new-skill.md |
| 8 | # Then re-run the setup script (or add a watch) |
| Pros | Cons |
|---|---|
| True single source - zero drift possible | Windows symlinks require admin privileges |
| Instant propagation, no sync needed | Some tools may not follow symlinks |
| No background processes | Breaks if source directory moves |
| Easy to verify (ls -la shows links) | New skills require re-running setup |
When to use:Solo developer on macOS/Linux. You want fire-and-forget sync. You're comfortable with symlinks and your tools all support them.
Approach 4: Git Pre-Commit Hook
If your skills live in a git repository (and they should, for versioning), you can use a pre-commit hook to automatically sync skills to tool directories every time you commit. This approach combines version control with automatic deployment: commit your skill changes, and the hook copies updated files to all tool directories before the commit finalizes.
The advantage over a manual script is that the sync is automatic - it happens as part of your git workflow, not as a separate step you might forget. The advantage over symlinks is that it works across machines (each machine's hook runs locally) and integrates with your version control history.
| 1 | #!/bin/bash |
| 2 | # .git/hooks/pre-commit (or .husky/pre-commit) |
| 3 | # Auto-sync skills to tool directories on every commit |
| 4 | |
| 5 | SKILLS_DIR="$(git rev-parse --show-toplevel)/skills" |
| 6 | |
| 7 | # Only run if skills directory has staged changes |
| 8 | if git diff --cached --name-only | grep -q "^skills/"; then |
| 9 | echo "🔄 Syncing updated skills to tool directories..." |
| 10 | |
| 11 | TARGETS=( |
| 12 | "$HOME/.claude/commands" |
| 13 | "$HOME/.cursor/rules" |
| 14 | "$HOME/.codex/skills" |
| 15 | ) |
| 16 | |
| 17 | # Get list of changed skill files |
| 18 | CHANGED=$(git diff --cached --name-only -- "skills/*.md") |
| 19 | |
| 20 | for file in $CHANGED; do |
| 21 | filename=$(basename "$file") |
| 22 | source="$SKILLS_DIR/$filename" |
| 23 | |
| 24 | # Skip deleted files |
| 25 | [ -f "$source" ] || continue |
| 26 | |
| 27 | for target in "${TARGETS[@]}"; do |
| 28 | mkdir -p "$target" |
| 29 | cp "$source" "$target/$filename" |
| 30 | done |
| 31 | |
| 32 | echo " Synced: $filename -> ${#TARGETS[@]} directories" |
| 33 | done |
| 34 | |
| 35 | # Handle deleted skills |
| 36 | DELETED=$(git diff --cached --diff-filter=D --name-only -- "skills/*.md") |
| 37 | for file in $DELETED; do |
| 38 | filename=$(basename "$file") |
| 39 | for target in "${TARGETS[@]}"; do |
| 40 | [ -f "$target/$filename" ] && rm "$target/$filename" |
| 41 | echo " Removed: $target/$filename" |
| 42 | done |
| 43 | done |
| 44 | |
| 45 | echo "✅ Skill sync complete." |
| 46 | fi |
| 1 | # Setup with Husky (recommended for team projects) |
| 2 | npx husky init |
| 3 | cp sync-hook.sh .husky/pre-commit |
| 4 | chmod +x .husky/pre-commit |
| 5 | |
| 6 | # Or manual git hook setup |
| 7 | cp sync-hook.sh .git/hooks/pre-commit |
| 8 | chmod +x .git/hooks/pre-commit |
| 9 | |
| 10 | # Now just commit normally - sync happens automatically |
| 11 | git add skills/code-review.md |
| 12 | git commit -m "update code review skill" |
| 13 | # Output: 🔄 Syncing updated skills to tool directories... |
| 14 | # Synced: code-review.md -> 3 directories |
| 15 | # ✅ Skill sync complete. |
| Pros | Cons |
|---|---|
| Automatic - sync on every commit | Only syncs on commit, not on save |
| Full version history via git | Hook setup required per machine |
| Only syncs changed files | Hooks can be bypassed (--no-verify) |
| Team-friendly with Husky | One-directional (repo to local tools) |
When to use: Your skills are in a git repo (personal or team). You want version history and automatic sync without thinking about it. You can tolerate a delay between saving and syncing (only happens at commit time).
Approach 5: Dedicated Tool (Praxl)
Purpose-built skill management tools handle everything the DIY approaches can't: bidirectional sync, format conversion between tools, quality scoring, team sharing, and version history with a UI. Praxl is one such tool - it provides a web editor for writing skills and a CLI for deploying them to any supported tool's directory.
The key differentiator is bidirectional awareness. Unlike scripts and symlinks that push from source to targets, Praxl can detect when you've edited a skill directly in a tool's directory and flag the conflict. It also handles format conversion: your SKILL.md can be automatically adapted to Cursor's MDC format with appropriate glob patterns, or stripped down for tools that expect simpler Markdown.
| 1 | # Typical workflow with a dedicated skill manager |
| 2 | |
| 3 | # 1. Write/edit skills in the web editor or CLI |
| 4 | # (versioned, quality-scored, backed up) |
| 5 | |
| 6 | # 2. Deploy to all tools with one command |
| 7 | praxl deploy --all |
| 8 | # Deploying 12 skills to 3 tools... |
| 9 | # ✅ Claude Code: 12 skills synced |
| 10 | # ✅ Cursor: 12 skills synced (converted to MDC) |
| 11 | # ✅ Codex CLI: 12 skills synced |
| 12 | # Done. |
| 13 | |
| 14 | # 3. Detect drift (skills edited directly in tool dirs) |
| 15 | praxl status |
| 16 | # ⚠️ code-review.md modified in ~/.cursor/rules/ |
| 17 | # (last Praxl deploy: 3 days ago, local edit: 2 hours ago) |
| 18 | # Run 'praxl diff code-review' to see changes |
| 19 | |
| 20 | # 4. Pull local changes back into the manager |
| 21 | praxl pull code-review --from cursor |
| 22 | # Pulled changes from ~/.cursor/rules/code-review.md |
| 23 | # New version: 1.3.1 |
| Pros | Cons |
|---|---|
| Bidirectional sync and drift detection | Requires installing an additional tool |
| Format conversion (SKILL.md to MDC) | Learning curve for CLI or web UI |
| Built-in quality scoring | External dependency for your workflow |
| Team sharing and collaboration | May not support every tool immediately |
| Version history with rollback | Cloud-synced (data leaves your machine) |
When to use: You have 10+ skills across 2+ tools. You work on a team that shares skills. You want quality scoring, version history, and bidirectional sync without building it yourself.
Final Comparison: All 5 Approaches Ranked
Here's how the five approaches compare across the dimensions that matter most. Score: 1 (worst) to 5 (best) for each dimension.
| Approach | Setup Effort | Reliability | Bidirectional | Team-Friendly | Versioning |
|---|---|---|---|---|---|
| Manual copy-paste | 5 (none) | 1 | 1 | 1 | 1 |
| Shell script/alias | 4 | 3 | 1 | 2 | 1 |
| Symbolic links | 3 | 4 | N/A (same file) | 1 | 1 |
| Pre-commit hook | 2 | 4 | 1 | 4 | 5 |
| Dedicated tool | 2 | 5 | 5 | 5 | 5 |
Choosing the Right Approach
Don't overcomplicate this. Start with the simplest approach that solves your current pain, and upgrade when the pain returns. Here's a practical decision tree:
1-4 skills, solo developer
Start with manual copy-paste. The overhead of any automation is higher than just copying a few files. Move to symlinks when you hit 5 skills.
5-15 skills, solo developer, single machine
Use symbolic links. Zero maintenance after setup. One file, all tools see it. If you need to version skills, put the source directory in a git repo.
5-15 skills, multiple machines
Use the shell script approach with skills in a git repo. Clone the repo on each machine, run the sync script. The pre-commit hook variant automates the local sync.
Any number of skills, team environment
Use the pre-commit hook if your team is comfortable with git hooks, or a dedicated tool if you want quality scoring, drift detection, and a web UI. The hook is free; the tool adds features you'll appreciate at scale.
15+ skills, format conversion needed
Use a dedicated tool. At this scale, you need format conversion (SKILL.md to MDC), drift detection, and team governance. DIY scripts become maintenance burdens.
The Cost of Not Syncing
Let's quantify the waste. A developer with 15 skills across 3 tools, using manual copy-paste, spends roughly 45 minutes per week on skill-related friction: discovering drift, comparing files, resolving conflicts, and copying updates. That's 39 hours per year - almost a full work week - spent on file management instead of building software. For a team of 5, multiply by 5.
The hidden cost is worse: inconsistent AI behavior across tools erodes trust. When your code review skill gives different feedback in Cursor than in Claude, you stop trusting either tool's output. You start manually verifying AI suggestions instead of acting on them. The productivity gain from AI skills diminishes every time you catch a discrepancy.
Pick an approach, implement it today, and move on. The best sync strategy is the one you actually use - not the most technically elegant one collecting dust in your “I'll set this up later” list.
Manage your skills with Praxl
Edit once, deployed to every AI tool. Version history, AI review, team sharing.
Try Praxl free
Praxl