Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions kimaki/post-upgrade.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#!/usr/bin/env bash
# post-upgrade.sh — Remove unwanted bundled Kimaki skills.
# post-upgrade.sh — Enforce kimaki skill state on every restart.
#
# Two symmetric passes run against $(npm root -g)/kimaki/skills/:
# 1. KILL — remove unwanted bundled kimaki skills listed in skills-kill-list.txt.
# 2. RESTORE — re-copy wp-coding-agents skills from the persistent source dir
# (kimaki-config/skills/). `npm update -g kimaki` wipes the
# bundled skills dir, so without this restore pass Discord
# slash commands silently degrade between upgrades.
#
# Invoked two ways:
# VPS: ExecStartPre in kimaki.service (runs on every service start).
Expand All @@ -9,6 +16,12 @@
# 1. KIMAKI_SKILLS_DIR env var (explicit override)
# 2. $(npm root -g)/kimaki/skills (works on macOS + Linux when npm is on PATH)
# 3. /usr/lib/node_modules/kimaki/skills (Linux VPS fallback when npm absent)
#
# Persistent skill source dir resolution priority:
# 1. KIMAKI_SKILL_SOURCE_DIR env var (explicit override)
# 2. $KIMAKI_DATA_DIR/kimaki-config/skills/ if KIMAKI_DATA_DIR set
# 3. $HOME/.kimaki/kimaki-config/skills/ (local default)
# 4. /opt/kimaki-config/skills/ (VPS default)
set -euo pipefail

if [[ -n "${KIMAKI_SKILLS_DIR:-}" ]]; then
Expand Down Expand Up @@ -48,4 +61,34 @@ while IFS= read -r skill || [[ -n "$skill" ]]; do
fi
done < "$KILL_LIST"

echo "kimaki-config: done ($removed skills removed)"
# Restore pass — re-copy wp-coding-agents skills from the persistent source
# dir. Idempotent: `rm -rf` before each `cp -r` so a stale copy in SKILLS_DIR
# always gets replaced by the current source.
if [[ -n "${KIMAKI_SKILL_SOURCE_DIR:-}" ]]; then
SOURCE_DIR="$KIMAKI_SKILL_SOURCE_DIR"
elif [[ -n "${KIMAKI_DATA_DIR:-}" ]]; then
SOURCE_DIR="$KIMAKI_DATA_DIR/kimaki-config/skills"
elif [[ -d "$HOME/.kimaki/kimaki-config/skills" ]]; then
SOURCE_DIR="$HOME/.kimaki/kimaki-config/skills"
else
SOURCE_DIR="/opt/kimaki-config/skills"
fi

restored=0
if [[ -d "$SOURCE_DIR" ]]; then
for skill_dir in "$SOURCE_DIR"/*/; do
[[ -d "$skill_dir" ]] || continue
skill_name="$(basename "$skill_dir")"
if [[ -f "$skill_dir/SKILL.md" ]]; then
target="$SKILLS_DIR/$skill_name"
rm -rf "$target"
cp -r "$skill_dir" "$target"
echo "kimaki-config: restored $skill_name"
restored=$((restored + 1))
fi
done
else
echo "kimaki-config: persistent skill source dir not found at $SOURCE_DIR, skipping restore"
fi

echo "kimaki-config: done ($removed skills removed, $restored skills restored)"
54 changes: 53 additions & 1 deletion lib/skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,51 @@ install_skills_from_local_repo() {
fi
}

# Mirror every SKILL.md-containing subdir from $SKILLS_DIR into the
# persistent kimaki-config/skills/ dir. This is the durable source of
# truth that survives `npm update -g kimaki` wipes — kimaki/post-upgrade.sh
# reads from this path on every kimaki restart to restore the mirror copy
# at $(npm root -g)/kimaki/skills/.
#
# Path resolution matches the plugin-persistence pattern used elsewhere:
# Local: $KIMAKI_DATA_DIR/kimaki-config/skills/ (defaults to ~/.kimaki/kimaki-config/skills/)
# VPS: /opt/kimaki-config/skills/
install_skills_to_persistent_source() {
local persistent_dir
if [ "$LOCAL_MODE" = true ]; then
local data_dir="${KIMAKI_DATA_DIR:-$HOME/.kimaki}"
persistent_dir="$data_dir/kimaki-config/skills"
else
persistent_dir="/opt/kimaki-config/skills"
fi

if [ "$DRY_RUN" = true ]; then
echo -e "${BLUE}[dry-run]${NC} Would mirror skills to persistent source: $persistent_dir/"
return
fi

mkdir -p "$persistent_dir" 2>/dev/null || {
warn "Could not create persistent skill source dir $persistent_dir — skipping mirror"
return
}

local copied=0
for skill_dir in "$SKILLS_DIR"/*/; do
[ -d "$skill_dir" ] || continue
local skill_name
skill_name=$(basename "$skill_dir")
if [ -f "$skill_dir/SKILL.md" ]; then
rm -rf "$persistent_dir/$skill_name"
cp -r "$skill_dir" "$persistent_dir/$skill_name"
copied=$((copied + 1))
fi
done
if [ "$copied" -gt 0 ]; then
log "Skills mirrored to persistent source: $persistent_dir/ ($copied)"
log " post-upgrade.sh will restore these on every kimaki restart."
fi
}

