diff --git a/setup.sh b/setup.sh index ba8db1e..593eb76 100755 --- a/setup.sh +++ b/setup.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Install Domna's curated skill set into the current repo. +# Install Domna's curated skill set globally (~/.claude). # # Run from the root of the target repo: # curl -fsSL https://raw.githubusercontent.com/Hestia-Homes/agentic-toolkit/main/setup.sh | bash @@ -8,78 +8,93 @@ # bash /path/to/agentic-toolkit/setup.sh # # What this does: -# 1. Drops the pinned skills-lock.json from agentic-toolkit into the target repo. -# 2. Runs `skills experimental_install` to restore the exact pinned versions -# of Matt Pocock's skills + Domna's own skills (Hestia-Homes/agentic-toolkit). +# 1. Copies the pinned skills-lock.json from agentic-toolkit to ~/.claude. +# 2. Parses it and runs `skills add --global` per source so all skills land +# in ~/.claude/skills (user-level, available in every repo). # -# To upgrade skills across all Domna repos: -# - In agentic-toolkit, re-install the skills you want, then commit the -# resulting skills-lock.json (this script reads from that file). -# - Devs re-run setup.sh in their target repos. +# Note: `skills experimental_install` would be the natural fit but it only +# restores at project scope — confirmed empirically that running it against +# a global lock prints "No project skills found" and exits 0, installing +# nothing. So we drive `skills add --global` from the lock instead. +# +# Logs verbose output to $HOME/.claude/agentic-toolkit-setup.log so failures +# under postCreateCommand or `| bash` are inspectable after the fact. # set -euo pipefail +# --- logging ------------------------------------------------------------------- +CLAUDE_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}" +mkdir -p "$CLAUDE_DIR" +LOG_FILE="$CLAUDE_DIR/agentic-toolkit-setup.log" +# Tee everything (stdout + stderr) to the log so silent failures aren't silent. +exec > >(tee -a "$LOG_FILE") 2>&1 +echo "=== agentic-toolkit setup.sh @ $(date -u +%FT%TZ) ===" + +# Trap so a failure under set -e prints the failing line into the log. +trap 'rc=$?; echo "ERROR: setup.sh exited $rc at line $LINENO" >&2; exit $rc' ERR + # --- config -------------------------------------------------------------------- LOCK_URL="https://raw.githubusercontent.com/Hestia-Homes/agentic-toolkit/main/skills-lock.json" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd || true)" LOCAL_LOCK="${SCRIPT_DIR:+$SCRIPT_DIR/skills-lock.json}" +AGENT_TARGET="claude-code" +DEST_LOCK="$CLAUDE_DIR/skills-lock.json" # --- guards -------------------------------------------------------------------- if ! command -v npx >/dev/null 2>&1; then echo "error: npx is required (install Node.js >= 20)." >&2 exit 1 fi -if [[ ! -d .git ]]; then - echo "error: run this script from the root of a git repository." >&2 +if ! command -v node >/dev/null 2>&1; then + echo "error: node is required to parse skills-lock.json." >&2 exit 1 fi -# --- stage skills-lock.json ---------------------------------------------------- -LOCK_FILE="$(mktemp -t skills-lock.XXXXXX.json)" -trap 'rm -f "$LOCK_FILE"' EXIT - +# --- stage skills-lock.json into ~/.claude ------------------------------------ if [[ -n "$LOCAL_LOCK" && -f "$LOCAL_LOCK" ]]; then - echo "==> Using local skills-lock.json from $LOCAL_LOCK" - cp "$LOCAL_LOCK" "$LOCK_FILE" + echo "==> Copying local skills-lock.json -> $DEST_LOCK" + cp "$LOCAL_LOCK" "$DEST_LOCK" else - echo "==> Fetching skills-lock.json from $LOCK_URL" + echo "==> Fetching skills-lock.json -> $DEST_LOCK" if command -v curl >/dev/null 2>&1; then - curl -fsSL "$LOCK_URL" -o "$LOCK_FILE" + curl -fsSL "$LOCK_URL" -o "$DEST_LOCK" elif command -v wget >/dev/null 2>&1; then - wget -qO "$LOCK_FILE" "$LOCK_URL" + wget -qO "$DEST_LOCK" "$LOCK_URL" else echo "error: need curl or wget to fetch skills-lock.json." >&2 exit 1 fi fi -AGENT_TARGET="claude-code" +# --- parse lock: write "sourceskill1,skill2,..." to a tempfile ----------- +GROUPS_FILE="$(mktemp -t skills-groups.XXXXXX)" +trap 'rm -f "$GROUPS_FILE"' EXIT -# --- install (globally, grouped by source) ------------------------------------- -# `skills experimental_install` only restores at project scope. Domna installs -# globally (~/.claude), so we parse the lock and call `skills add` per source -# with the explicit skill list from the lock file. -echo "==> Installing skills globally (~/.claude) from skills-lock.json" - -# Group skills by source -> "sourceskill1,skill2,..." -GROUPS="$(node -e ' - const lock = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); +node --input-type=module -e " + import fs from 'node:fs'; + const lock = JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); const bySource = new Map(); for (const [name, entry] of Object.entries(lock.skills || {})) { - if (!entry.source) continue; + if (!entry || !entry.source) continue; if (!bySource.has(entry.source)) bySource.set(entry.source, []); bySource.get(entry.source).push(name); } - for (const [src, names] of bySource) { - process.stdout.write(src + "\t" + names.join(",") + "\n"); - } -' "$LOCK_FILE")" + const out = [...bySource.entries()] + .map(([src, names]) => src + '\t' + names.join(',')) + .join('\n'); + fs.writeFileSync(process.argv[2], out + (out ? '\n' : '')); +" "$DEST_LOCK" "$GROUPS_FILE" -if [[ -z "$GROUPS" ]]; then - echo "error: no skills found in lock file." >&2 +if [[ ! -s "$GROUPS_FILE" ]]; then + echo "error: no skills found in $DEST_LOCK." >&2 exit 1 fi +echo "==> Skill groups parsed from lock:" +cat "$GROUPS_FILE" + +# --- install (globally, grouped by source) ------------------------------------- +echo "==> Installing skills globally (~/.claude)" while IFS=$'\t' read -r SOURCE SKILLS; do [[ -z "$SOURCE" ]] && continue echo "==> $SOURCE :: $SKILLS" @@ -89,14 +104,12 @@ while IFS=$'\t' read -r SOURCE SKILLS; do --copy \ --global \ --yes -done <<< "$GROUPS" +done < "$GROUPS_FILE" -# --- post-install reminder ----------------------------------------------------- +echo "==> Done. Log: $LOG_FILE" cat <<'EOF' -==> Done. Next steps: - - 1. Run /setup-matt-pocock-skills (one-time per repo) to record the issue - tracker, triage labels, and domain-doc layout. - +Next step: + Run /setup-matt-pocock-skills once per repo to record the issue tracker, + triage labels, and domain-doc layout. EOF