diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index ebd87fa..27c70aa 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -574,7 +574,7 @@ Pre-commit hooks have `--no-verify`. Per `project-discipline` Rule 4 («never sk --- -## ⚪ [claude-skills-update-skill] — Orchestrator-скил `update-claude-skills` — Claude-Code-сторона аналог `hermes-installer-skill`. Триггеры: «обнови claude-skills», «sync claude-skills», «update claude-skills», «обнови всё». На Windows + Claude Code (а также Linux/Mac) прогоняет в одну команду полный uplift существующей установки: +## 🔴 [claude-skills-update-skill] — Orchestrator-скил `update-claude-skills` — Claude-Code-сторона аналог `hermes-installer-skill`. Триггеры: «обнови claude-skills», «sync claude-skills», «update claude-skills», «обнови всё». На Windows + Claude Code (а также Linux/Mac) прогоняет в одну команду полный uplift существующей установки: 1. `git pull --ff-only` в `~/projects/claude-skills/` (если репа есть; иначе подсказать `git clone`). 2. `git pull` + `npm run build` в `~/projects/.common/lib/projects-meta-mcp/` — только если изменения в source. @@ -590,8 +590,8 @@ Cross-platform: PowerShell-ветка + bash-ветка (как у `install.ps1` Возможное пересечение с `factory-bootstrap` (проект `factory`, промоутнут 2026-05-06): выяснить scope-границу до начала работы. Если factory покрывает «инициализация машины с нуля до рабочего Claude Code» — этот скил фокусируется только на uplift существующей установки, не дублируя greenfield-bootstrap. -**Status:** ready -**Where I stopped:** (not started). Создана 2026-05-07 после incident'а на `pilonuxt`, где обнаружилась общая боль: «как обновить claude-skills на удалённой машине без ручного ритуала». Hermes-сторона закрывается через `[hermes-installer-skill]` (⚪ ready); Claude-Code-сторона до этой таски не имела автоматизации. +**Status:** done +**Where I stopped:** Shipped. `scripts/update.sh` + `scripts/update.ps1` — pull/build/install/version-diff/reload-hint cycle. `skills/update-claude-skills/SKILL.md` v0.1.0 — thin wrapper, detects platform, calls script. `hermes/mapping.yaml` — mode: skip (Claude-Code-only). Build+install verified: `dist/update-claude-skills.skill` (1942 bytes), `~/.claude/skills/update-claude-skills/SKILL.md` v0.1.0, SKIPPED.md lists reason. Hermes rebuild: 24 skills (13 auto, 2 manual, 9 skip, 0 pending). **Next action:** ⚠️ **ARCH-note (2026-05-07, после ревизии `.factory/factory.yaml`):** таска НЕ дубликат factory L1 — она Layer 2 citizen в дизайне factory. `factory.yaml` line 83-91 уже включает `claude-skills` как компонент с `post_install: 'bash {target}/scripts/install.sh'`. **Recommended shape (вариант B с оглядкой на A):** реальная update-логика — в `scripts/update.{ps1,sh}` (рядом с `install.{ps1,sh}`), один источник истины. Скил `update-claude-skills` — короткий wrapper, на триггер вызывает нужный скрипт по `active-platform`. Когда L1 Go-бинарь дойдёт — `factory update` использует те же скрипты без duplication. 1) Скрипты: `scripts/update.ps1` + `scripts/update.sh` в корне репы. Логика: pull/build/install в трёх местах (claude-skills + .common/lib/projects-meta-mcp + .common/lib/interns-mcp), version-diff, reload-hint. **Возможность совмещения с `[install-ps1]`:** добавить `--prune` flag сразу в `update.{ps1,sh}` и в `install.{ps1,sh}` (там 1 of 3 criteria из install-ps1). 2) Скил-структура: `skills/update-claude-skills/SKILL.md`, frontmatter `version: 0.1.0`, описание с триггерами («обнови claude-skills», «sync claude-skills»). Скил — wrapper, не содержит логику. 3) Build + install: `pwsh ./scripts/build.ps1 update-claude-skills`, `pwsh ./scripts/install.ps1 update-claude-skills`. 4) Smoke на текущей машине — должно быть no-op (всё свежее, идемпотентность). 5) Mapping в `hermes/mapping.yaml` (`mode: skip` — Claude-Code-only) или `mode: manual` если параллельно делаем Hermes-twin (логика та же, но Hermes-side скрипт другой — там не install.sh а skill_manage). 6) Обновить `.factory/factory.yaml` post_install: `bash {target}/scripts/update.sh` (или `pwsh ... update.ps1` если factory детектит OS) — отдельный 1-line PR в `.factory`. 7) Doc `.wiki/concepts/claude-skills-update-flow.md` (опционально слить с `install-cross-platform.md` из `[install-ps1]`). 8) `tasks_close`. diff --git a/dist-hermes/SKIPPED.md b/dist-hermes/SKIPPED.md index 65b62f0..fdc0ff5 100644 --- a/dist-hermes/SKIPPED.md +++ b/dist-hermes/SKIPPED.md @@ -12,6 +12,7 @@ Do not edit by hand — edit the mapping and re-run the build. - **caveman-review** — Caveman family — cheap-model context, no compression motive. - **find-skills** — Hermes has built-in skills_list() / progressive disclosure. - **setup-interns** — Hermes itself is a cheap-intern model — the delegation tier collapses. +- **update-claude-skills** — Claude-Code-only orchestrator — Hermes uses hermes-installer-skill instead. - **using-interns** — Hermes itself is a cheap-intern model — the delegation tier collapses. ## Pending (deferred to follow-up tasks) diff --git a/dist-hermes/software-development/project-bootstrap/SKILL.md b/dist-hermes/software-development/project-bootstrap/SKILL.md index 3d5062e..c8c9fae 100644 --- a/dist-hermes/software-development/project-bootstrap/SKILL.md +++ b/dist-hermes/software-development/project-bootstrap/SKILL.md @@ -1,6 +1,6 @@ --- name: project-bootstrap -version: 1.10.0 +version: 1.10.1 description: > Initializes or upgrades a project in the current folder: git, .gitignore, README.md, .wiki/ using Karpathy's method, .tasks/ for task tracking, CLAUDE.md with skill triggers. @@ -338,7 +338,9 @@ use task management system check across all projects pull remote before work follow project discipline +follow tdd-criteria delegate to interns when allowed +recommend, don't menu we're on Windows ``` @@ -365,6 +367,14 @@ push only after explicit per-session approval. Install the skill on the host if `project-discipline` is not in `~/.claude/skills/`; otherwise the trigger is silently dead like any other absent skill. +The `follow tdd-criteria` line activates the `tdd-criteria` skill, which enforces +test-driven development by default with four bright-line carve-outs (visual CSS, +spike exploration, oneshot scripts, pure wrappers) and four anti-loophole rules +(including test-immutability: modifying assertions requires a `[test-modify: ...]` +marker in the commit subject). Full rationale at `.wiki/concepts/tdd-criteria-design.md` +in the `claude-skills` repo. Install the skill on the host if `tdd-criteria` is not +in `~/.claude/skills/`; otherwise the trigger is silently dead like any other absent skill. + The `delegate to interns when allowed` line activates the `using-interns` skill, which lets Claude offload predictable bulk I/O and summarization tasks (reading 3+ files, distilling long transcripts) to cheap intern LLMs via the @@ -378,6 +388,14 @@ server is registered — install via `setup-interns` on a fresh machine if `mcp__interns__*` tools are missing. Full design at `.wiki/concepts/interns-design.md` in the `claude-skills` repo. +The `recommend, don't menu` line activates the `recommend-dont-menu` skill, +which overrides the default `superpowers:brainstorming` behavior: in design +discussions, architecture reviews, or "what should we do" questions, the agent +gives **one argued recommendation with explicit trade-offs**, not a multiple- +choice menu. User instructions always take precedence over skill defaults. +Install the skill on the host if `recommend-dont-menu` is not in `~/.claude/skills/`; +otherwise the trigger is silently dead like any other absent skill. + The `we're on Windows` line activates the `active-platform` skill and pins the project's default platform to Windows / PowerShell — so generated commands and README quick-starts use PS-native syntax. Bootstrapping on a Linux or macOS diff --git a/dist/update-claude-skills.skill b/dist/update-claude-skills.skill new file mode 100644 index 0000000..973ec66 Binary files /dev/null and b/dist/update-claude-skills.skill differ diff --git a/hermes/mapping.yaml b/hermes/mapping.yaml index 4e2046a..125c932 100644 --- a/hermes/mapping.yaml +++ b/hermes/mapping.yaml @@ -133,3 +133,7 @@ skills: recommend-dont-menu: mode: auto category: productivity + + update-claude-skills: + mode: skip + reason: "Claude-Code-only orchestrator — Hermes uses hermes-installer-skill instead." diff --git a/scripts/update.ps1 b/scripts/update.ps1 new file mode 100644 index 0000000..ae7f518 --- /dev/null +++ b/scripts/update.ps1 @@ -0,0 +1,186 @@ +# update.ps1 — Full uplift cycle for claude-skills on Windows (PowerShell) +# +# 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.ps1 +# 5. Show version diff (before -> after) +# 6. Print reload hints +# +# Usage: update.ps1 [-Yes] +# -Yes — skip confirmation prompts (assume yes) + +[CmdletBinding()] +param( + [switch]$Yes +) + +$ErrorActionPreference = 'Stop' + +# ── Paths ────────────────────────────────────────────────────────────────── + +$root = Split-Path -Parent $PSScriptRoot +$skillsSrc = Join-Path $root 'skills' +$target = if ($env:CLAUDE_SKILLS_DIR) { $env:CLAUDE_SKILLS_DIR } else { Join-Path $env:USERPROFILE '.claude\skills' } + +$commonRoot = if ($env:COMMON_ROOT) { $env:COMMON_ROOT } else { Join-Path $env:USERPROFILE 'projects\.common' } +$metaMcp = Join-Path $commonRoot 'lib\projects-meta-mcp' +$internsMcp = Join-Path $commonRoot 'lib\interns-mcp' + +# ── Collect before-versions ──────────────────────────────────────────────── + +$beforeVersions = @{} +if (Test-Path $target) { + Get-ChildItem -Path $target -Directory | ForEach-Object { + $vf = Join-Path $_.FullName 'SKILL.md' + if (Test-Path $vf) { + $ver = (Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' | + Select-Object -First 1).Matches.Groups[1].Value + if (-not $ver) { $ver = '?' } + $beforeVersions[$_.Name] = $ver + } + } +} + +# ── Step 1: git pull ──────────────────────────────────────────────────────── + +Write-Host "`n[update] Pulling claude-skills repo..." -ForegroundColor Cyan +Push-Location $root + +$dirty = git status --porcelain 2>$null +if ($LASTEXITCODE -ne 0) { $dirty = $true } +if ($dirty) { + Write-Host "[warn] Working tree has uncommitted changes. Stashing..." -ForegroundColor Yellow + git stash push -m 'update-ps1-auto-stash' + if ($LASTEXITCODE -ne 0) { Write-Error "Cannot stash changes"; Pop-Location; exit 1 } + $stashed = $true +} else { + $stashed = $false +} + +git pull --ff-only +if ($LASTEXITCODE -ne 0) { + Write-Error "git pull --ff-only failed (diverged or no upstream)" + Pop-Location; exit 1 +} +Write-Host "[ok] Repo updated." -ForegroundColor Green + +if ($stashed) { + Write-Host "[update] Popping stashed changes..." -ForegroundColor Cyan + git stash pop 2>$null + if ($LASTEXITCODE -ne 0) { + Write-Host "[warn] Could not pop stash — resolve manually" -ForegroundColor Yellow + } +} + +# ── Step 2: projects-meta-mcp ───────────────────────────────────────────── + +$mcpRebuilt = $false + +if (Test-Path (Join-Path $metaMcp '.git')) { + Write-Host "[update] Checking projects-meta-mcp..." -ForegroundColor Cyan + Push-Location $metaMcp + $preSha = git rev-parse HEAD + git pull --ff-only 2>$null + if ($LASTEXITCODE -ne 0) { + Write-Host "[warn] projects-meta-mcp: pull failed or no upstream" -ForegroundColor Yellow + } + $postSha = git rev-parse HEAD + + if ($preSha -ne $postSha) { + Write-Host "[update] Source changed, rebuilding projects-meta-mcp..." -ForegroundColor Cyan + npm run build 2>$null + if ($LASTEXITCODE -ne 0) { + npm install; npm run build + } + Write-Host "[ok] projects-meta-mcp rebuilt." -ForegroundColor Green + $mcpRebuilt = $true + } else { + Write-Host "[ok] projects-meta-mcp: up to date." -ForegroundColor Green + } + Pop-Location +} else { + Write-Host "[warn] projects-meta-mcp not found at $metaMcp — skipping." -ForegroundColor Yellow +} + +# ── Step 3: interns-mcp ─────────────────────────────────────────────────── + +if (Test-Path (Join-Path $internsMcp '.git')) { + Write-Host "[update] Checking interns-mcp..." -ForegroundColor Cyan + Push-Location $internsMcp + $preSha = git rev-parse HEAD + git pull --ff-only 2>$null + if ($LASTEXITCODE -ne 0) { + Write-Host "[warn] interns-mcp: pull failed or no upstream" -ForegroundColor Yellow + } + $postSha = git rev-parse HEAD + + if ($preSha -ne $postSha) { + Write-Host "[update] Source changed, reinstalling interns-mcp..." -ForegroundColor Cyan + pip install -e . 2>$null + if ($LASTEXITCODE -ne 0) { pip3 install -e . } + Write-Host "[ok] interns-mcp reinstalled." -ForegroundColor Green + $mcpRebuilt = $true + } else { + Write-Host "[ok] interns-mcp: up to date." -ForegroundColor Green + } + Pop-Location +} else { + Write-Host "[warn] interns-mcp not found at $internsMcp — skipping." -ForegroundColor Yellow +} + +# ── Step 4: Install skills ───────────────────────────────────────────────── + +Pop-Location +Write-Host "[update] Installing skills..." -ForegroundColor Cyan +& "$root\scripts\install.ps1" +Write-Host "[ok] Skills installed." -ForegroundColor Green + +# ── Step 5: Version diff ─────────────────────────────────────────────────── + +Write-Host "[update] Version diff:" -ForegroundColor Cyan +$changes = $false +Get-ChildItem -Path $target -Directory | ForEach-Object { + $vf = Join-Path $_.FullName 'SKILL.md' + if (Test-Path $vf) { + $after = (Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' | + Select-Object -First 1).Matches.Groups[1].Value + if (-not $after) { $after = '?' } + $before = $beforeVersions[$_.Name] + if (-not $before) { $before = 'new' } + if ($before -ne $after) { + Write-Host " $before -> $after ($($_.Name))" + $changes = $true + } + } +} +if (-not $changes) { + Write-Host ' (no version changes)' +} + +# ── Step 6: New setup-skills hint ────────────────────────────────────────── + +$newSetup = @() +Get-ChildItem -Path $skillsSrc -Directory | ForEach-Object { + $name = $_.Name + if ($name -like 'setup-*' -and -not (Test-Path (Join-Path $target $name))) { + $newSetup += $name + } +} + +if ($newSetup.Count -gt 0) { + Write-Host '' + Write-Host '[update] New setup skills available:' -ForegroundColor Cyan + $newSetup | ForEach-Object { Write-Host " - $_" } + Write-Host ' Run the setup skill to configure it.' +} + +# ── Step 7: Reload hints ────────────────────────────────────────────────── + +Write-Host '' +Write-Host '[ok] Update complete!' -ForegroundColor Green +if ($mcpRebuilt) { + Write-Host ' -> Run /reload-mcp to reload MCP servers (source changed)' +} +Write-Host ' -> Start a new Claude session for skill changes to take full effect' \ No newline at end of file diff --git a/scripts/update.sh b/scripts/update.sh new file mode 100644 index 0000000..2467ef5 --- /dev/null +++ b/scripts/update.sh @@ -0,0 +1,175 @@ +#!/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" \ No newline at end of file diff --git a/skills/update-claude-skills/SKILL.md b/skills/update-claude-skills/SKILL.md new file mode 100644 index 0000000..7c8b212 --- /dev/null +++ b/skills/update-claude-skills/SKILL.md @@ -0,0 +1,84 @@ +--- +name: update-claude-skills +version: 0.1.0 +description: > + Full uplift cycle for an existing claude-skills installation: git pull, + conditionally rebuild MCP servers, install skills, show version diff, suggest + reload. Trigger on "update claude-skills", "sync claude-skills", + "обнови claude-skills", "обнови всё", or when the user wants to bring their + skills up to date. Cross-platform (PowerShell on Windows, bash on Linux/macOS). + Does NOT handle greenfield bootstrap — that's project-bootstrap's job. +--- + +# update-claude-skills + +> One command to bring your claude-skills installation fully up to date — repo, MCP servers, skills, and version diff. + +## When this runs + +**On explicit trigger** — when the user says any of: `update claude-skills`, `sync claude-skills`, `обнови claude-skills`, `обнови всё`, `update skills`, or close variants asking to refresh the skills catalog. + +**Never** automatically at session start (that's `pulling-before-work`'s job for the git part). This skill is for the full uplift cycle — git + build + install + diff — which is heavier and intentional. + +## Process + +### 1. Detect platform + +Determine which script to run: + +- **Windows (PowerShell):** `pwsh ~/projects/claude-skills/scripts/update.ps1` +- **Linux / macOS:** `bash ~/projects/claude-skills/scripts/update.sh` + +Use the `active-platform` skill's detection if available. Otherwise: +- If `$env:OS` is `Windows_NT` or `IsWindows` is true → PowerShell path. +- Otherwise → bash path. + +If the repo is at a non-default location, adjust the path accordingly (the user may have cloned to `~/projects/claude-skills` or another directory — check `git -C rev-parse --is-inside-work-tree` if unsure). + +### 2. Run the update script + +Execute the appropriate script. Show the output to the user — it contains version diffs and reload hints. + +If the script exits non-zero, **stop** and show the error. Common failures: +- `git pull --ff-only` fails → the repo has diverged or there's no upstream. The user must resolve manually. +- MCP build fails → show the error, suggest running `npm run build` / `pip install -e .` manually. + +### 3. Offer to reload MCP servers + +If the script output mentions "MCP servers rebuilt" or "source changed": + +> MCP servers were rebuilt. Run `/reload-mcp` to reload them. + +If no MCP changes: + +> Skills updated. Start a new session (or `/clear`) for changes to take full effect. + +### 4. Offer to run new setup skills + +If the script detected new `setup-*` skills that aren't yet installed: + +> New setup skills available: ``. Want me to run any of them? + +The user decides — never auto-run setup skills. + +## What the scripts do + +The update scripts (`scripts/update.sh` and `scripts/update.ps1`) handle: + +1. **git pull --ff-only** in `~/projects/claude-skills/` (stash if dirty, pop after). +2. **Conditionally rebuild projects-meta-mcp** — if `~/projects/.common/lib/projects-meta-mcp/` has a `.git` directory and source changed (`git pull` fetched new commits), run `npm run build`. +3. **Conditionally rebuild interns-mcp** — same pattern, `pip install -e .`. +4. **Install all skills** via `install.sh` / `install.ps1`. +5. **Show version diff** — before/after `version:` frontmatter for each skill. +6. **Print reload hints** — `/reload-mcp` if MCP changed, new session otherwise. + +## Out of scope + +- **Greenfield bootstrap** — use `project-bootstrap` for first-time setup on a new machine. +- **`--prune` flag** — removing skills not in `skills/` from `~/.claude/skills/`. Tracked separately in `[install-ps1]`. +- **Hermes-side update** — `hermes-installer-skill` handles the Hermes/Linux factory path. +- **Auto-run setup skills** — the user decides which new setup skills to configure. + +## Cross-agent applicability + +Pure orchestration — calls platform scripts, no Claude-specific tool references. Hermes-mappable as `mode: skip` (Claude-Code-only; Hermes uses `hermes-installer-skill` instead). \ No newline at end of file