/update-skills -- Skill Repository Management
Manage skill repo updates, symlink health, and new skill installation across multiple source repositories and remotes.
Parse the user's argument to determine the operation. Default to update if no argument given.
Standalone skill -- no dependency on ops-base or ops-config.
English output only -- this is a technical utility.
Known Sources
This table identifies repos and their remote URLs. Local paths are discovered dynamically at runtime (see Repo Discovery below).
| Repo | origin | local |
|---|---|---|
core-skills | https://github.com/tandregbg/core-claude-skills.git | ssh://gituser@192.168.11.5//volume1/git/core-skills.git |
sonetel-skills | https://github.com/Sonetel/sonetel-claude-skills.git | ssh://gituser@192.168.11.5//volume1/git/sonetel-skills.git |
t1k-skills | https://github.com/t1kab/t1k-skills.git | ssh://gituser@192.168.11.5//volume1/git/t1k-skills.git |
generic-design-system-kit | https://github.com/t1kab/generic-design-system-kit.git | -- |
Repo Discovery
Repo locations are discovered dynamically -- no hardcoded paths. Three mechanisms combined:
- •Self-discovery -- resolve the
update-skillssymlink (~/.claude/skills/update-skills) to find wherecore-skillsis cloned. The parent of that repo's root becomes the base directory for sibling repos (e.g. ifcore-skillslives at/home/ubuntu/src/core-skills, the base directory is/home/ubuntu/src). - •Symlink scanning -- scan all entries in
~/.claude/skills/, resolve each symlink to its real path, walk up to find the git root (git -C <path> rev-parse --show-toplevel), collect unique git roots. Any repo found this way that is NOT in the sources table is included but noted as "discovered" (no known remotes beyond what git reports). - •Sources table -- provides repo names and remote URLs. Matched against discovered repos by directory basename. Used for
install(clone URLs) and remote verification.
Version Safety (Commit Graph Ancestor Check)
Before pulling from any remote, verify it is safe using git merge-base:
git fetch <remote> git merge-base --is-ancestor HEAD <remote>/<branch>
Interpretation:
- •Exit code 0 (HEAD is ancestor of remote): safe -- remote is ahead, fast-forward possible
- •Exit code 1 (HEAD is NOT ancestor of remote): unsafe -- remote is behind local or has diverged
- •Exit code 128 or fetch failure: unreachable -- remote is down or not accessible
Pull logic per repo:
- •Check for dirty working tree (
git status --porcelain). If dirty: skip repo entirely, warn the user. - •
git fetch --all(continue even if some remotes fail -- note which ones are unreachable) - •Determine the current branch (
git symbolic-ref --short HEAD) - •For each remote that has
<remote>/<branch>: a. Run the ancestor check b. If safe: count commits ahead (git rev-list HEAD..<remote>/<branch> --count) c. If unsafe: record as "behind or diverged" d. If unreachable: record as "unreachable" - •Decision:
- •If no remote is ahead: "Already up to date"
- •If exactly one remote is ahead: pull from it (
git pull <remote> <branch>) - •If multiple remotes are ahead and they point to the same commit: pull from any (prefer
origin) - •If multiple remotes are ahead but point to different commits: pull from the one that is furthest ahead (most commits ahead of local HEAD)
- •If remotes have diverged from each other (neither is ancestor of the other): warn the user, do not pull, ask for guidance
- •After pull: report what happened (commits pulled, from which remote)
Operations
1. update (default) -- Fetch and pull all repos
Trigger: /update-skills or /update-skills update
Steps:
- •Discover repos -- self-discovery + symlink scanning + sources table matching
- •For each repo:
a. Verify the local path exists. If not: warn and skip (suggest
install) b. Check for dirty working tree. If dirty: warn and skip c. Fetch all remotes d. Apply version safety logic (see above) e. Pull if safe - •Scan for new skills -- after pulling, compare
skills/*/directories in each repo against existing symlinks in~/.claude/skills/ - •Create symlinks for new skills -- for each skill directory that has no corresponding symlink:
- •Show the user what will be created:
~/.claude/skills/<name> -> <repo-path>/skills/<name> - •Create the symlink:
ln -s <repo-path>/skills/<name> ~/.claude/skills/<name>
- •Show the user what will be created:
- •Report summary:
code
## Update Summary ### core-skills - Pulled 3 commits from origin/main - New skill symlinked: update-skills ### generic-design-system-kit - Already up to date - All symlinks present ### Symlink Health - 10 active, 0 broken, 0 orphaned
2. status -- Show current state
Trigger: /update-skills status
Steps:
- •
Discover repos
- •
For each repo, report:
- •Repo name and local path
- •Current branch and HEAD commit (short hash + message)
- •Version (read from README.md or package.json if available -- look for
**Version:**pattern) - •Remotes (name, URL, reachable/unreachable)
- •Skills provided (list of
skills/*/directories) - •Working tree status (clean/dirty)
- •
Symlink state:
- •List all symlinks in
~/.claude/skills/ - •For each: show target, whether target exists, which repo it belongs to
- •List all symlinks in
- •
Format as a structured report:
code## Skill Repository Status ### core-skills (v1.5.0) Path: <discovered-path>/core-skills Branch: main @ a1b2c3d "v1.5.0: Rename to core-skills" Tree: clean Remotes: origin: https://github.com/tandregbg/core-claude-skills.git local: ssh://gituser@192.168.11.5//volume1/git/core-skills.git Skills: ops-base, ops-config, transcript, management-ops, marketing-ops, project-ops, t1k-ops, cr, update-skills ### generic-design-system-kit Path: <discovered-path>/generic-design-system-kit Branch: main @ d4e5f6g "Latest commit message" Tree: clean Remotes: origin: https://github.com/t1kab/generic-design-system-kit.git Skills: brand-design-system, brand-webapp-structure ### Symlinks (10 active) All symlinks valid. No broken or orphaned links.Replace
<discovered-path>with the actual resolved path at runtime.
3. check -- Verify symlink health
Trigger: /update-skills check
Steps:
- •
Scan
~/.claude/skills/-- list all entries - •
For each entry, check:
- •Is it a symlink? (vs regular directory)
- •Does the symlink target exist?
- •Does the target contain a SKILL.md? (valid skill directory)
- •Which repo does it belong to?
- •
Cross-reference with repos -- for each known repo, check if all
skills/*/directories have symlinks - •
Categorize findings:
Healthy: Symlink exists, target exists, SKILL.md present
Broken: Symlink exists but target does not exist (repo moved/deleted?)
Missing: Skill directory exists in repo but no symlink in
~/.claude/skills/Orphaned: Symlink in
~/.claude/skills/points to a path that is not inside any known repoNot a symlink: Entry in
~/.claude/skills/is a regular directory (not managed by this system) - •
Report (paths shown are the actual resolved paths at runtime):
code## Symlink Health Check Healthy (10): ops-base -> <repo-path>/core-skills/skills/ops-base transcript -> <repo-path>/core-skills/skills/transcript ... Missing (0): (none) Broken (0): (none) Orphaned (0): (none)
- •
Offer fixes -- if any Missing or Broken found:
- •Missing: "Create symlink for <name>?"
- •Broken: "Remove broken symlink <name>?" (ask first -- never auto-remove)
4. install <repo> -- Clone and set up a repo
Trigger: /update-skills install <repo-name-or-url>
Steps:
- •
Determine the base directory:
- •Resolve the
update-skillssymlink to find thecore-skillsrepo root - •The parent of that root is the base directory (e.g. if
core-skillsis at/home/user/src/core-skills, base directory is/home/user/src)
- •Resolve the
- •
Resolve the repo:
- •If argument matches a repo name in the sources table: use the origin URL, clone target is
<base-dir>/<repo-name> - •If argument is a URL: extract repo name from URL, clone target is
<base-dir>/<repo-name> - •If argument matches neither: ask the user for the clone URL
- •If argument matches a repo name in the sources table: use the origin URL, clone target is
- •
Check if already installed:
- •If the clone target exists and is a git repo: report "Already installed" and run
updateon it instead - •If the clone target exists but is not a git repo: warn and abort
- •If the clone target exists and is a git repo: report "Already installed" and run
- •
Clone:
bashgit clone <origin-url> <base-dir>/<repo-name>
- •
Add additional remotes (if known from sources table):
bashgit -C <base-dir>/<repo-name> remote add local <local-url>
- •
Create symlinks for all skill directories found in the cloned repo:
- •Scan
<base-dir>/<repo-name>/skills/*/for directories containing SKILL.md or README.md - •For each, create:
ln -s <base-dir>/<repo-name>/skills/<name> ~/.claude/skills/<name> - •If a symlink already exists with that name: warn (name conflict), do not overwrite
- •Scan
- •
Report:
code## Installed: generic-design-system-kit Cloned to: <base-dir>/generic-design-system-kit Remotes: origin (GitHub) Skills symlinked: brand-design-system -> ~/.claude/skills/brand-design-system brand-webapp-structure -> ~/.claude/skills/brand-webapp-structure
Safety Rules (always enforced)
- •Never auto-remove symlinks. Broken or orphaned symlinks are reported but only removed with explicit user confirmation.
- •Never pull with dirty working tree. If
git status --porcelainreturns output, skip the repo and warn. - •Never push. This skill only fetches and pulls. Pushing is the user's responsibility.
- •Never force-pull. Only fast-forward merges. If fast-forward is not possible, warn and skip.
- •Ask before fixing. When
checkfinds issues, present findings and ask before making changes. - •Skip unreachable remotes gracefully. NAS may be offline -- log it, continue with other remotes.
- •No destructive git operations. No
reset --hard, noclean -f, nocheckout ., nobranch -D. - •Symlink conflicts are never overwritten. If a symlink name already exists, warn and skip.