diff --git a/shared/skills-sync/SKILL.md b/shared/skills-sync/SKILL.md new file mode 100644 index 0000000..a29afa1 --- /dev/null +++ b/shared/skills-sync/SKILL.md @@ -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 + +# Stash any local changes first +git stash + +# Pull latest +git pull origin + +# 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 +git add -A +git commit -m "" +git pull origin --rebase +git push origin +``` + +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 +git commit -m "Resolve conflict in : kept [user's choice]" +git push origin +``` + +### 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/-update` +2. Commit changes to the branch +3. Push the branch: `git push origin skill/-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-/-/merge_requests/new?merge_request[source_branch]=skill/-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") \ No newline at end of file