Add skills-sync skill
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
---
|
||||
name: skills-sync
|
||||
description: >
|
||||
Manages syncing, updating, and sharing Claude skills via Helloprint's GitLab repositories. Use this
|
||||
skill whenever a user mentions: syncing skills, updating skills, pulling new skills, pushing skill
|
||||
changes, git conflicts in skills, sharing a skill, publishing a skill, "my skills are outdated",
|
||||
"get latest skills", "save my skill changes", "skill sync", "skill update", or any reference to
|
||||
git operations in the context of Claude skills. Also trigger when users mention skill repos, skill
|
||||
repositories, or ask how to get new skills that were shared with them. This skill is designed for
|
||||
non-technical users who should never need to understand git commands directly.
|
||||
---
|
||||
|
||||
# Skills Sync
|
||||
|
||||
A friendly skill that handles all git operations for Claude skills behind the scenes. The user
|
||||
should never need to type a git command — Claude does everything and explains what happened in
|
||||
plain language.
|
||||
|
||||
## Important Principles
|
||||
|
||||
1. **Never show raw git output** to the user unless they ask for it or something goes wrong
|
||||
2. **Use simple language**: "download latest changes" not "git pull", "save your work" not "commit"
|
||||
3. **Always confirm before pushing** — the user should approve before changes go to the team
|
||||
4. **Handle conflicts gracefully** — explain what happened and offer clear choices
|
||||
5. **Protect secrets** — never commit `.env` files or anything matching secret patterns
|
||||
|
||||
## GitLab Configuration
|
||||
|
||||
All skill repositories are hosted on Helloprint's GitLab instance. The URL pattern is:
|
||||
|
||||
```
|
||||
git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-{process}.git
|
||||
```
|
||||
|
||||
### Helloprint Value Chain Repositories
|
||||
|
||||
Repos are organized around Helloprint's core value chain processes, not departments:
|
||||
|
||||
| Process | Lead | Repository |
|
||||
|----------------------------|---------|------------------------|
|
||||
| (Shared — everyone) | — | skills-shared |
|
||||
| Source Products | Rick | skills-source-products |
|
||||
| Add Products | Rick | skills-add-products |
|
||||
| Sell Products & Services | Niels | skills-sell-products |
|
||||
| Deliver Products | Rick | skills-deliver-products|
|
||||
| Get Paid & Be Compliant | Lennart | skills-get-paid |
|
||||
| Serve Customers | Maarten | skills-serve-customers |
|
||||
|
||||
Full SSH URLs:
|
||||
- `git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-shared.git`
|
||||
- `git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-source-products.git`
|
||||
- `git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-add-products.git`
|
||||
- `git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-sell-products.git`
|
||||
- `git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-deliver-products.git`
|
||||
- `git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-get-paid.git`
|
||||
- `git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-serve-customers.git`
|
||||
|
||||
> **Note**: Some people work across multiple processes (e.g., Rick leads Source, Add, and Deliver).
|
||||
> During setup, ask the user which process(es) they work in — they may need access to more than one repo.
|
||||
|
||||
### GitLab web interface
|
||||
|
||||
To browse skills online:
|
||||
```
|
||||
https://gitlab.it.helloprint.com/ai-and-automation/claude-skills/skills-{process}
|
||||
```
|
||||
|
||||
## Expected Directory Layout
|
||||
|
||||
```
|
||||
/mnt/skills/user/
|
||||
├── .skills-sync.json # Config file this skill creates
|
||||
├── shared/ # Cloned from skills-shared
|
||||
│ ├── .git/
|
||||
│ └── (shared skills...)
|
||||
├── source-products/ # Cloned from skills-source-products
|
||||
│ ├── .git/
|
||||
│ └── (process skills...)
|
||||
├── sell-products/ # Cloned from skills-sell-products
|
||||
│ ├── .git/
|
||||
│ └── (process skills...)
|
||||
└── my-custom-skill/ # Local skill, not git-managed
|
||||
```
|
||||
|
||||
### First-time setup
|
||||
|
||||
If `.skills-sync.json` doesn't exist, walk the user through setup:
|
||||
|
||||
1. Ask for their name and email
|
||||
2. Ask which process(es) they work in — show the list of six processes
|
||||
- People may work in more than one process (e.g., Rick works in Source, Add, and Deliver)
|
||||
3. Confirm the repos — everyone gets `skills-shared` plus their process repo(s)
|
||||
4. Check that SSH access works: `ssh -T git@gitlab.it.helloprint.com`
|
||||
- If this fails, tell the user: "It looks like your SSH key isn't set up for GitLab yet. Ask IT to help you set up an SSH key."
|
||||
5. Clone each repo into `/mnt/skills/user/`
|
||||
6. Configure git user name and email
|
||||
7. Create `.skills-sync.json` to remember the setup
|
||||
|
||||
```json
|
||||
{
|
||||
"gitlab_host": "gitlab.it.helloprint.com",
|
||||
"gitlab_group": "ai-and-automation/claude-skills",
|
||||
"repos": [
|
||||
{
|
||||
"name": "Shared Skills",
|
||||
"path": "/mnt/skills/user/shared",
|
||||
"remote_url": "git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-shared.git",
|
||||
"branch": "main",
|
||||
"access": "read-only"
|
||||
},
|
||||
{
|
||||
"name": "Sell Products & Services",
|
||||
"path": "/mnt/skills/user/sell-products",
|
||||
"remote_url": "git@gitlab.it.helloprint.com:ai-and-automation/claude-skills/skills-sell-products.git",
|
||||
"branch": "main",
|
||||
"access": "read-write"
|
||||
}
|
||||
],
|
||||
"user": {
|
||||
"name": "Niels",
|
||||
"email": "niels@helloprint.com"
|
||||
},
|
||||
"secrets_patterns": [".env", "*.key", "*.pem", "*.secret", "*credentials*"],
|
||||
"last_sync": "2026-02-27T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Core Operations
|
||||
|
||||
### 1. Get Latest Skills ("sync" / "update")
|
||||
|
||||
**Trigger phrases**: "update my skills", "get latest", "sync", "are my skills up to date?"
|
||||
|
||||
```bash
|
||||
# For each repo in config:
|
||||
cd <repo_path>
|
||||
|
||||
# Stash any local changes first
|
||||
git stash
|
||||
|
||||
# Pull latest
|
||||
git pull origin <branch>
|
||||
|
||||
# Re-apply local changes if any
|
||||
git stash pop
|
||||
```
|
||||
|
||||
**Tell the user**:
|
||||
- "Your skills are up to date! I pulled the latest changes from [N] skill repos."
|
||||
- If there were updates: "Updated skills: [list skill folder names that changed]"
|
||||
- If there were conflicts: move to conflict resolution (see below)
|
||||
|
||||
### 2. Save & Share Changes ("push" / "share" / "publish")
|
||||
|
||||
**Trigger phrases**: "save my changes", "share this skill", "push my updates", "publish"
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Run `git status` to see what changed
|
||||
2. Summarize changes in plain language: "You've modified the **order-tracking** skill (changed 2 files) and created a new **supplier-outreach** skill."
|
||||
3. **Ask for confirmation**: "Would you like to share these changes with your team?"
|
||||
4. Check for secrets before committing (see Security section)
|
||||
5. If confirmed:
|
||||
|
||||
```bash
|
||||
cd <repo_path>
|
||||
git add -A
|
||||
git commit -m "<auto-generated descriptive message>"
|
||||
git pull origin <branch> --rebase
|
||||
git push origin <branch>
|
||||
```
|
||||
|
||||
6. Tell the user: "Your changes are now shared with the team!"
|
||||
|
||||
**Auto-generate commit messages** that are descriptive:
|
||||
- "Update order-tracking: added carrier integration for DPD"
|
||||
- "Add new skill: supplier-outreach for automated follow-ups"
|
||||
- "Fix invoice-processor: corrected VAT calculation logic"
|
||||
|
||||
### 3. Resolve Conflicts
|
||||
|
||||
**When this happens**: Two people edited the same file. Git can't merge automatically.
|
||||
|
||||
**Approach for non-technical users**:
|
||||
|
||||
1. Detect the conflict after a pull
|
||||
2. Read both versions (theirs and ours)
|
||||
3. Explain in plain language: "It looks like both you and a colleague changed the **order-tracking** skill. Here's what's different: [summary of differences]"
|
||||
4. Offer clear choices:
|
||||
- **"Keep my version"** — uses the user's changes, discards the other
|
||||
- **"Keep the team's version"** — uses what the team pushed, discards local changes
|
||||
- **"Merge both"** — Claude intelligently combines both changes and shows the result for approval
|
||||
5. After the user chooses, resolve the conflict and complete the merge
|
||||
|
||||
```bash
|
||||
# After resolving:
|
||||
git add <resolved_files>
|
||||
git commit -m "Resolve conflict in <skill-name>: kept [user's choice]"
|
||||
git push origin <branch>
|
||||
```
|
||||
|
||||
### 4. Check Status
|
||||
|
||||
**Trigger phrases**: "what's changed", "skill status", "any updates available"
|
||||
|
||||
Run `git status` and `git log --oneline -5` on each repo. Summarize:
|
||||
- Local changes not yet shared
|
||||
- How many updates are available from the team
|
||||
- When the last sync happened
|
||||
|
||||
Present as a simple summary, e.g.:
|
||||
"Here's the status of your skill repos:
|
||||
- **Shared Skills**: Up to date (last synced 2 hours ago)
|
||||
- **Sell Products**: You have 2 unsaved changes. The team pushed 3 updates since your last sync."
|
||||
|
||||
### 5. View History
|
||||
|
||||
**Trigger phrases**: "who changed this skill", "what changed recently", "skill history"
|
||||
|
||||
```bash
|
||||
git log --oneline --since="2 weeks ago" --pretty=format:"%h %an: %s (%ar)"
|
||||
```
|
||||
|
||||
Present as a readable timeline:
|
||||
"Recent changes to **Sell Products** skills:
|
||||
- Niels updated lead-qualifier (2 days ago)
|
||||
- Anna added quote-generator (5 days ago)
|
||||
- Niels fixed email-templates CSV handling (1 week ago)"
|
||||
|
||||
### 6. Create a Merge Request (optional advanced workflow)
|
||||
|
||||
**Trigger phrases**: "create a merge request", "submit for review", "MR"
|
||||
|
||||
If the team uses GitLab merge requests instead of direct pushes:
|
||||
|
||||
1. Create a feature branch: `git checkout -b skill/<skill-name>-update`
|
||||
2. Commit changes to the branch
|
||||
3. Push the branch: `git push origin skill/<skill-name>-update`
|
||||
4. Provide the user with a link to create the MR on GitLab:
|
||||
`https://gitlab.it.helloprint.com/ai-and-automation/claude-skills/skills-<process>/-/merge_requests/new?merge_request[source_branch]=skill/<skill-name>-update`
|
||||
5. Tell the user: "I've prepared your changes for review. Click the link to open the merge request in GitLab, then hit 'Create merge request'."
|
||||
|
||||
## Security: Handling Secrets
|
||||
|
||||
### Pre-commit Secret Check
|
||||
|
||||
**ALWAYS run this before any commit.** Scan staged files for:
|
||||
|
||||
```python
|
||||
import re
|
||||
|
||||
SECRET_PATTERNS = [
|
||||
r'(?i)(api[_-]?key|apikey)\s*[=:]\s*["\']?[\w-]{20,}',
|
||||
r'(?i)(secret|password|passwd|pwd)\s*[=:]\s*["\']?[^\s"\']{8,}',
|
||||
r'(?i)(token)\s*[=:]\s*["\']?[\w-]{20,}',
|
||||
r'sk-[a-zA-Z0-9]{20,}', # OpenAI-style keys
|
||||
r'ghp_[a-zA-Z0-9]{36}', # GitHub PATs
|
||||
r'glpat-[\w-]{20,}', # GitLab personal access tokens
|
||||
r'xox[bpras]-[\w-]+', # Slack tokens
|
||||
r'-----BEGIN [\w ]+ KEY-----', # Private keys
|
||||
r'(?i)bearer\s+[\w-]{20,}', # Bearer tokens
|
||||
]
|
||||
```
|
||||
|
||||
**If secrets are found**:
|
||||
1. **STOP** — do not commit
|
||||
2. Tell the user: "I found what looks like a secret key in [filename]. I won't share this to protect your security."
|
||||
3. Suggest: "You should move secrets to a `.env` file (which is git-ignored) or use the company's secret manager."
|
||||
|
||||
### .gitignore
|
||||
|
||||
Ensure every skills repo has a `.gitignore` with:
|
||||
|
||||
```
|
||||
.env
|
||||
.env.*
|
||||
*.key
|
||||
*.pem
|
||||
*.secret
|
||||
*credentials*
|
||||
.skills-sync.json
|
||||
__pycache__/
|
||||
.DS_Store
|
||||
```
|
||||
|
||||
### Recommended Secrets Approach
|
||||
|
||||
**For API keys and tokens used inside skills**, use this pattern:
|
||||
|
||||
1. Skills reference environment variables: `os.environ.get("API_KEY")`
|
||||
2. Each user has a local `.env` file (git-ignored) with their keys
|
||||
3. A `.env.example` file IS committed, showing required variables without values:
|
||||
```
|
||||
# Required API keys for this skill
|
||||
OPENAI_API_KEY=your-key-here
|
||||
SLACK_WEBHOOK_URL=your-url-here
|
||||
```
|
||||
4. When a user clones a skill repo, Claude helps them create their `.env` from the example
|
||||
5. Actual key values are distributed through a secure channel (password manager, not Slack/email)
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | User-friendly message |
|
||||
|-------|----------------------|
|
||||
| SSH auth failed | "I can't connect to GitLab. Your SSH key may not be set up yet — ask IT for help." |
|
||||
| Repo not found | "The skills repo doesn't seem to exist at that address. Can you double-check with your process lead?" |
|
||||
| Permission denied (push) | "You don't have permission to share changes to this repo. It might be read-only for your role, or you may need to create a merge request instead." |
|
||||
| Network error | "I can't reach GitLab right now. Check your internet/VPN connection and try again." |
|
||||
| Merge conflict | Move to conflict resolution flow (Section 3 above) |
|
||||
| Detached HEAD | Silently fix with `git checkout main` before proceeding |
|
||||
|
||||
## Tone Guide
|
||||
|
||||
- "I'll download the latest skills from your team" (not "git pull from origin")
|
||||
- "Save and share your changes" (not "commit and push")
|
||||
- "Someone else also edited this file" (not "merge conflict detected")
|
||||
- "Your skills are up to date!" (not "Already up to date. On branch main.")
|
||||
- "I'll prepare this for review on GitLab" (not "push to remote branch and open MR")
|
||||
Reference in New Issue
Block a user