2026-11-02 09:14:11 -05:00
|
|
|
#!/bin/sh
|
|
|
|
|
# Sync agent skills with .chezmoidata/skills.yaml through the Skills CLI:
|
2026-11-06 15:24:01 -05:00
|
|
|
# install every skill in the one declared source, then remove every
|
|
|
|
|
# CLI-installed skill that came from anywhere else.
|
2026-11-02 09:14:11 -05:00
|
|
|
# skills hash: {{ .skills | toJson | sha256sum }}
|
|
|
|
|
set -u
|
|
|
|
|
|
|
|
|
|
command -v npx >/dev/null 2>&1 || { echo "warning: npx not found — skipping skills sync" >&2; exit 0; }
|
2026-11-06 15:24:01 -05:00
|
|
|
command -v jq >/dev/null 2>&1 || { echo "warning: jq not found — skipping skills sync" >&2; exit 0; }
|
2026-11-02 09:14:11 -05:00
|
|
|
|
|
|
|
|
src={{ .chezmoi.sourceDir | quote }}
|
2026-11-06 15:24:01 -05:00
|
|
|
source={{ .skills.source | quote }}
|
|
|
|
|
agents={{ .skills.agents | join " " | quote }}
|
|
|
|
|
lock=${XDG_STATE_HOME:-$HOME/.local/state}/skills/.skill-lock.json
|
2026-11-02 09:14:11 -05:00
|
|
|
|
|
|
|
|
skills() { npx -y {{ .skills.cli | quote }} "$@" </dev/null; }
|
|
|
|
|
|
|
|
|
|
# Leftovers from when skills were vendored in this repo (chezmoi symlink mode):
|
|
|
|
|
# skill dirs whose files are symlinks into the source tree, and the old lock
|
|
|
|
|
# symlink. Drop them so the CLI writes real copies instead of writing through
|
|
|
|
|
# the links into the repo.
|
|
|
|
|
for dir in "$HOME/.agents/skills"/* "$HOME/.claude/skills"/*; do
|
|
|
|
|
[ -d "$dir" ] && [ ! -L "$dir" ] || continue
|
|
|
|
|
if [ -n "$(find "$dir" -type l -lname "$src/*" -print -quit)" ]; then
|
|
|
|
|
rm -rf "$dir"
|
|
|
|
|
fi
|
|
|
|
|
done
|
2026-11-06 15:24:01 -05:00
|
|
|
old_lock=$HOME/.agents/.skill-lock.json
|
|
|
|
|
if [ -L "$old_lock" ]; then
|
|
|
|
|
case $(readlink "$old_lock") in "$src"/*) rm -f "$old_lock" ;; esac
|
2026-11-02 09:14:11 -05:00
|
|
|
fi
|
2026-11-06 15:24:01 -05:00
|
|
|
# State file of the old per-skill sync; the CLI's lock file replaces it.
|
|
|
|
|
rm -f "${XDG_STATE_HOME:-$HOME/.local/state}/chezmoi/skills.txt"
|
2026-11-02 09:14:11 -05:00
|
|
|
|
2026-11-06 15:24:01 -05:00
|
|
|
echo "skills: $source → all skills"
|
|
|
|
|
# shellcheck disable=SC2086 # agents is a space-separated list
|
|
|
|
|
if ! skills add "$source" -g -y -a $agents --skill '*'; then
|
|
|
|
|
# Non-zero keeps the old hash, so the next `chezmoi apply` retries. Nothing
|
|
|
|
|
# is removed while the install is broken.
|
|
|
|
|
echo "error: skills add failed for $source" >&2
|
2026-11-02 09:14:11 -05:00
|
|
|
exit 1
|
|
|
|
|
fi
|
2026-11-06 15:24:01 -05:00
|
|
|
|
|
|
|
|
# The lock records each skill's source as owner/repo, also for tree URLs.
|
|
|
|
|
repo=$(printf '%s\n' "$source" | sed -E 's#^https://github\.com/##; s#(\.git)?(/tree/.*)?/?$##')
|
|
|
|
|
stale=$(jq -r --arg repo "$repo" \
|
|
|
|
|
'.skills // {} | to_entries[] | select(.value.source != $repo) | .key' "$lock" 2>/dev/null)
|
|
|
|
|
if [ -n "$stale" ]; then
|
|
|
|
|
echo "skills: removing" $stale
|
|
|
|
|
# shellcheck disable=SC2086 # one word per skill name
|
|
|
|
|
skills remove -g -y $stale || { echo "error: skills remove failed" >&2; exit 1; }
|
|
|
|
|
fi
|