ai-skills-sync
A CLI that routes AI skills to your coding agents based on project context. One JSON config declares which skills go where, and the tool fetches, caches, and copies them into agent-specific directories (.claude/skills, .cursor/skills, .github/skills, .opencode/skills, .agents/skills).
Overview
- Language: TypeScript
- Repo: peteretelej/ai-skills-sync
- Install:
npm install -g ai-skills-sync - Status: Active (v0.1.3)
Architecture
The CLI is a single-entry-point Commander program (src/cli.ts) with four subcommands: add, remove, list, config, and cache clean. The default action (no subcommand) runs a full sync.
Module breakdown:
types.ts- Core data model. DefinesConfig(the JSON schema),SkillRef(source + optional subpath),SyncState(installed skill tracking), andAgentTypeunion. IncludesparseSource()for theowner/repo@refformat.config.ts- Reads/writes~/.config/ai-skills-sync/config.json. Handles interactive setup via@inquirer/prompts, JSON parse error extraction with line/column reporting, and config mutations (addSkillToConfig,removeSkillFromConfig). Always injects$schemaon save.resolver.ts- Determines which skills apply to the current project. Collects global skills, project-specific skills (matched by normalized path), and conditional skills (viascanner.ts). Deduplicates with priority ordering (project > global > conditional) and resolves install names with dot-prefix collision handling (e.g.obra.tddvsacme.tdd).scanner.ts- Evaluates conditional rules by runningfsp.glob()against the project root, with an exclude list for common artifact directories. Early-exits on first match per rule.fetcher.ts- Git clone + cache management. Usesexecato shallow-clone repos with a 60s timeout andGIT_TERMINAL_PROMPT=0. Caches to~/.cache/ai-skills-sync/github/{owner}/{repo}/{sha}/. IncludescleanCache()to prune entries not referenced by active state.syncer.ts- The main orchestrator. For each resolved skill: fetches it, copies to every detected agent directory, rewrites SKILL.md frontmatter on namespace collisions, detects orphaned skills (auto-removes conditionals, suggests removal for explicit ones), and checks.gitignorecoverage.agents.ts- Detects which agent directories exist in the project (.claude/skills,.cursor/skills,.github/skills,.opencode/skills,.agents/skills). Prompts to create them if none found.state.ts- Reads/writes~/.local/state/ai-skills-sync/state.json. Tracks installed skills per project with commit SHA and sync timestamp. ProvidesisInSync()for early-exit when nothing changed.paths.ts- Platform-aware path resolution usingenv-paths. Locates config, state, and cache directories.
Data flow: Config -> Resolver (collect + deduplicate) -> Fetcher (clone/cache) -> Syncer (copy to agent dirs) -> State (persist).
Key Design Decisions
Single JSON config with $schema: All skill routing is declared in one file at ~/.config/ai-skills-sync/config.json. The $schema field enables autocomplete and validation in editors. This was chosen over per-project config because skills are managed at the user level, not the project level.
Three-tier skill resolution: Global (everywhere), project-specific (by path match), and conditional (by file glob). Conditionals use ephemeral semantics: auto-installed when the pattern matches, auto-removed when it stops matching. Explicit skills (global/project) are only suggested for removal, never auto-removed.
Dot-prefix collision handling: When two repos export a skill with the same directory name, the install directory gets prefixed with the owner (obra.tdd, acme.tdd) and the SKILL.md frontmatter name field is rewritten to match.
Multi-agent support: The tool writes to all detected agent directories simultaneously. A single sync populates Claude Code, Cursor, GitHub Copilot, OpenCode, and .agents at once. Each skill install records which agents received it.
--skill flag for monorepos: When adding from a monorepo like anthropics/skills, the --skill frontend-design flag recursively searches the cloned repo for a directory with that name containing a SKILL.md file, then sets the subpath automatically.
Shallow clone with SHA-keyed cache: Repos are cloned with --depth 1 for speed. The cache is keyed by commit SHA, so updating a skill means fetching a new SHA and the old one gets cleaned up by cache clean.
Development
npm install
npm run build # tsup
npm run dev # tsx watch
npm test # vitest
npm run typecheck # tsc --noEmit