Skip to content

Repository files navigation

skillsync

One canonical Agent Skills tree, symlinked into every agent on your machine. Edit a skill once — Claude Code, Codex, and any other Agent Skills–compliant client see the change instantly. No copies, no drift.

Why does this exist?

I use several coding agents side by side — Claude Code, Codex, and Hermes and I wanted the skills I write to work in all of them. My first attempt was the obvious one: copy each skill into every agent's skills directory. It broke down fast. The same skill ended up duplicated across ~/.claude/skills, ~/.agents/skills, and whatever directory each new CLI decided to read; I would fix a skill in one place and, a week later, two agents behaved differently for no visible reason.

skillsync is the setup I landed on: every skill lives exactly once in a canonical repository, and every agent gets a symlink to it. Editing the file updates all agents at the same instant, a new agent is one config line away, and drift is structurally impossible. The tooling here automates the symlinking, keeps the tree honest, and proves the agents actually discover what you shipped.

The model

This repository is a template for your canonical skills tree. Fork or clone it, drop your skills into skills/<name>/, list them in skills-manifest.json, and let the tooling do the rest:

skillsync repo (the single source of truth)
└── skills/
    └── my-skill/SKILL.md ◄─────────┐
                                    │ symlinks, one per skill
~/.agents/skills/my-skill ──────────┤   (Codex + Agent Skills clients)
~/.claude/skills/my-skill ──────────┘   (Claude Code)

Three tools operate on the tree:

Tool What it does
bin/skills-sync Plans and applies the symlink farm. Idempotent. --dry-run, --check (CI drift detection), --adopt (first migration, with backups), automatic rollback on failure.
bin/skills-lint Validates the tree: manifest integrity, frontmatter contract, credential/PII scanning, portability hygiene.
bin/skills-verify Confirms the symlink farm works end to end — static checks plus an optional live discovery probe against real client CLIs.

Requirements

  • Python 3.11+
  • PyYAML 6 (python3 -m pip install -r requirements.txt)
  • Git

Quickstart

git clone https://github.com/VitorLudke/skillsync
cd skillsync
python3 -m pip install -r requirements.txt

bin/skills-lint            # validate the tree (ships with one example skill)
bin/skills-sync --dry-run  # preview the plan
bin/skills-sync            # create the symlinks
bin/skills-verify --static # lint + drift check in one command

Then replace skills/hello-world/ with your own skills, update skills-manifest.json, and rerun bin/skills-sync.

If a target already contains a real directory with the same name as a canonical skill (a pre-existing copy), skills-sync refuses to touch it until you rerun with --adopt, which moves the original to a timestamped backup under ~/.local/share/skillsync/backups/ before linking.

Configuration

Optional skillsync.toml at the repository root. Without it (or with it untouched), the defaults are:

[sync]
# Directories that receive one symlink per canonical skill.
targets = ["~/.agents/skills", "~/.claude/skills"]

# Directories that must NOT contain entries named after canonical skills
# (some clients register duplicates when two discovery roots hold the same
# name). Canonical names found here are removed on sync; real files are
# backed up first when --adopt is passed.
cleanup = []

Add a target for any agent that reads a skills directory:

[sync]
targets = ["~/.agents/skills", "~/.claude/skills", "~/.mycli/skills"]

Agents that discover skills through their own config file instead of a directory can usually just be pointed at this repository's skills/ directory directly — check your client's documentation for an "additional skill directories" setting.

skills-sync also accepts ad-hoc extra targets: bin/skills-sync --target ~/.another/skills.

The frontmatter contract

Canonical skills carry exactly two frontmatter keys:

---
name: my-skill
description: When and how to use this skill.
---

name must match the directory name. Anything else is rejected by the lint — downstream clients rewrite or inject other keys (version, author, tags), so the canonical file stays at the intersection every client accepts.

Linting

bin/skills-lint                    # errors fail; warnings inform
bin/skills-lint --strict-warnings  # for publishing: warnings also fail

Errors: broken manifest/frontmatter, symlinked resources inside the tree, credential material (AWS keys, API tokens, private keys, JWTs, database URLs with literal passwords, and more), client-specific invocations without a capability fallback. Warnings: email addresses, Brazilian document and phone formats (CNPJ, CPF, +55 numbers), oversized SKILL.md files.

A pre-commit hook is included — enable it with:

git config core.hooksPath .githooks

Verifying discovery

bin/skills-verify runs the static checks, then (unless --static) installs a uniquely named temporary probe skill, symlinks it into the configured targets, asks real client CLIs whether they can see it, and removes every path it created:

  • Codex — probed when ~/.agents/skills is a configured target (codex debug prompt-input).
  • Claude Code — probed when ~/.claude/skills is a configured target (headless claude --print with a small spend cap; requires an authenticated claude CLI).

Targets that no built-in client reads are still probed for symlink integrity; if no built-in client applies, the live stage reports itself as skipped.

Safety properties

  • Fail-closed validation: a broken manifest or skill aborts the plan before anything is touched.
  • Every mutation is snapshot-verified against a preflight state and applied through quarantine-and-verify steps; a failure mid-apply rolls back the actions already taken.
  • --adopt never deletes: replaced paths land in ~/.local/share/skillsync/backups/<timestamp>/.
  • All roots must be dedicated directories strictly inside HOME; targets may not overlap each other, the repository, or the backup area.
  • Exit codes are stable for CI: 0 clean, 1 findings/drift, 2 usage or environment error.

Moving the repository

Symlinks store absolute paths. If you move the canonical repository, rerun bin/skills-sync from the new location — stale links pointing at the old path are replaced in place.

Uninstalling

Remove the symlinks by deleting them from your targets (they are plain per-skill symlinks named after each skill), or delete the repo and run your own cleanup; nothing else is installed anywhere. Adoption backups remain under ~/.local/share/skillsync/backups/ until you delete them.

Tests

python3 -m unittest discover -s tests

Everything runs against synthetic fixtures in temp directories; the suite never touches your real agent directories.

License

MIT

About

One canonical Agent Skills tree, symlinked into every agent CLI — edit a skill once, Claude Code, Codex and friends all see it

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages