Files
pi-kit/uninstall.sh
Aleksey Shakhmatov 035bededb0 feat(uninstall): one-command full uninstall with confirmation
- uninstall.sh: removes pi-kit from settings.json (string + gated object
  entries), the package clone, kit-installed public skills, ~/.config/pi-kit
  (env.sh with tokens, audit.jsonl) and the shell-rc sourcing block
- confirmation prompt by default; PI_KIT_UNINSTALL=1 for non-interactive,
  PI_KIT_KEEP_CONFIG=1 / PI_KIT_KEEP_SKILLS=1 to retain parts
- works without the pi binary (settings edited directly); notes how to
  remove pi itself
- tests: test/uninstall.test.sh against a throwaway $HOME (14 checks:
  full/partial removal, refusal without flag, idempotent re-run), wired
  into npm test
2026-08-06 11:45:50 +03:00

197 lines
7.7 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#
# pi-kit uninstall — removes the corporate kit from this machine completely.
# Idempotent: safe to re-run; missing pieces are skipped with a note.
#
# Usage (one command, asks for confirmation):
# curl -fsSL https://git.codelab.vc/ai/pi-kit/raw/branch/stable/uninstall.sh | bash
# # or, from a checkout:
# ./uninstall.sh
#
# What it removes:
# 1. the pi-kit package entry from ~/.pi/agent/settings.json and its clone
# (~/.pi/agent/git/git.codelab.vc/ai/pi-kit);
# 2. public skills the kit installed into ~/.agents/skills/
# (grill-me, grill-with-docs, code-review, diagnosing-bugs, frontend-design);
# 3. ~/.config/pi-kit (env.sh with tokens, audit.jsonl) and the sourcing block
# it added to your shell rc — only if you confirm (or unless kept).
#
# Non-interactive / skip confirmation: PI_KIT_UNINSTALL=1
# Keep secrets & rc block: PI_KIT_KEEP_CONFIG=1
# Keep public skills: PI_KIT_KEEP_SKILLS=1
#
# Pi itself is NOT removed (it may be used outside the kit). See the final note.
#
set -euo pipefail
# Mirrors the list in install.sh (COMMON_PUBLIC_SKILLS + PROFILE_PUBLIC).
PUBLIC_SKILLS=("grill-me" "grill-with-docs" "code-review" "diagnosing-bugs" "frontend-design")
SETTINGS="$HOME/.pi/agent/settings.json"
CONFIG_DIR="$HOME/.config/pi-kit"
ENV_FILE="$CONFIG_DIR/env.sh"
RC_MARK=">>> pi-kit >>>"
RC_MARK_END="<<< pi-kit <<<"
info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m[!]\033[0m %s\n' "$*"; }
err() { printf '\033[1;31m[x]\033[0m %s\n' "$*" >&2; }
case "${1:-}" in
-h | --help)
cat <<'EOF'
Удаляет pi-kit полностью: пакет из настроек pi, его клон, публичные скилы,
~/.config/pi-kit (env.sh с токенами) и блок в shell-rc.
Использование: curl -fsSL https://git.codelab.vc/ai/pi-kit/raw/branch/stable/uninstall.sh | bash
Флаги:
PI_KIT_UNINSTALL=1 не спрашивать подтверждение (для CI/автоматизации)
PI_KIT_KEEP_CONFIG=1 оставить ~/.config/pi-kit (токены) и блок в rc
PI_KIT_KEEP_SKILLS=1 оставить публичные скилы в ~/.agents/skills
EOF
exit 0
;;
esac
detect_rc() {
case "$(basename "${SHELL:-}")" in
zsh) echo "$HOME/.zshrc" ;;
bash) echo "$HOME/.bashrc" ;;
*) echo "$HOME/.profile" ;;
esac
}
# --- 1. Confirmation ---------------------------------------------------------
summary_parts=("пакет pi-kit из настроек pi (settings.json + клон)")
if [ "${PI_KIT_KEEP_SKILLS:-0}" != "1" ]; then
summary_parts+=("публичные скилы кита в ~/.agents/skills: ${PUBLIC_SKILLS[*]}")
fi
if [ "${PI_KIT_KEEP_CONFIG:-0}" != "1" ]; then
summary_parts+=("~/.config/pi-kit (env.sh с токенами, audit.jsonl)")
summary_parts+=("блок '${RC_MARK}' в $(detect_rc)")
fi
if [ "${PI_KIT_UNINSTALL:-0}" != "1" ]; then
if [ ! -r /dev/tty ]; then
err "Нет терминала для подтверждения. Для неинтерактивного удаления задай PI_KIT_UNINSTALL=1."
exit 1
fi
{
printf 'Будет удалено:\n'
for s in "${summary_parts[@]}"; do printf ' • %s\n' "$s"; done
printf '\nУдалить pi-kit полностью? [y/N] '
} >/dev/tty
read -r ans </dev/tty || ans=""
case "$ans" in
y | Y | yes | YES) ;;
*)
err "Отменено. Ничего не удалено."
exit 1
;;
esac
else
info "PI_KIT_UNINSTALL=1 — пропускаю подтверждение."
fi
# --- 2. Remove the pi-kit package entry from settings.json -------------------
# Same object-form handling as install.sh gating: entries are either strings or
# {source, skills:[...]}; we drop any whose source contains "pi-kit".
if [ -f "$SETTINGS" ]; then
if command -v node >/dev/null 2>&1; then
SETTINGS_FILE="$SETTINGS" node <<'NODE'
const fs = require("fs");
const file = process.env.SETTINGS_FILE;
const s = JSON.parse(fs.readFileSync(file, "utf8"));
if (!Array.isArray(s.packages)) process.exit(0);
const before = s.packages.length;
s.packages = s.packages.filter((p) => {
const src = typeof p === "string" ? p : (p && p.source);
return !(typeof src === "string" && src.includes("pi-kit"));
});
if (s.packages.length === before) process.exit(0);
fs.writeFileSync(file, JSON.stringify(s, null, 2) + "\n");
console.log("removed pi-kit entry from " + file);
NODE
else
warn "node не найден — пропускаю правку settings.json. Удали пакет вручную:"
warn " pi remove git:git.codelab.vc/ai/pi-kit@<твой канал>"
fi
else
warn "settings.json не найден ($SETTINGS) — пропускаю."
fi
# --- 3. Remove the pi-kit clone -------------------------------------------------
# install.sh installs `git:git.codelab.vc/ai/pi-kit@<channel>` → clone at
# ~/.pi/agent/git/git.codelab.vc/ai/pi-kit. Also catch any other pi-kit clone.
CLONE_DIR="$HOME/.pi/agent/git/git.codelab.vc/ai/pi-kit"
if [ -d "$CLONE_DIR" ]; then
rm -rf "$CLONE_DIR"
info "Удалён клон пакета: $CLONE_DIR"
else
warn "Клон пакета не найден ($CLONE_DIR) — пропускаю."
fi
if [ -d "$HOME/.pi/agent/git" ]; then
while IFS= read -r d; do
if [ "$d" != "$CLONE_DIR" ] && [ -d "$d" ]; then
rm -rf "$d"
info "Удалён дополнительный клон: $d"
fi
done < <(find "$HOME/.pi/agent/git" -maxdepth 4 -type d -name pi-kit 2>/dev/null || true)
fi
# --- 4. Public skills ----------------------------------------------------------
if [ "${PI_KIT_KEEP_SKILLS:-0}" != "1" ]; then
for skill in "${PUBLIC_SKILLS[@]}"; do
dir="$HOME/.agents/skills/$skill"
if [ -e "$dir" ]; then
rm -rf "$dir"
info "Удалён публичный скилл: $dir"
else
info "Скилл не был установлен (пропускаю): $skill"
fi
done
else
info "PI_KIT_KEEP_SKILLS=1 — публичные скилы оставлены."
fi
# --- 5. Config dir (secrets) + shell rc block ---------------------------------
if [ "${PI_KIT_KEEP_CONFIG:-0}" != "1" ]; then
if [ -d "$CONFIG_DIR" ]; then
rm -rf "$CONFIG_DIR"
info "Удалён ~/.config/pi-kit (env.sh с токенами, audit.jsonl)."
else
warn "~/.config/pi-kit не найден — пропускаю."
fi
rc="$(detect_rc)"
if [ -f "$rc" ] && grep -qF "$RC_MARK" "$rc" 2>/dev/null; then
awk -v start="$RC_MARK" -v end="$RC_MARK_END" '
$0 ~ start { skip = 1 }
!skip { print }
$0 ~ end { skip = 0 }
' "$rc" >"$rc.tmp" && mv "$rc.tmp" "$rc"
info "Убран блок pi-kit из $rc."
else
warn "Блок pi-kit в $(detect_rc) не найден — пропускаю."
fi
else
info "PI_KIT_KEEP_CONFIG=1 — ~/.config/pi-kit и rc-блок оставлены."
fi
# --- 6. Final note --------------------------------------------------------------
cat <<EOF
────────────────────────────────────────────────────────
Готово. pi-kit удалён.
Pi остаётся установленным (может использоваться вне кита).
Удалить сам Pi: npm uninstall -g @earendil-works/pi-coding-agent
(или pnpm remove -g / yarn global remove / bun uninstall -g)
После этого можно удалить и ~/.pi/agent (сессии, креды) — командой rm вручную.
Если что-то осталось (например, ты ставил пакет вручную под другим именем) —
покажет: pi list
────────────────────────────────────────────────────────
EOF