install_skills() {
SKILLS_DIR="$(runtime_skills_dir)"

Expand Down Expand Up @@ -94,9 +139,16 @@ install_skills() {
fi
done
log "Skills also copied to Kimaki: $KIMAKI_SKILLS_DIR/"
warn "Note: Kimaki upgrades (npm update -g kimaki) will remove these. Re-run --skills-only after upgrading."
fi
fi

# Mirror skills into the persistent kimaki-config/skills/ dir so
# post-upgrade.sh can restore them on every kimaki restart after
# `npm update -g kimaki` wipes $(npm root -g)/kimaki/skills/.
# Path mirrors the plugin-persistence pattern:
# Local: $KIMAKI_DATA_DIR/kimaki-config/skills/ (defaults to ~/.kimaki/kimaki-config/skills/)
# VPS: /opt/kimaki-config/skills/
install_skills_to_persistent_source
fi
else
log "Phase 8.5: Skipping agent skills (--no-skills)"
Expand Down
9 changes: 8 additions & 1 deletion skills/upgrade-wp-coding-agents/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,14 @@ Drop `--dry-run`:

Backups are written next to each touched file with a timestamp suffix. On VPS that means `/opt/kimaki-config.backup.<ts>`, `AGENTS.md.backup.<ts>`, `kimaki.service.backup.<ts>`. On local, the kimaki-config backup lands under `$KIMAKI_DATA_DIR/backups/` (defaults to `~/.kimaki/backups/`).

On local, `upgrade.sh` also runs `post-upgrade.sh` inline to enforce the skills kill list against the npm-installed kimaki package — VPS gets this on the next `systemctl restart kimaki` via the unit's `ExecStartPre`.
### Persistent skill source

`--skills-only` (and a full run) also mirrors every installed skill into the persistent kimaki-config skill source dir. This is the durable copy that survives `npm update -g kimaki` wipes of `$(npm root -g)/kimaki/skills/`:

- **Local:** `$KIMAKI_DATA_DIR/kimaki-config/skills/` (defaults to `~/.kimaki/kimaki-config/skills/`)
- **VPS:** `/opt/kimaki-config/skills/`

On local, `upgrade.sh` runs `post-upgrade.sh` inline. On VPS, `kimaki.service`'s `ExecStartPre` runs it on next service start. `post-upgrade.sh` performs two symmetric passes against `$(npm root -g)/kimaki/skills/`: (1) remove the unwanted bundled skills listed in `skills-kill-list.txt`, and (2) restore the wp-coding-agents skills from the persistent source dir. Both passes are idempotent and run on every kimaki restart.

## Step 5 — Verify

Expand Down
Loading