| name | cc:sync-skills |
| description | Push local skills to https://github.com/{{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}} for reuse across projects. Discovers skills, syncs to remote repository, generates index, and reports results. Use when you want to share skills across projects or when user says "sync skills", "push skills to GitHub", or "share skills". |
Skill Sync Tool
Overview
This skill syncs local skills from .claude/skills/ to a central GitHub repository for reuse across projects. It:
- Discovers local skills - Scans .claude/skills/ directory
- Selects skills to sync - Interactive selection with filtering
- Syncs to GitHub - Clones/pulls {{SKILLS_REPO_NAME}} repo, copies skills
- Generates index - Creates README.md with skill catalog
- Commits and pushes - Atomic commit with descriptive message
- Reports results - Shows sync status and GitHub URLs
When to use:
- Share skills across multiple projects
- Backup skills to version control
- Collaborate on skill development
- Distribute skills to team members
Prerequisites
Workflow
Step 1: Verify Prerequisites
Check GitHub CLI authentication:
gh auth status
Expected output:
✓ Logged in to github.com as {{SKILLS_REPO_OWNER}} (keyring)
✓ Git operations for github.com configured to use https protocol.
✓ Token: *******************
If not authenticated:
gh auth login
Check git configuration:
git config user.name
git config user.email
If not configured:
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
Step 2: Discover Local Skills
Scan for skills:
find .claude/skills -mindepth 1 -maxdepth 1 -type d | sort
Example output:
.claude/skills/add-content-image
.claude/skills/cdk-scripting
.claude/skills/commit
.claude/skills/arch:create-adr
.claude/skills/editor-in-chief
.claude/skills/fetch-story
.claude/skills/gather-context
.claude/skills/gather-nfr
.claude/skills/lsp-diagnostics
.claude/skills/lsp-find-references
.claude/skills/lsp-goto-definition
.claude/skills/lsp-hover
.claude/skills/mermaid-diagram
.claude/skills/mr
.claude/skills/overall-review
.claude/skills/performance-review
.claude/skills/refactor-skill
.claude/skills/regenerate-course-content
.claude/skills/security-review
.claude/skills/play-story
.claude/skills/sync-skills
.claude/skills/ux-professional
.claude/skills/write-cdk
.claude/skills/write-typescript
Analyze each skill:
For each skill directory:
SKILL_NAME=$(basename $SKILL_DIR)
if [ -f "$SKILL_DIR/SKILL.md" ]; then
DESCRIPTION=$(sed -n '/^---$/,/^---$/p' "$SKILL_DIR/SKILL.md" | grep "^description:" | sed 's/description: *//')
SCOPE=$(sed -n '/^---$/,/^---$/p' "$SKILL_DIR/SKILL.md" | grep "^scope:" | sed 's/scope: *//' | tr -d '"')
SCOPE=${SCOPE:-global}
HAS_CONFIG=$([ -f "$SKILL_DIR/config.yaml" ] && echo "✓" || echo "")
HAS_REFS=$([ -d "$SKILL_DIR/references" ] && echo "✓" || echo "")
FILE_COUNT=$(find "$SKILL_DIR" -type f | wc -l | tr -d ' ')
echo "$SKILL_NAME|$DESCRIPTION|$HAS_CONFIG|$HAS_REFS|$FILE_COUNT|$SCOPE"
fi
Scope column in the presented table:
Include a Scope column. Skills with scope: project are marked ⚠ project-only.
Present skills to user:
Found 24 skills in .claude/skills/:
Skill Name | Params | Modular | Files | Description
--------------------------- | ------ | ------- | ----- | -----------
add-content-image | | | 1 | Add screenshots to course materials
cdk-scripting | | | 1 | AWS CDK best practices guide
commit | | | 1 | Create AIGCODE-numbered commits
create-adr | | | 1 | Generate Architecture Decision Records
fetch-story | | | 1 | Fetch next Ready story from GitHub
mr | ✓ | ✓ | 8 | Create theme-based pull requests
refactor-skill | | ✓ | 3 | Convert monolithic skills to modular structure
sync-skills | | | 1 | Push skills to {{SKILLS_REPO_NAME}} repo
...
Step 3: Select Skills to Sync
Prompt user with options:
Use AskUserQuestion for interactive selection:
Which skills should I sync to {{SKILLS_REPO_NAME}} repo?
Options:
[A] All skills (24 total)
[M] Modular skills only (skills with references/ directory) - 5 skills
[P] Parametrized skills only (skills with config.yaml) - 3 skills
[C] Custom selection (choose specific skills)
[N] None (cancel sync)
If Custom selection:
Present multi-select for specific skills:
Select skills to sync (multiple selection):
[ ] add-content-image
[ ] cdk-scripting
[x] commit (selected)
[ ] create-adr
[ ] fetch-story
[x] mr (selected)
[x] refactor-skill (selected)
[x] sync-skills (selected)
...
Selected: 4 skills
Store selection:
SELECTED_SKILLS=(
"commit"
"mr"
"refactor-skill"
"sync-skills"
)
Step 3b: Scope check — detect misplaced project-only skills
After the user confirms their selection, check whether any selected skills have scope: project
and are currently installed at global level (~/.claude/skills/):
GLOBAL_SKILLS_DIR="$HOME/.claude/skills"
MISPLACED=()
for SKILL_NAME in "${SELECTED_SKILLS[@]}"; do
SCOPE=$(sed -n '/^---$/,/^---$/p' ".claude/skills/$SKILL_NAME/SKILL.md" \
| grep "^scope:" | sed 's/scope: *//' | tr -d '"')
if [ "$SCOPE" = "project" ] && [ -d "$GLOBAL_SKILLS_DIR/$SKILL_NAME" ]; then
MISPLACED+=("$SKILL_NAME")
fi
done
If $MISPLACED is non-empty, print a warning and offer to fix:
⚠️ The following skills are marked scope: project but are installed globally:
- git:commit (~/.claude/skills/git:commit)
These skills rely on project-level config and may behave incorrectly when run globally.
Options:
[1] Remove from global, install locally in this project (recommended)
[2] Leave as-is and continue
[3] Abort
If option [1] chosen — for each misplaced skill:
rm -rf "$HOME/.claude/skills/$SKILL_NAME"
if [ ! -d ".claude/skills/$SKILL_NAME" ]; then
mkdir -p ".claude/skills/$SKILL_NAME"
cp -r "$HOME/.claude/skills/$SKILL_NAME/." ".claude/skills/$SKILL_NAME/"
fi
echo "✓ $SKILL_NAME moved from ~/.claude/skills/ → .claude/skills/"
If option [2] chosen — continue without changes.
If option [3] chosen — exit 0.
Step 4: Prepare Sync Directory
Create temporary working directory:
SYNC_DIR=$(mktemp -d -t skill-sync-XXXXXX)
echo "Working directory: $SYNC_DIR"
cd "$SYNC_DIR"
Clone {{SKILLS_REPO_NAME}} repository:
gh repo clone {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
cd {{SKILLS_REPO_NAME}}
If repository doesn't exist:
gh repo create {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}} --public --description "Shared Claude Code skills for cross-project reuse"
cat > README.md <<'EOF'
Shared Claude Code skills for reuse across projects.
See individual skill directories for documentation.
EOF
git add README.md
git commit -m "Initial commit"
git push origin main
Pull latest changes:
git pull origin main --rebase
Step 5: Copy Selected Skills
For each selected skill:
for SKILL_NAME in "${SELECTED_SKILLS[@]}"; do
echo "Copying $SKILL_NAME..."
mkdir -p "$SYNC_DIR/{{SKILLS_REPO_NAME}}/$SKILL_NAME"
rsync -av --exclude='*.tmp' --exclude='.DS_Store' \
"$PROJECT_ROOT/.claude/skills/$SKILL_NAME/" \
"$SYNC_DIR/{{SKILLS_REPO_NAME}}/$SKILL_NAME/"
if [ -f "$SYNC_DIR/{{SKILLS_REPO_NAME}}/$SKILL_NAME/SKILL.md" ]; then
echo "✓ $SKILL_NAME copied successfully"
else
echo "✗ $SKILL_NAME copy failed - SKILL.md missing"
fi
done
Handle project-specific paths:
Some skills may reference project-specific paths. Warn user:
grep -r "vibe-coding-course\|aigensa\|\.claude\|_bmad" \
"$SYNC_DIR/{{SKILLS_REPO_NAME}}/" | \
grep -v "config.yaml" | \
grep -v ".git/"
if [ $? -eq 0 ]; then
echo "⚠️ Warning: Found project-specific references in synced skills."
echo " These may need adjustment for cross-project use."
echo " Consider using config.yaml for project-specific values."
fi
Step 6: Generate README Index
Create comprehensive index:
cd "$SYNC_DIR/{{SKILLS_REPO_NAME}}"
cat > README.md <<'EOF'
Shared Claude Code skills for reuse across projects.
This repository contains reusable skills for Claude Code. Each skill is a self-contained package with:
- `SKILL.md` - Main skill documentation and instructions
- `config.yaml` (optional) - Parametrized project-specific settings
- `hooks.json` (optional) - Success criteria and validation hooks
- `references/` (optional) - Detailed documentation loaded as needed
- `scripts/` (optional) - Executable helper scripts
- `assets/` (optional) - Static files used by the skill
EOF
echo "| Skill | Description | Params | Modular | Last Updated |" >> README.md
echo "|-------|-------------|--------|---------|--------------|" >> README.md
for SKILL_DIR in */; do
SKILL_NAME=$(basename "$SKILL_DIR")
[ "$SKILL_NAME" = ".git" ] && continue
if [ -f "$SKILL_DIR/SKILL.md" ]; then
DESCRIPTION=$(sed -n '/^---$/,/^---$/p' "$SKILL_DIR/SKILL.md" | \
grep "^description:" | \
sed 's/description: *//' | \
sed 's/"//g' | \
cut -c1-80)
HAS_CONFIG=$([ -f "$SKILL_DIR/config.yaml" ] && echo "✓" || echo "")
HAS_REFS=$([ -d "$SKILL_DIR/references" ] && echo "✓" || echo "")
LAST_UPDATE=$(git log -1 --format="%cd" --date=short -- "$SKILL_DIR" 2>/dev/null || date +%Y-%m-%d)
echo "| [$SKILL_NAME]($SKILL_NAME/) | $DESCRIPTION | $HAS_CONFIG | $HAS_REFS | $LAST_UPDATE |" >> README.md
fi
done
cat >> README.md <<'EOF'
```bash
cp -r <skill-name> /path/to/your/project/.claude/skills/
Option 2: Clone Entire Repository
git submodule add https://github.com/{{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}.git .claude/{{SKILLS_REPO_NAME}}
ln -s .claude/{{SKILLS_REPO_NAME}}/commit .claude/skills/commit
ln -s .claude/{{SKILLS_REPO_NAME}}/mr .claude/skills/mr
Option 3: Use sync-skills Skill
/sync-skills --pull <skill-name>
Configuration
Many skills support parametrization via config.yaml. After copying a skill:
- Check if
config.yaml exists in the skill directory
- Customize values for your project (repository names, branch conventions, etc.)
- The skill will automatically load settings from config.yaml
Contributing
To add or update skills:
- Fork this repository
- Add/modify skills in their respective directories
- Ensure each skill has a valid
SKILL.md with frontmatter
- Run validation:
npm run validate-skills (if available)
- Submit a pull request
Or use the /sync-skills skill from your project to push changes directly.
Skill Structure Guidelines
Minimal Skill
skill-name/
└── SKILL.md (required: frontmatter + instructions)
Modular Skill
skill-name/
├── SKILL.md (main documentation, <500 lines)
├── config.yaml (optional: project-specific parameters)
├── hooks.json (optional: success criteria validation)
└── references/ (optional: detailed docs loaded as needed)
├── algorithm.md
├── examples.md
└── error-handling.md
Complete Skill
skill-name/
├── SKILL.md
├── config.yaml
├── hooks.json
├── references/
│ └── *.md
├── scripts/
│ └── *.py
└── assets/
└── *.*
License
Skills in this repository are provided as-is for use with Claude Code.
Check individual skill directories for specific licenses.
Maintenance
This repository is maintained by the aigensa development team.
Last sync: $(date +"%Y-%m-%d %H:%M:%S")
Skills count: $(find . -mindepth 1 -maxdepth 1 -type d ! -name ".git" | wc -l | tr -d ' ')
EOF
### Step 7: Commit and Push
**Check for changes:**
```bash
cd "$SYNC_DIR/{{SKILLS_REPO_NAME}}"
git add .
git status --short
If no changes:
No changes detected. All skills are already up-to-date in {{SKILLS_REPO_NAME}} repo.
If changes exist:
Show diff summary:
git diff --cached --stat
git status --short | grep "^A.*SKILL.md$"
git status --short | grep "^M.*SKILL.md$"
Create descriptive commit message:
COMMIT_MSG="Sync skills: $(echo ${SELECTED_SKILLS[@]} | tr ' ' ', ')
Updated: $(date +"%Y-%m-%d")
Source: $(basename $PROJECT_ROOT)
Changes:
$(git status --short | head -10)
"
git commit -m "$COMMIT_MSG"
Push to remote:
git push origin main
If push fails (authentication or permissions):
Error: Push failed. Possible causes:
1. Not authenticated with gh CLI
2. No write access to {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
3. Branch protection rules require PR
Solutions:
- Run: gh auth refresh
- Check: gh repo view {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
- Create PR instead: gh pr create
Step 8: Report Results
Success report:
✓ Skill sync completed successfully!
Synced Skills:
✓ commit → https://github.com/{{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}/tree/main/commit
✓ mr → https://github.com/{{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}/tree/main/mr
✓ refactor-skill → https://github.com/{{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}/tree/main/refactor-skill
✓ sync-skills → https://github.com/{{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}/tree/main/sync-skills
Repository: https://github.com/{{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
Commit: abc1234
README updated with 24 skills
To use these skills in another project:
1. Clone: gh repo clone {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
2. Copy: cp -r {{SKILLS_REPO_NAME}}/<skill-name> .claude/skills/
3. Configure: Edit config.yaml if present
Temp directory retained at: $SYNC_DIR
(Will be cleaned up on next sync or manually: rm -rf $SYNC_DIR)
Failure report:
✗ Skill sync failed
Error: [specific error message]
Attempted to sync:
- commit
- mr
- refactor-skill
- sync-skills
Troubleshooting:
1. Verify GitHub CLI auth: gh auth status
2. Check repository access: gh repo view {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
3. Review git config: git config --list
4. Check network connection
Temp directory retained for debugging: $SYNC_DIR
Review logs: cat $SYNC_DIR/sync.log
Step 9: Cleanup (Optional)
Ask user:
Sync complete. Clean up temporary directory?
[Y] Yes, delete $SYNC_DIR
[N] No, keep for review
Keeping the directory allows you to:
- Review exactly what was synced
- Make manual adjustments
- Debug any issues
If yes:
rm -rf "$SYNC_DIR"
echo "✓ Temporary directory cleaned up"
Pull Mode: Sync Skills FROM Repository
Usage:
/sync-skills --pull <skill-name>
Workflow:
- Clone {{SKILLS_REPO_NAME}} repo:
SYNC_DIR=$(mktemp -d)
cd "$SYNC_DIR"
gh repo clone {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
- Check if skill exists:
if [ ! -d "{{SKILLS_REPO_NAME}}/$SKILL_NAME" ]; then
echo "✗ Skill '$SKILL_NAME' not found in {{SKILLS_REPO_NAME}} repo"
echo "Available skills:"
ls -1 {{SKILLS_REPO_NAME}}/
exit 1
fi
- Copy to local .claude/skills/:
rsync -av "{{SKILLS_REPO_NAME}}/$SKILL_NAME/" ".claude/skills/$SKILL_NAME/"
- Check for config.yaml:
if [ -f ".claude/skills/$SKILL_NAME/config.yaml" ]; then
echo "⚠️ This skill uses config.yaml for project-specific settings."
echo " Please review and customize:"
echo " .claude/skills/$SKILL_NAME/config.yaml"
fi
- Report:
✓ Skill '$SKILL_NAME' installed successfully
Location: .claude/skills/$SKILL_NAME/
Files copied: $(find .claude/skills/$SKILL_NAME -type f | wc -l)
Next steps:
1. Review SKILL.md: cat .claude/skills/$SKILL_NAME/SKILL.md
2. Configure (if needed): vim .claude/skills/$SKILL_NAME/config.yaml
3. Test: /$SKILL_NAME
Configuration
sync-skills Config
Create .claude/skills/sync-skills/config.yaml to customize:
repository:
owner: {{SKILLS_REPO_OWNER}}
name: {{SKILLS_REPO_NAME}}
branch: main
sync:
include_backups: false
include_temp: false
dry_run: false
filters:
exclude_patterns:
- "*.backup.*"
- "*.tmp"
- ".DS_Store"
- "node_modules/"
min_file_size: 0
max_file_size: 10485760
commit:
prefix: "Sync skills:"
include_source: true
include_timestamp: true
Error Handling
Error: "gh: command not found"
Solution: Install GitHub CLI
brew install gh
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install gh
Error: "Authentication required"
Solution: Authenticate with GitHub CLI
gh auth login
Error: "Permission denied (publickey)"
Solution: Check SSH keys or switch to HTTPS
gh config set git_protocol https
ssh-keygen -t ed25519 -C "your@email.com"
gh ssh-key add ~/.ssh/id_ed25519.pub
Error: "Repository not found"
Solution: Verify repository exists and you have access
gh repo view {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}}
gh repo create {{SKILLS_REPO_OWNER}}/{{SKILLS_REPO_NAME}} --public
gh repo list {{SKILLS_REPO_OWNER}}
Error: "Merge conflict"
Solution: Pull latest changes and retry
cd "$SYNC_DIR/{{SKILLS_REPO_NAME}}"
git pull origin main --rebase
git push origin main
Advanced Usage
Sync Specific Files Only
rsync -av --include="*/" --include="SKILL.md" --exclude="*" \
.claude/skills/ {{SKILLS_REPO_NAME}}/
Sync to Different Repository
REPO_OWNER=myorg REPO_NAME=my-skills /sync-skills
Dry Run (Preview Changes)
cd {{SKILLS_REPO_NAME}}
git add .
git diff --cached --stat
git status --short
Batch Sync Multiple Projects
for PROJECT in project1 project2 project3; do
cd "$PROJECT"
/sync-skills --auto --skills=all
done
Best Practices
- Sync regularly - Keep {{SKILLS_REPO_NAME}} repo up-to-date with improvements
- Use config.yaml - Parametrize project-specific values before syncing
- Test before syncing - Ensure skills work in current project
- Review README - Check generated index before pushing
- Clean up temp dirs - Remove temp directories after successful sync
- Version control - Use git tags for skill versions if needed
Security Considerations
- Sensitive data: Never sync skills containing API keys, passwords, or credentials
- Project-specific paths: Use config.yaml to parametrize local paths
- Private repositories: Ensure {{SKILLS_REPO_NAME}} repo is private if syncing proprietary skills
- Access control: Verify who has write access to {{SKILLS_REPO_NAME}} repository
Troubleshooting Checklist