A shell script that keeps your AI coding assistant configs and skills in sync across Claude Code, Codex CLI, and Gemini CLI — automatically, every time you open a Claude session.
macOS only. Uses
stat -f(BSD stat). Linux support contributions are welcome.
The obvious alternative is symlinking the files. I tried that first and ran into two real problems:
- Claude deleted my
CLAUDE.md— and since it was symlinked toAGENTS.md, that file disappeared too. One delete, two casualties. - Cursor couldn't read symlinked skill files — it simply ignored them. I had to manually copy the files to get skills working again.
Physical copies with timestamps are less elegant but significantly more reliable.
If you use more than one AI coding assistant, you know the pain: you spend time building a great setup in one tool — preferences, conventions, custom skills — and the moment you switch to another, you're starting from scratch. Or worse, you end up with diverging configs that silently go out of sync.
This script solves that by treating the most recently modified file as the source of truth and propagating it to all other tools automatically.
| Scope | Files |
|---|---|
| Global config | ~/.claude/CLAUDE.md ↔ ~/.gemini/GEMINI.md ↔ ~/.codex/AGENTS.md |
| Local config | $CWD/CLAUDE.md ↔ $CWD/GEMINI.md ↔ $CWD/AGENTS.md |
| Global skills | ~/.claude/skills/ ↔ ~/.codex/skills/ ↔ ~/.gemini/skills/ ↔ ~/.agents/skills/ |
| Local skills | $CWD/.claude/skills/ ↔ $CWD/.codex/skills/ ↔ $CWD/.gemini/skills/ |
Local sync only runs if at least one of the files/directories already exists in the project. It won't create files in projects that don't have any AI config yet.
The script uses file timestamps (mtime) to determine which file is most recent:
- On first sync, the newest file wins and is copied to all others using
cp -p(preserving its timestamp) - After sync, all files share the same timestamp → next run does nothing
- If you edit a file in Codex or Gemini, that file gets a newer timestamp → it becomes the source on the next Claude session start
No state files, no hashes — just timestamps.
cp sync-skills.sh ~/.claude/sync-skills.sh
chmod +x ~/.claude/sync-skills.shEdit (or create) ~/.claude/settings.json and add the hooks block:
{
"hooks": {
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "bash /Users/YOUR_USERNAME/.claude/sync-skills.sh"
}
]
}
]
}
}Replace
/Users/YOUR_USERNAMEwith your actual home directory path (e.g./Users/john). You can find it by runningecho $HOMEin your terminal.
The hook fires on every session start and resume — no manual intervention needed.
# Dry run (simulate without making changes)
bash ~/.claude/sync-skills.sh --dry-run
# Run for real
bash ~/.claude/sync-skills.sh- macOS (uses BSD
stat -f) python3(for parsing the SessionStart JSON payload — pre-installed on macOS)- Claude Code, Codex CLI, and/or Gemini CLI installed
Contributions are welcome! Some ideas:
- Linux support (
stat -c "%Y"instead ofstat -f "%m") - Support for additional tools (Cursor, Copilot CLI, etc.)
- Conflict detection when two files were edited between syncs
Open an issue or submit a PR.
MIT