sync
Push skills from source to all targets.
Use skillshare sync hooks for native hooks (see hooks).
Use skillshare sync mcp for MCP connection settings, or skillshare sync --all
to include skills, agents, extras, MCP and hooks. MCP synchronization uses entry
ownership and conflict checks rather than skill symlinks. See mcp.
Operations like install and uninstall only modify source — sync propagates to targets. This lets you batch changes, preview with --dry-run, and control when targets update. See Why Sync is a Separate Step.
When to Use
- After installing, uninstalling, or editing skills — propagate changes to all targets
- After changing a target's sync mode — apply the new mode
- Periodically to ensure all targets are in sync
Command Overview
| Type | Command | Direction |
|---|---|---|
| Local sync | sync / collect | Source ↔ Targets |
| Remote sync | push / pull | Source ↔ Git Remote |
sync= Distribute from Source to Targetscollect= Collect from Targets back to Sourcepush= Push to git remotepull= Pull from git remote and sync
Overview
| Command | Direction | Description |
|---|---|---|
sync | Source → Targets | Push skills to all targets |
collect <target> | Target → Source | Collect skills from target to source |
push | Source → Remote | Commit and push to git |
pull | Remote → Source → Targets | Pull from git, then sync |
Project Mode
When .skillshare/config.yaml exists in the current directory, sync auto-detects project mode:
cd my-project/
skillshare sync # Auto-detected project mode
skillshare sync -p # Explicit project mode
Project sync defaults to merge mode (per-skill symlinks), but each target can be set to copy or symlink mode via skillshare target <name> --mode copy -p. Backup is not created (project targets are reproducible from source).
.skillshare/skills/ .claude/skills/
├── my-skill/ ────────► ├── my-skill/ → (symlink)
├── pdf/ ────────► ├── pdf/ → (symlink)
└── ... └── local/ (preserved)
Cleanup after a default path moves
A project config stores target names, not paths, so a target follows its built-in
default. When a tool changes that default — as goose and openhands did when they
adopted .agents/skills — the skills skillshare wrote to the old directory stay
behind, and the tool reads both locations and lists every skill twice.
Project sync removes them. For each target without an explicit path:, it looks
at the directories that target's runtime also scans, and in any of them that no
configured target writes to, it removes the entries skillshare created. Folders
you made yourself and symlinks pointing outside the project are never touched.
Cleaned 1 leftover skill from .goose/skills: the default path for 'goose' moved to .agents/skills
Setting an explicit path: for a target opts it out of the cleanup, and
--dry-run previews what would be removed without changing anything.
Sync
Push skills from source to all targets.
skillshare sync # Sync skills to all targets
skillshare sync agents # Sync agents only
skillshare sync --all # Sync skills + agents + extras + MCP + hooks
skillshare sync --dry-run # Preview changes
skillshare sync -n # Short form
skillshare sync --force # Overwrite all managed skills
skillshare sync -f # Short form
| Flag | Short | Description |
|---|---|---|
--all | Also sync agents, extras, MCP and hooks after skills (excludes plugins) | |
--dry-run | -n | Preview changes without writing |
--force | -f | Overwrite all managed entries regardless of checksum (copy mode) or replace existing directories with symlinks (merge mode) |
--json | Output as JSON | |
--quiet | -q | Suppress token summary and budget warnings |
JSON Output
skillshare sync --json
{
"targets": 3,
"linked": 12,
"local": 2,
"updated": 0,
"pruned": 1,
"ignored_count": 2,
"ignored_skills": ["_team/vendor/lib", "test-draft"],
"dry_run": false,
"duration": "0.234s",
"warnings": ["source link _dev-skills not followed: target is missing; kept existing target entries, nothing pruned this run"],
"details": [
{
"name": "claude",
"mode": "merge",
"linked": 8,
"local": 2,
"updated": 0,
"pruned": 1
},
{
"name": "cursor",
"mode": "merge",
"linked": 4,
"local": 0,
"updated": 0,
"pruned": 0
}
],
"context_cost": {
"groups": [
{
"targets": ["claude", "cursor"],
"always_loaded_tokens": 12400,
"on_demand_tokens": 58200
}
]
}
}
The ignored_count and ignored_skills fields show skills excluded by .skillignore (and .skillignore.local if present). These are filtered at discovery time and never reach any target. When .skillignore.local is active, the text output includes a .local source hint. See .skillignore for pattern syntax.
warnings appears only when a first-level source link was not followed (see follow_source_links). A run that kept target entries because the link's target was unavailable says so there; pruned is 0 in that case by design.
What Happens
When a target fails
Sync runs every target; one failed target does not stop the others. A target fails when syncing it hits an error, or when its own settings in the config are invalid, for example its skills path is a file instead of a folder or its mode is unknown. A target with invalid settings is skipped for skills and agents in that run. Each failed target is reported (✗ <target> invalid config: … in text output, error in its --json details entry), and the command exits non-zero after the other targets have synced.
Problems with the config as a whole still stop sync before any target runs: a missing or invalid source folder, an invalid global mode or target_naming, an invalid git_root, or invalid extras.
Example Output
$ skillshare sync
✓ Backup claude, claude-work, cursor, gemini, opencode, universal → ~/.local/share/skillshare/backups/2026-09-28_12-52-50
✓ claude 43 linked · 1 pruned
✓ claude-work 43 linked · 1 pruned
✓ cursor 43 linked · 1 local · 1 pruned
✓ gemini 43 linked · 1 pruned
✓ opencode 43 linked · 1 pruned
✓ universal 43 linked · 1 pruned
✓ Synced 43 skills to 6 targets · 0.0s
Context ~1.2K tokens always loaded · ~18.5K on demand
Collect
Collect skills from a target back to source.
skillshare collect claude # Collect from Claude
skillshare collect claude --dry-run # Preview
skillshare collect --all # Collect from all targets
When to use: You created/edited a skill directly in a target (e.g., ~/.claude/skills/) and want to bring it to source.
After collecting:
skillshare collect claude
skillshare sync # ← Distribute to other targets
Pull
Pull from git remote and sync to all targets.
skillshare pull # Pull from git remote
skillshare pull --dry-run # Preview
When to use: You pushed changes from another machine and want to sync them here.
Push
Commit and push source to git remote.
skillshare push # Auto-generated message
skillshare push -m "Add pdf" # Custom message
Conflict handling:
- If remote is ahead,
pushfails → runpullfirst
Dotfiles Manager Compatibility
If you use a dotfiles manager (GNU Stow, chezmoi, yadm, bare-git) that symlinks your source or target directories, skillshare handles it transparently:
# Dotfiles manager creates:
~/.config/skillshare/skills/ → ~/dotfiles/ss-skills/ # symlinked source
~/.claude/skills/ → ~/dotfiles/claude-skills/ # symlinked target
- Symlinked source — all commands (
sync,update,uninstall,list,diff,install) resolve the symlink before walking, so skills are discovered correctly. Chained symlinks (link → link → real dir) also work. - Symlinked target —
syncdetects that the target symlink was not created by skillshare and preserves it. Skills are synced into the resolved directory. - Status/collect —
statusandcollectfollow external target symlinks instead of reporting conflicts.
When a target directory is a symlink, sync checks whether it points to the skillshare source directory. Only symlinks created by skillshare's own symlink mode are removed during mode conversion — external symlinks (from dotfiles managers) are always preserved.
Sync Modes
| Mode | Behavior | Use case |
|---|---|---|
merge | Each skill symlinked individually | Default. Preserves local skills. |
copy | Each skill copied as real files | Compatibility-first setups, vendoring skills into a project repo, or environments where symlink behavior is unreliable. |
symlink | Entire directory is one symlink | Exact copies everywhere. |
Per-target override remains the primary tuning knob:
skillshare target <name> --mode copy
skillshare sync
The compatibility hint is printed by doctor, not by sync. Its example target is chosen in this priority:
cursor → antigravity → copilot → opencode.
If none of these targets exist (or they already run copy), no compatibility hint is shown.
See Sync Modes for a neutral decision matrix.
Per-target include/exclude filters
In merge and copy modes, each target can define include / exclude patterns in config:
targets:
codex:
path: ~/.codex/skills
include: [codex-*]
claude:
path: ~/.claude/skills
exclude: [codex-*]
- Matching is against flat target names (for example
team__frontend__ui) - An
includepattern that matches no skill is reported, because such a target syncs nothing and drops what a previous pattern linked. Filters keep using flat names even whentarget_naming: standardshows the bareSKILL.mdname in the target includeis applied first, thenexcludediff,status,doctor, and UI drift all use the filtered expected set- In symlink mode, filters are ignored
- In copy mode, filters work the same way as merge mode
syncremoves existing source-linked or managed entries that are now excluded- Targets that share one folder need the same filters; otherwise each sync undoes the other and
syncwarns (seesynckeeps showing the same changes)
See Configuration for full details.
These are just one of three filtering layers. See Filtering Skills for a complete guide covering .skillignore, SKILL.md targets, and target filters.
Filter behavior examples
Assume source contains:
core-authcore-docscodex-agentcodex-experimentalteam__frontend__ui
include only
targets:
codex:
path: ~/.codex/skills
include: [codex-*, core-*]
After sync, codex receives:
core-authcore-docscodex-agentcodex-experimental
Use this when a target should receive only a curated subset.
exclude only
targets:
claude:
path: ~/.claude/skills
exclude: [codex-*, *-experimental]
After sync, claude receives:
core-authcore-docsteam__frontend__ui
Use this when a target should get "almost everything" except specific groups.
include + exclude
targets:
cursor:
path: ~/.cursor/skills
include: [core-*, codex-*]
exclude: [*-experimental]
After sync, cursor receives:
core-authcore-docscodex-agent
codex-experimental is first included, then removed by exclude.
What gets removed when filters change
When a filter is updated and sync runs:
- Links skillshare created for source skills that are now filtered out are pruned
- A live symlink/junction into the source that skillshare never tracked is preserved and counted as local
- Local non-symlink folders already in target are preserved
Merge Mode (Default)
Source Target (claude)
─────────────────────────────────────────────────────────────
skills/ ~/.claude/skills/
├── my-skill/ ────────► ├── my-skill/ → (symlink)
├── another/ ────────► ├── another/ → (symlink)
└── ... ├── local-only/ (preserved)
└── .skillshare-manifest.json
Copy Mode
Source Target (cursor)
─────────────────────────────────────────────────────────────
skills/ ~/.cursor/skills/
├── my-skill/ ────copy► ├── my-skill/ (real files)
├── another/ ────copy► ├── another/ (real files)
└── ... ├── local-only/ (preserved)
└── .skillshare-manifest.json
Both merge and copy modes write .skillshare-manifest.json to track managed skills. In copy mode, checksums enable incremental sync (unchanged skills are skipped); --force overwrites all.
Symlink Mode
Source Target (claude)
─────────────────────────────────────────────────────────────
skills/ ────────► ~/.claude/skills → (symlink to source)
├── my-skill/
├── another/
└── ...
Change Mode
skillshare target claude --mode merge
skillshare target claude --mode copy
skillshare target claude --mode symlink
skillshare sync # Apply change
Safety Warning
In symlink mode, deleting through target deletes source!
rm -rf ~/.claude/skills/my-skill # ❌ Deletes from SOURCE
skillshare target remove claude # ✅ Safe way to unlink
Backup
Backups are created automatically before sync and target remove.
Location: ~/.local/share/skillshare/backups/<timestamp>/
A snapshot captures only local target content. Merge-mode symlinks are skipped — they point into your source and sync recreates them — so snapshots stay small no matter how large your skills are. Retention is applied automatically after each sync. See What Gets Backed Up and Backups & Disk Space.
Manual Backup
skillshare backup # Backup all targets
skillshare backup claude # Backup specific target
skillshare backup --list # List all backups
skillshare backup --cleanup # Remove old backups
skillshare backup --dry-run # Preview
Example Output
$ skillshare backup --list
Backups
─────────────────────────────────────────
2026-01-20_15-30-00/
claude/ 5 skills, 2.1 MB
cursor/ 5 skills, 2.1 MB
2026-01-19_10-00-00/
claude/ 4 skills, 1.8 MB
Restore
Restore targets from backup.
skillshare restore claude # Latest backup
skillshare restore claude --from 2026-01-19_10-00-00 # Specific backup
skillshare restore claude --dry-run # Preview
Agent Sync
Agents are synced separately from skills. Use sync agents for agent-only sync, or sync --all to include skills, agents, extras, MCP, and hooks:
skillshare sync # Sync skills only (default)
skillshare sync agents # Sync agents only
skillshare sync --all # Sync skills + agents + extras + MCP + hooks
Agent sync supports all three modes (merge, copy, symlink), matching the target's configured mode. On Windows without Developer Mode, merge mode copies agent files instead of linking them and prints ! <target>: agents file links need Windows Developer Mode; copying instead; see Windows troubleshooting. Only targets with an agents path definition receive agent syncs — currently Claude, Cursor, OpenCode, and Augment. See Agents — Supported Targets for the full list.
Orphan cleanup, .agentignore filtering, and per-target include/exclude filters all work the same way as for skills. In merge mode, orphan cleanup removes only broken links and links that point into the agents source; live links to agent files elsewhere and local files are preserved.
Sync Plugins
sync plugins [name] is an alias for plugin sync. Plugins are
excluded from sync --all and use native installation operations instead of
skill sync modes.
skillshare sync plugins --dry-run --json
skillshare sync plugins demo --target claude --no-tui
plugin enable and plugin disable save target selection only. The next plugin
sync installs selected bindings and uninstalls deselected ones while keeping their
definitions. Unmanaged plugins are unaffected. Plugin sync accepts --target,
--dry-run, --json, --no-tui, --revision, and mode flags; ordinary sync options
such as --force, --quiet, and --all do not apply. See plugin for
native client requirements, project scope, and partial-failure recovery.
Sync Extras
Sync non-skill resources (rules, commands, prompts, etc.) to arbitrary directories. Extras are configured separately from skills and have their own source directories.
skillshare sync extras # Sync all configured extras
skillshare sync extras --dry-run # Preview changes
skillshare sync extras --force # Overwrite conflicting files
skillshare sync --all # Sync skills + agents + extras + MCP + hooks
| Flag | Short | Description |
|---|---|---|
--dry-run | -n | Preview changes without writing |
--force | -f | Overwrite conflicting files at target |
--json returns a non-zero exit status when extras sync has errors. sync --all also exits
non-zero when an extras target fails, with or without --json. An extra whose source
directory does not exist is skipped with a hint, not created. For single-file extras,
--dry-run also reports edits that would be backed up before replacement.
sync extras works in both global and project mode. Use sync --all to sync skills, agents, extras, MCP, and hooks together, or sync extras to sync extras only. In project mode, extras source is .skillshare/extras/<name>/.
Configuration
Add an extras section to your config (~/.config/skillshare/config.yaml for global, .skillshare/config.yaml for project):
extras:
- name: rules
targets:
- path: ~/.claude/rules
- path: ~/.cursor/rules
mode: copy
- name: commands
targets:
- path: ~/.claude/commands
Each extra has:
name— directory name underextras/in your config directorytargets— list of target paths with optionalmode
Source files live under the extras/ subdirectory:
~/.config/skillshare/
├── config.yaml
├── skills/ ← skill source
└── extras/ ← extras source root
├── rules/ ← extras: rules
│ ├── coding.md
│ └── testing.md
└── commands/ ← extras: commands
└── deploy.md
Sync modes
| Mode | Behavior |
|---|---|
merge | Per-file symlink from target to source (default) |
copy | Per-file copy |
symlink | Entire source directory symlinked to target path |
In merge mode, only broken symlinks and symlinks into the extra's source are pruned — user-created local files and live links to other locations are preserved.
On Windows without Developer Mode, merge mode (and a single-file extra in symlink mode) copies files instead, reports the target as (copy), and prints file links need Windows Developer Mode; copying instead under it. These copies are updated and pruned like links, and replaced with links once file links work.
Identical local files are reported as local preserved; sync extras does not suggest --force for them. They remain local files, not managed links.
What happens
- Walks the source directory (
~/.config/skillshare/extras/<name>/) - For each target, creates symlinks or copies per configured mode
- Removes orphan files in the target that no longer exist in source
Example output
$ skillshare sync extras
Extras
✓ rules ~/.claude/rules 2 files linked
✓ rules ~/.cursor/rules 2 files copied
✓ commands ~/.claude/commands 1 files linked
✓ Synced 2 extras to 3 folders · 0.0s
Context Cost
After syncing, skillshare displays a token cost summary:
✓ Synced 47 skills to 4 targets · 0.3s
Context ~12.4K tokens always loaded · ~58.2K on demand
- Always-loaded: frontmatter name + description (loaded every request)
- On-demand: skill body (loaded when triggered)
Targets with identical token counts are grouped on one line.
Budget Warnings
Configure warning thresholds in your config:
context_budget:
warn_always_loaded_tokens: 10000 # default; 0 = disabled
warn_on_demand_tokens: 100000 # default; 0 = disabled
When a threshold is exceeded, a warning appears with the top 3 offenders:
! Always-loaded context is ~50,123 tokens (budget: 10,000)
Top 3:
• my-big-skill ~8,200 tokens
• another-verbose-skill ~6,400 tokens
• chatgpt-system-prompt ~5,100 tokens
Run `skillshare analyze` for details.
Quiet Mode
Use --quiet or -q to suppress token summary and budget warnings:
skillshare sync --quiet
JSON output (--json) always includes context_cost regardless of --quiet.
See Also
- status — Show sync state
- diff — Show differences
- Targets — Manage targets
- Cross-Machine Sync — Sync across computers
- install — Install skills
- Configuration — Extras config reference