version: '3' # Skills library Taskfile. # # Primary entry point for project + host installation. Consumer projects # do NOT depend on this file directly — they ship their own # `skills:install` target that delegates here via `install.sh`. This # Taskfile is invoked by maintainers of the skills repo itself, plus by # install.sh during the post-clone wire step. vars: REPO_URL: 'https://gitea.d-ma.be/mathias/skills.git' CHECKOUT_DIR: '{{.HOME}}/.local/share/skills' CLAUDE_GLOBAL_DIR: '{{.HOME}}/.claude/skills' tasks: default: cmds: - task: list list: desc: 'Print every skill in this repo' cmds: - 'ls -1 {{.TASKFILE_DIR}} | grep -Ev "^(Taskfile.yml|install.sh|README.md|SKILLS_INDEX.md|.gitea|.git$)$" || true' silent: true install: desc: 'Wire skills into every harness detected on this host (Claude Code today, more in phase 2).' cmds: - task: install:claude:global - task: install:claude:repo install:claude:global: desc: 'Per-skill symlinks under ~/.claude/skills/ — visible in every Claude Code project on this host.' cmds: - mkdir -p {{.CLAUDE_GLOBAL_DIR}} - | for skill in $(ls -1 "{{.TASKFILE_DIR}}" | grep -Ev "^(Taskfile.yml|install.sh|README.md|SKILLS_INDEX.md|.gitea|.git$)$"); do target="{{.TASKFILE_DIR}}/${skill}" link="{{.CLAUDE_GLOBAL_DIR}}/${skill}" if [ -L "$link" ] || [ -e "$link" ]; then current=$(readlink "$link" 2>/dev/null || true) if [ "$current" = "$target" ]; then continue fi rm -rf "$link" fi ln -s "$target" "$link" echo "linked $link → $target" done install:claude:repo: desc: 'Per-skill symlinks under $(pwd)/.claude/skills/ when invoked inside a git repo.' cmds: - | if ! git rev-parse --show-toplevel >/dev/null 2>&1; then echo "not in a git repo — skipping per-repo wire"; exit 0 fi repo=$(git rev-parse --show-toplevel) if [ "$repo" = "{{.TASKFILE_DIR}}" ]; then echo "running from skills repo itself — skipping per-repo wire"; exit 0 fi target_dir="$repo/.claude/skills" mkdir -p "$target_dir" for skill in $(ls -1 "{{.TASKFILE_DIR}}" | grep -Ev "^(Taskfile.yml|install.sh|README.md|SKILLS_INDEX.md|.gitea|.git$)$"); do target="{{.TASKFILE_DIR}}/${skill}" link="${target_dir}/${skill}" if [ -L "$link" ] || [ -e "$link" ]; then current=$(readlink "$link" 2>/dev/null || true) if [ "$current" = "$target" ]; then continue fi rm -rf "$link" fi ln -s "$target" "$link" echo "linked $link → $target" done update: desc: 'git pull the canonical checkout then re-run install.' cmds: - | if [ ! -d "{{.CHECKOUT_DIR}}/.git" ]; then echo "no canonical checkout at {{.CHECKOUT_DIR}} — run install.sh first"; exit 1 fi git -C "{{.CHECKOUT_DIR}}" pull --ff-only - task: install release: desc: 'Tag HEAD per Bump-Type in the latest commit footer. Normally CI handles this — run locally only when CI is unavailable.' cmds: - | latest=$(git -C "{{.TASKFILE_DIR}}" describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") major=$(echo "$latest" | sed -E 's/^v([0-9]+)\.([0-9]+)\.([0-9]+)$/\1/') minor=$(echo "$latest" | sed -E 's/^v([0-9]+)\.([0-9]+)\.([0-9]+)$/\2/') patch=$(echo "$latest" | sed -E 's/^v([0-9]+)\.([0-9]+)\.([0-9]+)$/\3/') bump=$(git -C "{{.TASKFILE_DIR}}" log -1 --pretty=%B | grep -iE "^Bump-Type:" | head -1 | awk '{print tolower($2)}') case "$bump" in major) major=$((major + 1)); minor=0; patch=0 ;; minor) minor=$((minor + 1)); patch=0 ;; *) patch=$((patch + 1)) ;; esac next="v${major}.${minor}.${patch}" echo "tagging $next (previous $latest, bump=${bump:-patch})" git -C "{{.TASKFILE_DIR}}" tag -a "$next" -m "release $next" echo "now: git push origin $next" check: desc: 'Sanity check — every skill dir has a SKILL.md, no stray files at root.' cmds: - | missing=0 for skill in $(ls -1 "{{.TASKFILE_DIR}}" | grep -Ev "^(Taskfile.yml|install.sh|README.md|SKILLS_INDEX.md|.gitea|.git$)$"); do dir="{{.TASKFILE_DIR}}/${skill}" if [ ! -d "$dir" ]; then echo "ERROR: $skill is not a directory" >&2 missing=$((missing + 1)) continue fi if [ ! -f "$dir/SKILL.md" ]; then echo "ERROR: $dir missing SKILL.md" >&2 missing=$((missing + 1)) fi done if [ $missing -gt 0 ]; then echo "$missing skill(s) failed structure check" >&2 exit 1 fi echo "all skills have SKILL.md"