Files
claude-skills/scripts/update.sh
vitya 627a183b3e feat(update-claude-skills): add update skill + scripts [v0.1.0]
New skill and cross-platform scripts that automate the full uplift cycle:
git pull → conditionally rebuild MCP servers → install skills → version
diff → reload hints. Claude-Code-only (Hermes uses hermes-installer-skill).

- scripts/update.sh: bash version (Linux/macOS/git-bash)
- scripts/update.ps1: PowerShell version (Windows)
- skills/update-claude-skills/SKILL.md: thin wrapper, detects platform
- hermes/mapping.yaml: mode: skip (Claude-Code-only)
- dist/update-claude-skills.skill: built archive
- .tasks/STATUS.md: task marked done

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 14:04:27 +03:00

175 lines
6.3 KiB
Bash

#!/usr/bin/env bash
# update.sh — Full uplift cycle for claude-skills on Linux/macOS (and git-bash on Windows)
#
# Steps:
# 1. git pull --ff-only in claude-skills repo
# 2. Conditionally rebuild projects-meta-mcp (if source changed)
# 3. Conditionally rebuild interns-mcp (if source changed)
# 4. Install all skills via install.sh
# 5. Show version diff (before → after)
# 6. Print reload hints
#
# Usage: update.sh [--yes]
# --yes — skip confirmation prompts (assume yes)
set -euo pipefail
YES_MODE=false
[[ "${1:-}" == "--yes" ]] && YES_MODE=true
# ── Paths ──────────────────────────────────────────────────────────────────
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SKILLS_SRC="$ROOT/skills"
TARGET="${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}"
COMMON_ROOT="${COMMON_ROOT:-$HOME/projects/.common}"
META_MCP="$COMMON_ROOT/lib/projects-meta-mcp"
INTERNS_MCP="$COMMON_ROOT/lib/interns-mcp"
# ── Helpers ────────────────────────────────────────────────────────────────
info() { echo -e "\033[1;34m[update]\033[0m $*"; }
ok() { echo -e "\033[1;32m[ok]\033[0m $*"; }
warn() { echo -e "\033[1;33m[warn]\033[0m $*"; }
fail() { echo -e "\033[1;31m[fail]\033[0m $*" >&2; exit 1; }
confirm() {
local msg="$1"
if $YES_MODE; then return 0; fi
read -rp "$msg [y/N] " ans
[[ "$ans" =~ ^[Yy] ]]
}
# ── Collect before-versions ────────────────────────────────────────────────
declare -A BEFORE_VERSIONS=()
if [[ -d "$TARGET" ]]; then
for skill_dir in "$TARGET"/*/; do
name="$(basename "$skill_dir")"
vf="$skill_dir/SKILL.md"
if [[ -f "$vf" ]]; then
ver="$(grep -oP '^version:\s*\K[0-9]+\.[0-9]+\.[0-9]+' "$vf" 2>/dev/null || echo '?')"
BEFORE_VERSIONS["$name"]="$ver"
fi
done
fi
# ── Step 1: git pull ────────────────────────────────────────────────────────
info "Pulling claude-skills repo..."
cd "$ROOT"
if [[ -n "$(git status --porcelain)" ]]; then
warn "Working tree has uncommitted changes. Stashing..."
git stash push -m "update-sh-auto-stash" || fail "Cannot stash changes"
STASHED=true
else
STASHED=false
fi
git pull --ff-only || fail "git pull --ff-only failed (diverged or no upstream)"
ok "Repo updated."
if $STASHED; then
info "Popping stashed changes..."
git stash pop || warn "Could not pop stash — resolve manually"
fi
# ── Step 2: projects-meta-mcp ─────────────────────────────────────────────
if [[ -d "$META_MCP/.git" ]]; then
info "Checking projects-meta-mcp..."
cd "$META_MCP"
PRE_SHA="$(git rev-parse HEAD)"
git pull --ff-only 2>/dev/null || warn "projects-meta-mcp: pull failed or no upstream"
POST_SHA="$(git rev-parse HEAD)"
if [[ "$PRE_SHA" != "$POST_SHA" ]]; then
info "Source changed, rebuilding projects-meta-mcp..."
npm run build 2>/dev/null || npm install && npm run build
ok "projects-meta-mcp rebuilt."
MCP_REBUILT=true
else
ok "projects-meta-mcp: up to date."
MCP_REBUILT=false
fi
else
warn "projects-meta-mcp not found at $META_MCP — skipping."
MCP_REBUILT=false
fi
# ── Step 3: interns-mcp ───────────────────────────────────────────────────
if [[ -d "$INTERNS_MCP/.git" ]]; then
info "Checking interns-mcp..."
cd "$INTERNS_MCP"
PRE_SHA="$(git rev-parse HEAD)"
git pull --ff-only 2>/dev/null || warn "interns-mcp: pull failed or no upstream"
POST_SHA="$(git rev-parse HEAD)"
if [[ "$PRE_SHA" != "$POST_SHA" ]]; then
info "Source changed, reinstalling interns-mcp..."
pip install -e . 2>/dev/null || pip3 install -e .
ok "interns-mcp reinstalled."
MCP_REBUILT=true
else
ok "interns-mcp: up to date."
fi
else
warn "interns-mcp not found at $INTERNS_MCP — skipping."
fi
# ── Step 4: Install skills ─────────────────────────────────────────────────
cd "$ROOT"
info "Installing skills..."
bash "$ROOT/scripts/install.sh"
ok "Skills installed."
# ── Step 5: Version diff ───────────────────────────────────────────────────
info "Version diff:"
CHANGES=false
for skill_dir in "$TARGET"/*/; do
name="$(basename "$skill_dir")"
vf="$skill_dir/SKILL.md"
if [[ -f "$vf" ]]; then
after="$(grep -oP '^version:\s*\K[0-9]+\.[0-9]+\.[0-9]+' "$vf" 2>/dev/null || echo '?')"
before="${BEFORE_VERSIONS[$name]:-new}"
if [[ "$before" != "$after" ]]; then
echo " $before$after ($name)"
CHANGES=true
fi
fi
done
if ! $CHANGES; then
echo " (no version changes)"
fi
# ── Step 6: New setup-skills hint ──────────────────────────────────────────
NEW_SETUP=()
for skill_dir in "$SKILLS_SRC"/*/; do
name="$(basename "$skill_dir")"
if [[ "$name" == setup-* ]] && [[ ! -d "$TARGET/$name" ]]; then
NEW_SETUP+=("$name")
fi
done
if [[ ${#NEW_SETUP[@]} -gt 0 ]]; then
echo ""
info "New setup skills available:"
for s in "${NEW_SETUP[@]}"; do
echo " - $s"
done
echo " Run the setup skill to configure it."
fi
# ── Step 7: Reload hints ──────────────────────────────────────────────────
echo ""
ok "Update complete!"
if $MCP_REBUILT; then
echo " → Run /reload-mcp to reload MCP servers (source changed)"
fi
echo " → Start a new Claude session for skill changes to take full effect"