Cross-platform skill & MCP sync for Claude Code CLI, Codex CLI, and Cursor
Synchronize your skills and MCP servers across Claude Code CLI, Codex CLI, and Cursor.
Source of truth: Claude Code CLI (~/.claude/).
~/.claude/skills/ → ~/.cursor/skills-cursor/ and ~/.codex/skills/<project>/.claude/skills/ → <project>/.cursor/skills/ and <project>/.codex/skills/Two modes:
Default: If the user doesn't specify a mode, run audit.
These are HARD GATES — never violate them:
references/native-skills-registry.md)<TOKEN>sk-, Bearer , AQ., bot tokens matching \d+:AA, long hex/base64 strings~/.codex/auth.json~/ in all displayed outputProject scan root (override if your projects live elsewhere):
SCAN_ROOT: ~/Developer/
The skill scans this directory for project-local skills and per-project MCP configs. Adjust if your projects are in a different location (e.g. ~/Projects/, ~/src/).
Check which platforms are installed:
# Claude Code CLI (required)
[ -d ~/.claude/skills ] && echo "claude: YES" || echo "claude: NO"
# Cursor
[ -d ~/.cursor ] && echo "cursor: YES" || echo "cursor: NO"
# Codex CLI
[ -d ~/.codex ] && echo "codex: YES" || echo "codex: NO"
~/.claude/skills/ doesn't exist, stop and explain how to install Claude Code.~/.cursor/skills-cursor/, ~/.codex/skills/.Report detected platforms to the user before proceeding.
ls -la ~/.claude/skills/
Enumerate all entries. Each entry is a skill (directory or symlink to a directory containing SKILL.md).
Read references/native-skills-registry.md from this skill's directory. Extract:
CURSOR_NATIVE: list of Cursor native skill namesCODEX_NATIVE: list of Codex native skill namesFor each global CLI skill name:
Cursor check:
native-skipls -la ~/.cursor/skills-cursor/<name> ~/.claude/skills/<name> → syncedwrong-targetMISSINGCodex check:
native-skipls -la ~/.codex/skills/<name>~/.claude/skills/<name> → syncedwrong-target MISSING## Global Skills Audit
| Skill | CLI | Cursor | Codex |
|-------|-----|--------|-------|
| my-skill | ✅ | ✅ synced | MISSING |
| atlas | ✅ | ✅ synced | native-skip |
...
Summary: N global skills, M gaps (K Cursor + L Codex)
# Scan SCAN_ROOT:
find <SCAN_ROOT> -path "*/.claude/skills/*" -iname "skill.md" -not -path "*/.claude/worktrees/*" -type f 2>/dev/null
Note: The
-not -path "*/.claude/worktrees/*"filter excludes temporary agent worktree copies (.claude/worktrees/agent-*/) which clone the project's.claude/directory and are not real projects.
For each match:
<project>/.claude/skills/<name>/.claude/SKILL.md as one project-local skill~/.codex/skills/ or ~/.cursor/skills-cursor/For each project-local CLI skill name in project <project>:
Cursor check:
native-skipls -la <project>/.cursor/skills/<name><project>/.claude/skills/<name> → syncedwrong-targetMISSINGCodex check:
native-skipls -la <project>/.codex/skills/<name><project>/.claude/skills/<name> → syncedwrong-targetMISSING## Project-Local Skills Audit
| Project | Skill | Claude | Cursor | Codex |
|---------|-------|--------|--------|-------|
| notes-transcriber | pipelineall | ✅ | MISSING | ✅ synced |
...
Summary: N project-local skills, M gaps
# CLI — JSON
cat ~/.claude.json
# → parse mcpServers section
# Cursor — JSON (may not exist yet)
cat ~/.cursor/mcp.json 2>/dev/null || echo "{}"
# Codex — TOML
cat ~/.codex/config.toml 2>/dev/null || echo ""
# → find all [mcp_servers.*] section names
For each server in CLI's mcpServers:
command field → stdiourl field or type: "http" → HTTPFor each CLI MCP server:
Cursor check:
mcpServers → syncedMISSINGCodex check:
unsupported (not MISSING)[mcp_servers.*] → syncedMISSING## MCP Servers Audit (Global)
| Server | Type | CLI | Cursor | Codex |
|--------|------|-----|--------|-------|
| playwright | stdio | ✅ | ✅ synced | MISSING |
| my-api | HTTP | ✅ | MISSING | unsupported |
...
Summary: N servers, M gaps
# Scan SCAN_ROOT:
find <SCAN_ROOT> -maxdepth 2 -name ".mcp.json" -type f 2>/dev/null
.mcp.jsonFirst, read the file and check if mcpServers is empty ({}). If empty — skip the project entirely (do NOT create platform configs for empty MCP).
If non-empty, check if corresponding platform configs exist:
<project>/.cursor/mcp.json<project>/.codex/config.toml## MCP Servers Audit (Per-Project)
| Project | CLI (.mcp.json) | Cursor | Codex |
|---------|-----------------|--------|-------|
| my-project | ✅ 3 servers | MISSING | MISSING |
...
For cross-platform compatibility, CLAUDE.md should be a symlink to AGENTS.md in every project that has AGENTS.md. This ensures Codex (which reads claude.md via project_doc_fallback_filenames) gets the full project instructions.
for project_dir in <SCAN_ROOT>/*/; do
[ -f "$project_dir/AGENTS.md" ] || continue
# Check if CLAUDE.md is a symlink to AGENTS.md
done
CLAUDE.md is symlink → AGENTS.md: symlinkedCLAUDE.md is symlink → other target: WRONG-TARGETCLAUDE.md exists but is a regular file: not-symlinkedCLAUDE.md doesn't exist: MISSING## CLAUDE.md → AGENTS.md Symlink
| Project | Status |
|---------|--------|
| my-project | symlinked |
| old-project | not-symlinked |
...
Summary: N projects, M gaps
Codex CLI requires explicit trust_level = "trusted" for each project. Audit for stale and missing entries.
grep -E '^\[projects\.' ~/.codex/config.toml 2>/dev/null | sed 's/\[projects\."\(.*\)"\]/\1/'
For each extracted path:
okstalefor dir in <SCAN_ROOT>/*/; do
[ -e "$dir/.git" ] || continue # -e, not -d: .git can be a file in worktrees
# Check if path is in Codex trusted projects
done
Projects in SCAN_ROOT with .git that are NOT in Codex config → MISSING.
## Codex Trusted Projects
| Project | Status |
|---------|--------|
| ~/Developer/my-project | ok |
| ~/Developer/old-deleted | ⚠️ stale |
| ~/Developer/new-project | MISSING |
...
Summary: N total, M stale, K missing
IMPORTANT: Do NOT auto-remove stale entries or auto-add missing ones. Report only — adding trust requires user confirmation.
Combine all audit results:
## Ecosystem Audit Summary
Platforms: Claude Code CLI ✅, Cursor ✅, Codex ✅
Skills (global): N total, M synced, K gaps
Skills (project-local): N total, M synced, K gaps
MCP (global): N total, M synced, K gaps, L unsupported (HTTP in Codex)
MCP (per-project): N projects, M synced, K gaps
CLAUDE.md symlink: N total, M gaps
Codex trusted projects: N total, M stale, K missing
→ Run `/ecosystem-sync sync` to fix N gaps
(or `/ecosystem-sync sync --dry-run` to preview)
If mode is audit, STOP HERE.
For each global skill with status MISSING or wrong-target:
Cursor:
mkdir -p ~/.cursor/skills-cursor
ln -sf ~/.claude/skills/<name> ~/.cursor/skills-cursor/<name>
Codex:
mkdir -p ~/.codex/skills
ln -sf ~/.claude/skills/<name> ~/.codex/skills/<name>
Verify each symlink after creation:
ls -la ~/.cursor/skills-cursor/<name>
# Should show: <name> -> /Users/.../.claude/skills/<name>
For each project-local skill <project>/.claude/skills/<name> with status MISSING or wrong-target:
Cursor:
mkdir -p <project>/.cursor/skills
ln -sf <project>/.claude/skills/<name> <project>/.cursor/skills/<name>
Codex:
mkdir -p <project>/.codex/skills
ln -sf <project>/.claude/skills/<name> <project>/.codex/skills/<name>
Verification:
ls -la <project>/.codex/skills/<name>
# Should show: <name> -> /Users/.../<project>/.claude/skills/<name>
Rules:
~/.codex/skills/ or ~/.cursor/skills-cursor/Read conversion rules from references/mcp-format-guide.md.
For each MISSING CLI MCP in Cursor:
~/.cursor/mcp.json (create {"mcpServers":{}} if doesn't exist)type field<TOKEN>)For each MISSING stdio CLI MCP in Codex:
~/.codex/config.toml[mcp_servers.<name>]
command = "<command>"
args = [<args as TOML array>]
env is present and non-empty: add [mcp_servers.<name>.env] sub-sectioncwd is present: add cwd = "<value>"⚠️ <name>: HTTP MCP not supported in Codex CLI[notice] section if it exists, otherwise append to endFor each project with .mcp.json but missing platform configs:
<project>/.mcp.json<project>/.cursor/mcp.json using same format conversion as global (Step 10a)<project>/.mcp.json<project>/.codex/config.toml with [mcp_servers.*] sectionsFor each project with AGENTS.md where CLAUDE.md has status MISSING or not-symlinked:
CLAUDE.md is a regular file containing only @AGENTS.md reference and comments:rm <project>/CLAUDE.md
ln -s AGENTS.md <project>/CLAUDE.md
CLAUDE.md has unique content beyond @AGENTS.md: skip with note — manual migration neededCLAUDE.md doesn't exist:ln -s AGENTS.md <project>/CLAUDE.md
Verification:
ls -la <project>/CLAUDE.md
# Should show: CLAUDE.md -> AGENTS.md
After sync completes, run a quick re-audit and display:
## Sync Complete
Skills synced: +N Cursor, +N Codex
MCP synced: +N Cursor, +N Codex
Skipped: N (HTTP in Codex), N (native skills)
Remaining gaps: N (if any, explain why)
If the user says "dry run", "preview", "--dry-run", or "what would change":
[DRY RUN]broken-symlink, suggest re-running syncchmod 644