feat(update-skills): dual install target — ~/.claude/skills + ~/.agents/skills (agent-neutral); pi settings hack removed (v0.2.1)
This commit is contained in:
@@ -397,13 +397,14 @@ needs-claude
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🟡 [agent-neutral-skill-pipeline] — ДОЛГ (идея 19 п.5, буфер claude-to-agents): инсталл/апдейт-пайплайн скилов — claude-only. update-claude-skills ставит только в ~/.claude/skills; pi получил каталог вручную (settings skills array, идея 6). Цель: update-skills обслуживает всех агентов (единый канон + честный per-agent срез). Связано с ренеймом репо (rename-repo-to-skills) и чисткой ~/.agents/skills. Сейчас НЕ исполняем (долг, status=paused) — осознанно отложено.
|
## 🟢 [agent-neutral-skill-pipeline] — ДОЛГ (идея 19 п.5): инсталл/апдейт-пайплайн скилов — claude-only. update-claude-skills ставил только в ~/.claude/skills; pi получил каталог вручную (settings skills array, идея 6). Цель: update-skills обслуживает всех агентов (единый канон + честный per-agent срез).
|
||||||
|
|
||||||
**Status:** paused
|
**Status:** done
|
||||||
**Where I stopped:** (not started)
|
**Where I stopped:** РЕШЕНИЕ ОПЕРАТОРА (2026-08-12, зафиксировано после вскрытия непротоколированного решения вчерашней сессии «канон = ~/.claude/skills»): **dual install target**. install.sh/ps1 + update.sh/ps1 ставят в ОБА каталога: ~/.claude/skills (Claude Code — читает только его нативно, кастомные диры не конфигурируются) + ~/.agents/skills (pi — нативный скан-путь, нейтральный неймспейс .agents/). Из ~/.pi/agent/settings.json убран skills-массив (вендор-лок устранён). update-skills SKILL.md v0.2.1 — секция «Install targets (dual, agent-neutral)», semver-bump, lint 46/0. Оба таргета синхронны (46/46, diff IDENTICAL). Источник истины — git-репо skills/, оба дира — инсталлы.
|
||||||
**Next action:** (пауза) После rename-repo-to-skills: спроектировать update-skills с таргетами ~/.claude/skills + ~/.agents/skills + (pi settings), подтвердить у владельца
|
**Next action:** (none — kept until merged) pi перезапустить чтобы убедиться, что скилы грузятся из ~/.agents/skills (нативный скан без settings-хака).
|
||||||
**Branch:** n/a
|
**Branch:** master
|
||||||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-08-12T09:58:08.312Z -->
|
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-08-12T09:58:08.312Z -->
|
||||||
|
<!-- closed-by: pi session 2026-08-12 / dual install target: ~/.claude/skills + ~/.agents/skills, pi settings hack убран, update-skills v0.2.1 -->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
BIN
dist/update-skills.skill
vendored
BIN
dist/update-skills.skill
vendored
Binary file not shown.
@@ -1,6 +1,10 @@
|
|||||||
# Install skills/<name>/ into ~\.claude\skills\<name>\ (or $env:CLAUDE_SKILLS_DIR)
|
# Install skills/<name>/ into BOTH agent skill dirs:
|
||||||
|
# ~\.claude\skills\<name>\ (Claude Code — native, not configurable)
|
||||||
|
# ~\.agents\skills\<name>\ (pi — native default scan path, agent-neutral namespace)
|
||||||
|
# $env:CLAUDE_SKILLS_DIR overrides ONLY the claude target (for testing/CI).
|
||||||
|
#
|
||||||
# Usage: install.ps1 [-Names <name1>,<name2>] [-Prune]
|
# Usage: install.ps1 [-Names <name1>,<name2>] [-Prune]
|
||||||
# no args = install all skills/* into target
|
# no args = install all skills/* into both targets
|
||||||
# -Prune = after install, remove target/<name>/ dirs that are NOT in skills/*
|
# -Prune = after install, remove target/<name>/ dirs that are NOT in skills/*
|
||||||
# (prune always scans full target, ignores -Names filter — it's a global cleanup)
|
# (prune always scans full target, ignores -Names filter — it's a global cleanup)
|
||||||
#
|
#
|
||||||
@@ -17,45 +21,54 @@ $ErrorActionPreference = 'Stop'
|
|||||||
$root = Split-Path -Parent $PSScriptRoot
|
$root = Split-Path -Parent $PSScriptRoot
|
||||||
$src = Join-Path $root 'skills'
|
$src = Join-Path $root 'skills'
|
||||||
|
|
||||||
|
# Dual install targets — the "canon" is the git repo (skills/); both dirs are installs.
|
||||||
|
$targets = @()
|
||||||
if ($env:CLAUDE_SKILLS_DIR) {
|
if ($env:CLAUDE_SKILLS_DIR) {
|
||||||
$target = $env:CLAUDE_SKILLS_DIR
|
$targets += $env:CLAUDE_SKILLS_DIR
|
||||||
} else {
|
} else {
|
||||||
$target = Join-Path $env:USERPROFILE '.claude\skills'
|
$targets += (Join-Path $env:USERPROFILE '.claude\skills')
|
||||||
}
|
}
|
||||||
|
$targets += (Join-Path $env:USERPROFILE '.agents\skills')
|
||||||
|
|
||||||
if (-not (Test-Path $target)) {
|
foreach ($target in $targets) {
|
||||||
New-Item -ItemType Directory -Force -Path $target | Out-Null
|
if (-not (Test-Path $target)) {
|
||||||
|
New-Item -ItemType Directory -Force -Path $target | Out-Null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Names.Count -eq 0) {
|
if ($Names.Count -eq 0) {
|
||||||
$Names = Get-ChildItem -Path $src -Directory | Sort-Object Name | Select-Object -ExpandProperty Name
|
$Names = Get-ChildItem -Path $src -Directory | Sort-Object Name | Select-Object -ExpandProperty Name
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($name in $Names) {
|
foreach ($target in $targets) {
|
||||||
$srcDir = Join-Path $src $name
|
foreach ($name in $Names) {
|
||||||
$dstDir = Join-Path $target $name
|
$srcDir = Join-Path $src $name
|
||||||
if (-not (Test-Path $srcDir -PathType Container)) {
|
$dstDir = Join-Path $target $name
|
||||||
Write-Warning "skip: $name (not found in skills/)"
|
if (-not (Test-Path $srcDir -PathType Container)) {
|
||||||
continue
|
Write-Warning "skip: $name (not found in skills/)"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (-not (Test-Path (Join-Path $srcDir 'SKILL.md'))) {
|
||||||
|
Write-Warning "skip: $name (missing SKILL.md)"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (Test-Path $dstDir) {
|
||||||
|
Remove-Item -Recurse -Force $dstDir
|
||||||
|
}
|
||||||
|
Copy-Item -Recurse $srcDir $dstDir
|
||||||
|
Write-Host "installed: $name -> $dstDir"
|
||||||
}
|
}
|
||||||
if (-not (Test-Path (Join-Path $srcDir 'SKILL.md'))) {
|
|
||||||
Write-Warning "skip: $name (missing SKILL.md)"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (Test-Path $dstDir) {
|
|
||||||
Remove-Item -Recurse -Force $dstDir
|
|
||||||
}
|
|
||||||
Copy-Item -Recurse $srcDir $dstDir
|
|
||||||
Write-Host "installed: $name -> $dstDir"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Prune) {
|
if ($Prune) {
|
||||||
$sourceNames = @(Get-ChildItem -Path $src -Directory | Select-Object -ExpandProperty Name)
|
$sourceNames = @(Get-ChildItem -Path $src -Directory | Select-Object -ExpandProperty Name)
|
||||||
$installedDirs = Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue
|
foreach ($target in $targets) {
|
||||||
foreach ($dir in $installedDirs) {
|
$installedDirs = Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue
|
||||||
if ($sourceNames -notcontains $dir.Name) {
|
foreach ($dir in $installedDirs) {
|
||||||
Write-Host "pruning: $($dir.Name) (not in skills/) -> $($dir.FullName)"
|
if ($sourceNames -notcontains $dir.Name) {
|
||||||
Remove-Item -Recurse -Force $dir.FullName
|
Write-Host "pruning: $($dir.Name) (not in skills/) -> $($dir.FullName)"
|
||||||
|
Remove-Item -Recurse -Force $dir.FullName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Install skills/<name>/ into ~/.claude/skills/<name>/ (or $CLAUDE_SKILLS_DIR)
|
# Install skills/<name>/ into BOTH agent skill dirs:
|
||||||
|
# ~/.claude/skills/<name>/ (Claude Code — native, not configurable)
|
||||||
|
# ~/.agents/skills/<name>/ (pi — native default scan path, agent-neutral namespace)
|
||||||
|
# $CLAUDE_SKILLS_DIR overrides ONLY the claude target (for testing/CI).
|
||||||
|
#
|
||||||
# Usage: install.sh [--prune] [name...]
|
# Usage: install.sh [--prune] [name...]
|
||||||
# no args = install all skills/* into target
|
# no args = install all skills/* into both targets
|
||||||
# --prune = after install, remove target/<name>/ dirs that are NOT in skills/*
|
# --prune = after install, remove target/<name>/ dirs that are NOT in skills/*
|
||||||
# (prune always scans full target, ignores name filter — global cleanup)
|
# (prune always scans full target, ignores name filter — global cleanup)
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
SRC="$ROOT/skills"
|
SRC="$ROOT/skills"
|
||||||
TARGET="${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}"
|
|
||||||
|
# Dual install targets — the "canon" is the git repo (skills/); both dirs are installs.
|
||||||
|
TARGETS=("${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}" "$HOME/.agents/skills")
|
||||||
|
|
||||||
prune=0
|
prune=0
|
||||||
positional=()
|
positional=()
|
||||||
@@ -33,31 +39,37 @@ else
|
|||||||
names=("${positional[@]}")
|
names=("${positional[@]}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$TARGET"
|
for target in "${TARGETS[@]}"; do
|
||||||
|
mkdir -p "$target"
|
||||||
|
done
|
||||||
|
|
||||||
for name in "${names[@]}"; do
|
for target in "${TARGETS[@]}"; do
|
||||||
src_dir="$SRC/$name"
|
for name in "${names[@]}"; do
|
||||||
dst_dir="$TARGET/$name"
|
src_dir="$SRC/$name"
|
||||||
if [ ! -d "$src_dir" ]; then
|
dst_dir="$target/$name"
|
||||||
echo "skip: $name (not found in skills/)" >&2
|
if [ ! -d "$src_dir" ]; then
|
||||||
continue
|
echo "skip: $name (not found in skills/)" >&2
|
||||||
fi
|
continue
|
||||||
if [ ! -f "$src_dir/SKILL.md" ]; then
|
fi
|
||||||
echo "skip: $name (missing SKILL.md)" >&2
|
if [ ! -f "$src_dir/SKILL.md" ]; then
|
||||||
continue
|
echo "skip: $name (missing SKILL.md)" >&2
|
||||||
fi
|
continue
|
||||||
rm -rf "$dst_dir"
|
fi
|
||||||
cp -R "$src_dir" "$dst_dir"
|
rm -rf "$dst_dir"
|
||||||
echo "installed: $name → $dst_dir"
|
cp -R "$src_dir" "$dst_dir"
|
||||||
|
echo "installed: $name → $dst_dir"
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$prune" -eq 1 ]; then
|
if [ "$prune" -eq 1 ]; then
|
||||||
for d in "$TARGET"/*/; do
|
for target in "${TARGETS[@]}"; do
|
||||||
[ -d "$d" ] || continue
|
for d in "$target"/*/; do
|
||||||
name="$(basename "$d")"
|
[ -d "$d" ] || continue
|
||||||
if [ ! -d "$SRC/$name" ]; then
|
name="$(basename "$d")"
|
||||||
echo "pruning: $name (not in skills/) → $d"
|
if [ ! -d "$SRC/$name" ]; then
|
||||||
rm -rf "$d"
|
echo "pruning: $name (not in skills/) → $d"
|
||||||
fi
|
rm -rf "$d"
|
||||||
|
fi
|
||||||
|
done
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ $ErrorActionPreference = 'Stop'
|
|||||||
|
|
||||||
$root = Split-Path -Parent $PSScriptRoot
|
$root = Split-Path -Parent $PSScriptRoot
|
||||||
$skillsSrc = Join-Path $root 'skills'
|
$skillsSrc = Join-Path $root 'skills'
|
||||||
$target = if ($env:CLAUDE_SKILLS_DIR) { $env:CLAUDE_SKILLS_DIR } else { Join-Path $env:USERPROFILE '.claude\skills' }
|
# Dual install targets — the "canon" is the git repo (skills/); both dirs are installs.
|
||||||
|
$targets = @()
|
||||||
|
if ($env:CLAUDE_SKILLS_DIR) { $targets += $env:CLAUDE_SKILLS_DIR } else { $targets += (Join-Path $env:USERPROFILE '.claude\skills') }
|
||||||
|
$targets += (Join-Path $env:USERPROFILE '.agents\skills')
|
||||||
|
|
||||||
$commonRoot = if ($env:COMMON_ROOT) { $env:COMMON_ROOT } else { Join-Path $env:USERPROFILE 'projects\.common' }
|
$commonRoot = if ($env:COMMON_ROOT) { $env:COMMON_ROOT } else { Join-Path $env:USERPROFILE 'projects\.common' }
|
||||||
$metaMcp = Join-Path $commonRoot 'lib\projects-meta-mcp'
|
$metaMcp = Join-Path $commonRoot 'lib\projects-meta-mcp'
|
||||||
@@ -31,13 +34,15 @@ $internsMcp = Join-Path $commonRoot 'lib\interns-mcp'
|
|||||||
# -- Collect before-versions --------------------------------------------------
|
# -- Collect before-versions --------------------------------------------------
|
||||||
|
|
||||||
$beforeVersions = @{}
|
$beforeVersions = @{}
|
||||||
if (Test-Path $target) {
|
foreach ($target in $targets) {
|
||||||
Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
if (Test-Path $target) {
|
||||||
$vf = Join-Path $_.FullName 'SKILL.md'
|
Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
if (Test-Path $vf) {
|
$vf = Join-Path $_.FullName 'SKILL.md'
|
||||||
$match = Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' -ErrorAction SilentlyContinue | Select-Object -First 1
|
if (Test-Path $vf) {
|
||||||
$ver = if ($match) { $match.Matches.Groups[1].Value } else { '?' }
|
$match = Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
$beforeVersions[$_.Name] = $ver
|
$ver = if ($match) { $match.Matches.Groups[1].Value } else { '?' }
|
||||||
|
$beforeVersions[$_.Name] = $ver
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,16 +149,18 @@ Write-Host "[ok] Skills installed." -ForegroundColor Green
|
|||||||
|
|
||||||
Write-Host "[update] Version diff:" -ForegroundColor Cyan
|
Write-Host "[update] Version diff:" -ForegroundColor Cyan
|
||||||
$changes = $false
|
$changes = $false
|
||||||
Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
foreach ($target in $targets) {
|
||||||
$vf = Join-Path $_.FullName 'SKILL.md'
|
Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
if (Test-Path $vf) {
|
$vf = Join-Path $_.FullName 'SKILL.md'
|
||||||
$match = Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' -ErrorAction SilentlyContinue | Select-Object -First 1
|
if (Test-Path $vf) {
|
||||||
$after = if ($match) { $match.Matches.Groups[1].Value } else { '?' }
|
$match = Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
$before = $beforeVersions[$_.Name]
|
$after = if ($match) { $match.Matches.Groups[1].Value } else { '?' }
|
||||||
if (-not $before) { $before = 'new' }
|
$before = $beforeVersions[$_.Name]
|
||||||
if ($before -ne $after) {
|
if (-not $before) { $before = 'new' }
|
||||||
Write-Host " $before -> $after ($($_.Name))"
|
if ($before -ne $after) {
|
||||||
$changes = $true
|
Write-Host " $before -> $after ($($_.Name))"
|
||||||
|
$changes = $true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,9 +173,11 @@ if (-not $changes) {
|
|||||||
$newSetup = @()
|
$newSetup = @()
|
||||||
Get-ChildItem -Path $skillsSrc -Directory | ForEach-Object {
|
Get-ChildItem -Path $skillsSrc -Directory | ForEach-Object {
|
||||||
$name = $_.Name
|
$name = $_.Name
|
||||||
if ($name -like 'setup-*' -and -not (Test-Path (Join-Path $target $name))) {
|
$missing = $false
|
||||||
$newSetup += $name
|
foreach ($target in $targets) {
|
||||||
|
if ($name -like 'setup-*' -and -not (Test-Path (Join-Path $target $name))) { $missing = $true }
|
||||||
}
|
}
|
||||||
|
if ($missing) { $newSetup += $name }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($newSetup.Count -gt 0) {
|
if ($newSetup.Count -gt 0) {
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ YES_MODE=false
|
|||||||
|
|
||||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
SKILLS_SRC="$ROOT/skills"
|
SKILLS_SRC="$ROOT/skills"
|
||||||
TARGET="${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}"
|
# Dual install targets — the "canon" is the git repo (skills/); both dirs are installs.
|
||||||
|
TARGETS=("${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}" "$HOME/.agents/skills")
|
||||||
|
|
||||||
COMMON_ROOT="${COMMON_ROOT:-$HOME/projects/.common}"
|
COMMON_ROOT="${COMMON_ROOT:-$HOME/projects/.common}"
|
||||||
META_MCP="$COMMON_ROOT/lib/projects-meta-mcp"
|
META_MCP="$COMMON_ROOT/lib/projects-meta-mcp"
|
||||||
@@ -43,8 +44,9 @@ confirm() {
|
|||||||
# ── Collect before-versions ────────────────────────────────────────────────
|
# ── Collect before-versions ────────────────────────────────────────────────
|
||||||
|
|
||||||
declare -A BEFORE_VERSIONS=()
|
declare -A BEFORE_VERSIONS=()
|
||||||
if [[ -d "$TARGET" ]]; then
|
for target in "${TARGETS[@]}"; do
|
||||||
for skill_dir in "$TARGET"/*/; do
|
[[ -d "$target" ]] || continue
|
||||||
|
for skill_dir in "$target"/*/; do
|
||||||
name="$(basename "$skill_dir")"
|
name="$(basename "$skill_dir")"
|
||||||
vf="$skill_dir/SKILL.md"
|
vf="$skill_dir/SKILL.md"
|
||||||
if [[ -f "$vf" ]]; then
|
if [[ -f "$vf" ]]; then
|
||||||
@@ -52,7 +54,7 @@ if [[ -d "$TARGET" ]]; then
|
|||||||
BEFORE_VERSIONS["$name"]="$ver"
|
BEFORE_VERSIONS["$name"]="$ver"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
done
|
||||||
|
|
||||||
# ── Step 1: git pull ────────────────────────────────────────────────────────
|
# ── Step 1: git pull ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -133,17 +135,19 @@ ok "Skills installed."
|
|||||||
|
|
||||||
info "Version diff:"
|
info "Version diff:"
|
||||||
CHANGES=false
|
CHANGES=false
|
||||||
for skill_dir in "$TARGET"/*/; do
|
for target in "${TARGETS[@]}"; do
|
||||||
name="$(basename "$skill_dir")"
|
for skill_dir in "$target"/*/; do
|
||||||
vf="$skill_dir/SKILL.md"
|
name="$(basename "$skill_dir")"
|
||||||
if [[ -f "$vf" ]]; then
|
vf="$skill_dir/SKILL.md"
|
||||||
after="$(grep -oP '^version:\s*\K[0-9]+\.[0-9]+\.[0-9]+' "$vf" 2>/dev/null || echo '?')"
|
if [[ -f "$vf" ]]; then
|
||||||
before="${BEFORE_VERSIONS[$name]:-new}"
|
after="$(grep -oP '^version:\s*\K[0-9]+\.[0-9]+\.[0-9]+' "$vf" 2>/dev/null || echo '?')"
|
||||||
if [[ "$before" != "$after" ]]; then
|
before="${BEFORE_VERSIONS[$name]:-new}"
|
||||||
echo " $before → $after ($name)"
|
if [[ "$before" != "$after" ]]; then
|
||||||
CHANGES=true
|
echo " $before → $after ($name)"
|
||||||
|
CHANGES=true
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
done
|
||||||
done
|
done
|
||||||
if ! $CHANGES; then
|
if ! $CHANGES; then
|
||||||
echo " (no version changes)"
|
echo " (no version changes)"
|
||||||
@@ -154,8 +158,12 @@ fi
|
|||||||
NEW_SETUP=()
|
NEW_SETUP=()
|
||||||
for skill_dir in "$SKILLS_SRC"/*/; do
|
for skill_dir in "$SKILLS_SRC"/*/; do
|
||||||
name="$(basename "$skill_dir")"
|
name="$(basename "$skill_dir")"
|
||||||
if [[ "$name" == setup-* ]] && [[ ! -d "$TARGET/$name" ]]; then
|
if [[ "$name" == setup-* ]]; then
|
||||||
NEW_SETUP+=("$name")
|
missing=false
|
||||||
|
for target in "${TARGETS[@]}"; do
|
||||||
|
[[ ! -d "$target/$name" ]] && missing=true
|
||||||
|
done
|
||||||
|
$missing && NEW_SETUP+=("$name")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: update-skills
|
name: update-skills
|
||||||
author: ours
|
author: ours
|
||||||
version: 0.2.0
|
version: 0.2.1
|
||||||
description: >
|
description: >
|
||||||
Full uplift cycle for an existing skills installation: git pull,
|
Full uplift cycle for an existing skills installation: git pull,
|
||||||
conditionally rebuild MCP servers, install skills, show version diff, suggest
|
conditionally rebuild MCP servers, install skills, show version diff, suggest
|
||||||
@@ -54,6 +54,10 @@ If no MCP changes:
|
|||||||
|
|
||||||
> Skills updated. Start a new session (or `/clear`) for changes to take full effect.
|
> Skills updated. Start a new session (or `/clear`) for changes to take full effect.
|
||||||
|
|
||||||
|
Both agents pick up the new catalog on their next session: Claude Code reads
|
||||||
|
`~/.claude/skills` natively; pi reads `~/.agents/skills` natively (default
|
||||||
|
scan path — no settings needed). See "Install targets" below.
|
||||||
|
|
||||||
### 4. Offer to run new setup skills
|
### 4. Offer to run new setup skills
|
||||||
|
|
||||||
If the script detected new `setup-*` skills that aren't yet installed:
|
If the script detected new `setup-*` skills that aren't yet installed:
|
||||||
@@ -62,6 +66,20 @@ If the script detected new `setup-*` skills that aren't yet installed:
|
|||||||
|
|
||||||
The user decides — never auto-run setup skills.
|
The user decides — never auto-run setup skills.
|
||||||
|
|
||||||
|
## Install targets (dual, agent-neutral)
|
||||||
|
|
||||||
|
The canon is the git repo — `skills/<name>/SKILL.md`. `install.sh` / `install.ps1`
|
||||||
|
install into **both** agent dirs (identical copies, synced by the script — no drift):
|
||||||
|
|
||||||
|
| Target | Agent | Why |
|
||||||
|
|---|---|---|
|
||||||
|
| `~/.claude/skills` | Claude Code | Claude Code reads this natively; custom skill dirs are NOT configurable in Claude Code (only plugin `skillsPaths`) |
|
||||||
|
| `~/.agents/skills` | pi | pi reads this natively (default scan path); the agent-neutral `.agents/` namespace is our convention |
|
||||||
|
|
||||||
|
`$CLAUDE_SKILLS_DIR` / `$env:CLAUDE_SKILLS_DIR` overrides only the claude target (for testing/CI).
|
||||||
|
pi must NOT have `~/.claude/skills` in its settings `skills` array — that was the old vendor-locked
|
||||||
|
setup; pi loads `~/.agents/skills` by default. Verify with `pi --help` / a fresh session listing skills.
|
||||||
|
|
||||||
## What the scripts do
|
## What the scripts do
|
||||||
|
|
||||||
The update scripts (`scripts/update.sh` and `scripts/update.ps1`) handle:
|
The update scripts (`scripts/update.sh` and `scripts/update.ps1`) handle:
|
||||||
@@ -76,7 +94,7 @@ The update scripts (`scripts/update.sh` and `scripts/update.ps1`) handle:
|
|||||||
## Out of scope
|
## Out of scope
|
||||||
|
|
||||||
- **Greenfield bootstrap** — use `project-bootstrap` for first-time setup on a new machine.
|
- **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]`.
|
- **`--prune` flag** — removing skills not in `skills/` from the install targets (both `~/.claude/skills/` and `~/.agents/skills/`). Tracked separately in `[install-ps1]`.
|
||||||
- **Hermes-side update** — `hermes-installer-skill` handles the Hermes/Linux factory path.
|
- **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.
|
- **Auto-run setup skills** — the user decides which new setup skills to configure.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user