Skip to main content

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.

Why is sync a separate command?

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​

TypeCommandDirection
Local syncsync / collectSource ↔ Targets
Remote syncpush / pullSource ↔ Git Remote
  • sync = Distribute from Source to Targets
  • collect = Collect from Targets back to Source
  • push = Push to git remote
  • pull = Pull from git remote and sync

Overview​

CommandDirectionDescription
syncSource → TargetsPush skills to all targets
collect <target>Target → SourceCollect skills from target to source
pushSource → RemoteCommit and push to git
pullRemote → Source → TargetsPull 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
FlagShortDescription
--allAlso sync agents, extras, MCP and hooks after skills (excludes plugins)
--dry-run-nPreview changes without writing
--force-fOverwrite all managed entries regardless of checksum (copy mode) or replace existing directories with symlinks (merge mode)
--jsonOutput as JSON
--quiet-qSuppress 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, push fails → run pull first

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 — sync detects that the target symlink was not created by skillshare and preserves it. Skills are synced into the resolved directory.
  • Status/collect — status and collect follow external target symlinks instead of reporting conflicts.
How sync decides

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​

ModeBehaviorUse case
mergeEach skill symlinked individuallyDefault. Preserves local skills.
copyEach skill copied as real filesCompatibility-first setups, vendoring skills into a project repo, or environments where symlink behavior is unreliable.
symlinkEntire directory is one symlinkExact 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 include pattern 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 when target_naming: standard shows the bare SKILL.md name in the target
  • include is applied first, then exclude
  • diff, 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
  • sync removes 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 sync warns (see sync keeps showing the same changes)

See Configuration for full details.

tip

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-auth
  • core-docs
  • codex-agent
  • codex-experimental
  • team__frontend__ui

include only​

targets:
codex:
path: ~/.codex/skills
include: [codex-*, core-*]

After sync, codex receives:

  • core-auth
  • core-docs
  • codex-agent
  • codex-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-auth
  • core-docs
  • team__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-auth
  • core-docs
  • codex-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.

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
FlagShortDescription
--dry-run-nPreview changes without writing
--force-fOverwrite 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.

Both modes supported

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 under extras/ in your config directory
  • targets — list of target paths with optional mode

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​

ModeBehavior
mergePer-file symlink from target to source (default)
copyPer-file copy
symlinkEntire 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​

  1. Walks the source directory (~/.config/skillshare/extras/<name>/)
  2. For each target, creates symlinks or copies per configured mode
  3. 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​