update-all.sh 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #!/usr/bin/env bash
  2. # ============================================================
  3. # Claude Code — Update all components
  4. # Pulls latest config, updates submodules, refreshes symlinks,
  5. # and runs doctor to verify.
  6. # ============================================================
  7. set -euo pipefail
  8. GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
  9. ok() { echo -e "${GREEN}✓${NC} $1"; }
  10. warn() { echo -e "${YELLOW}⚠${NC} $1"; }
  11. info() { echo -e "${BLUE}→${NC} $1"; }
  12. REPO="$(cd "$(dirname "$0")" && pwd)"
  13. VERSION=$(cat "$REPO/version.txt" 2>/dev/null || echo "unknown")
  14. # Load shared detection library
  15. # shellcheck source=lib/detect-plugins.sh
  16. source "$REPO/lib/detect-plugins.sh"
  17. echo ""
  18. echo "═══ claude-config update (v${VERSION}) ═══"
  19. echo ""
  20. # ── 0. Update Claude Code CLI ──
  21. echo "── Updating Claude Code CLI..."
  22. if command -v claude &>/dev/null; then
  23. CURRENT_VER=$(claude --version 2>/dev/null | head -1 || echo "unknown")
  24. info "Current: $CURRENT_VER"
  25. if npm install -g @anthropic-ai/claude-code@latest 2>/dev/null; then
  26. NEW_VER=$(claude --version 2>/dev/null | head -1 || echo "unknown")
  27. if [ "$CURRENT_VER" = "$NEW_VER" ]; then
  28. ok "Claude Code already up to date ($NEW_VER)"
  29. else
  30. ok "Claude Code updated: $CURRENT_VER → $NEW_VER"
  31. fi
  32. else
  33. warn "Claude Code update failed — try manually: npm install -g @anthropic-ai/claude-code@latest"
  34. fi
  35. else
  36. warn "Claude Code not found — install first with: make install"
  37. fi
  38. echo ""
  39. # ── 1. Pull latest config ──
  40. echo "── Pulling latest config..."
  41. cd "$REPO"
  42. if git pull --rebase 2>/dev/null; then
  43. ok "Config repo updated"
  44. else
  45. warn "git pull failed — check for uncommitted changes"
  46. fi
  47. # ── 2. Update GStack submodule ──
  48. echo ""
  49. echo "── Updating GStack submodule..."
  50. warn "GStack tracks branch = main (no commit hash). Review upstream commits before updating."
  51. echo ""
  52. printf " Proceed with GStack update? [y/N] "
  53. read -r _gstack_confirm
  54. if [[ "$_gstack_confirm" =~ ^[Yy]$ ]]; then
  55. if git submodule update --remote skills-external/gstack 2>/dev/null; then
  56. if [ -d "skills-external/gstack" ]; then
  57. if [ -x "skills-external/gstack/setup" ]; then
  58. if (cd skills-external/gstack && ./setup) 2>/dev/null; then
  59. ok "GStack updated"
  60. else
  61. warn "GStack ./setup failed — submodule updated but setup did not complete"
  62. fi
  63. else
  64. warn "GStack ./setup not found or not executable — skipping"
  65. ok "GStack submodule pointer updated"
  66. fi
  67. fi
  68. else
  69. warn "GStack submodule update failed — run: git submodule update --init"
  70. fi
  71. else
  72. info "GStack update skipped"
  73. fi
  74. # ── 3. Update RTK (if pinned version available) ──
  75. echo ""
  76. echo "── Updating RTK..."
  77. if command -v cargo &>/dev/null; then
  78. RTK_VERSION=""
  79. if [ -f "$REPO/plugins.lock.json" ] && command -v python3 &>/dev/null; then
  80. RTK_VERSION=$(python3 -c "
  81. import json
  82. with open('$REPO/plugins.lock.json') as f:
  83. d = json.load(f)
  84. print(d.get('rtk',{}).get('version',''))
  85. " 2>/dev/null || true)
  86. fi
  87. if [ -n "$RTK_VERSION" ] && [ "$RTK_VERSION" != "latest" ]; then
  88. info "Pinned version: $RTK_VERSION"
  89. info "Compiling from source — this may take a few minutes..."
  90. if cargo install --git https://github.com/rtk-ai/rtk --tag "$RTK_VERSION" --force; then
  91. ok "RTK updated to $RTK_VERSION"
  92. else
  93. warn "RTK update failed"
  94. fi
  95. else
  96. info "No pinned version — installing latest"
  97. info "Compiling from source — this may take a few minutes..."
  98. if cargo install --git https://github.com/rtk-ai/rtk --force; then
  99. ok "RTK updated (latest)"
  100. else
  101. warn "RTK update failed"
  102. fi
  103. fi
  104. else
  105. warn "Cargo not available — skipping RTK"
  106. fi
  107. # ── 4. Update GSD v2 ──
  108. echo ""
  109. echo "── Updating GSD v2 (gsd-pi)..."
  110. if command -v gsd &>/dev/null; then
  111. GSD_VER=""
  112. if [ -f "$REPO/plugins.lock.json" ] && command -v python3 &>/dev/null; then
  113. GSD_VER=$(python3 -c "
  114. import json
  115. with open('$REPO/plugins.lock.json') as f:
  116. d = json.load(f)
  117. print(d.get('gsd',{}).get('version',''))
  118. " 2>/dev/null || true)
  119. fi
  120. if [ -n "$GSD_VER" ] && [ "$GSD_VER" != "latest" ]; then
  121. info "Pinned version: $GSD_VER"
  122. if npm install -g "gsd-pi@${GSD_VER}" 2>/dev/null; then
  123. ok "GSD v2 updated to $GSD_VER"
  124. else
  125. warn "GSD v2 update failed"
  126. fi
  127. else
  128. info "No pinned version — installing latest"
  129. if npm install -g gsd-pi 2>/dev/null; then
  130. ok "GSD v2 updated (latest)"
  131. else
  132. warn "GSD v2 update failed"
  133. fi
  134. fi
  135. else
  136. warn "GSD v2 not installed — skipping (run: npm install -g gsd-pi)"
  137. fi
  138. # ── 5. Update Context7 CLI ──
  139. echo ""
  140. echo "── Updating Context7 CLI..."
  141. if command -v ctx7 &>/dev/null; then
  142. CTX7_VER=""
  143. if [ -f "$REPO/plugins.lock.json" ] && command -v python3 &>/dev/null; then
  144. CTX7_VER=$(python3 -c "
  145. import json
  146. with open('$REPO/plugins.lock.json') as f:
  147. d = json.load(f)
  148. print(d.get('ctx7',{}).get('version',''))
  149. " 2>/dev/null || true)
  150. fi
  151. if [ -n "$CTX7_VER" ] && [ "$CTX7_VER" != "latest" ]; then
  152. info "Pinned version: $CTX7_VER"
  153. if npm install -g "ctx7@${CTX7_VER}" 2>/dev/null; then
  154. ok "ctx7 updated to $CTX7_VER"
  155. else
  156. warn "ctx7 update failed"
  157. fi
  158. else
  159. if npm install -g ctx7@latest 2>/dev/null; then
  160. ok "ctx7 updated (latest)"
  161. else
  162. warn "ctx7 update failed"
  163. fi
  164. fi
  165. else
  166. info "ctx7 not installed — skipping"
  167. fi
  168. # ── 6. Update Graphifyy ──
  169. echo ""
  170. echo "── Updating Graphifyy..."
  171. if command -v graphify &>/dev/null; then
  172. if pipx upgrade graphifyy 2>/dev/null; then
  173. ok "graphifyy updated"
  174. else
  175. warn "graphifyy update failed — try: pipx upgrade graphifyy"
  176. fi
  177. else
  178. info "graphifyy not installed — skipping"
  179. fi
  180. # ── 7. Update Emil Design Engineering skill ──
  181. echo ""
  182. echo "── Updating Emil Design Engineering..."
  183. EMIL_DIR="$REPO/skills-external/emil-design-eng"
  184. EMIL_URL="https://raw.githubusercontent.com/emilkowalski/skill/main/skills/emil-design-eng/SKILL.md"
  185. if [ -d "$EMIL_DIR" ]; then
  186. info "Fetching latest SKILL.md from emilkowalski/skill..."
  187. if curl -fsSL "$EMIL_URL" -o "$EMIL_DIR/SKILL.md.tmp" \
  188. && mv "$EMIL_DIR/SKILL.md.tmp" "$EMIL_DIR/SKILL.md"; then
  189. ok "emil-design-eng updated"
  190. else
  191. warn "emil-design-eng update failed"
  192. fi
  193. else
  194. info "emil-design-eng not installed — skipping (run: make plugin)"
  195. fi
  196. # ── 8. Update marketplace plugins ──
  197. echo ""
  198. echo "── Updating marketplace plugins..."
  199. if command -v claude &>/dev/null; then
  200. _plugins=$(claude plugin list 2>/dev/null \
  201. | grep -oP '(?<=❯ )\S+' || true)
  202. if [ -n "$_plugins" ]; then
  203. while IFS= read -r _p; do
  204. _name="${_p%%@*}"
  205. info "Updating $_name..."
  206. if claude plugin update "$_name" 2>/dev/null; then
  207. ok "$_name updated"
  208. else
  209. warn "$_name update failed"
  210. fi
  211. done <<< "$_plugins"
  212. else
  213. info "No marketplace plugins installed — skipping"
  214. fi
  215. else
  216. warn "Claude Code not found — skipping plugin update"
  217. fi
  218. # ── 9. Update shellcheck ──
  219. echo ""
  220. echo "── Updating shellcheck..."
  221. if command -v shellcheck &>/dev/null; then
  222. # Detect OS for package manager update
  223. if [[ "$OSTYPE" == "darwin"* ]]; then
  224. if brew upgrade shellcheck 2>/dev/null; then
  225. ok "shellcheck updated"
  226. else
  227. ok "shellcheck already up to date"
  228. fi
  229. elif command -v apt-get &>/dev/null; then
  230. if sudo apt-get install -y --only-upgrade shellcheck 2>/dev/null; then
  231. ok "shellcheck updated"
  232. else
  233. ok "shellcheck already up to date"
  234. fi
  235. elif command -v dnf &>/dev/null; then
  236. if sudo dnf upgrade -y shellcheck 2>/dev/null; then
  237. ok "shellcheck updated"
  238. else
  239. ok "shellcheck already up to date"
  240. fi
  241. elif command -v pacman &>/dev/null; then
  242. if sudo pacman -S --noconfirm shellcheck 2>/dev/null; then
  243. ok "shellcheck updated"
  244. else
  245. ok "shellcheck already up to date"
  246. fi
  247. else
  248. info "shellcheck installed via binary — update manually"
  249. fi
  250. else
  251. info "shellcheck not installed — skipping (run: make plugin)"
  252. fi
  253. # ── 10. Refresh symlinks ──
  254. echo ""
  255. echo "── Refreshing symlinks..."
  256. bash "$REPO/link.sh"
  257. # ── 11. Run doctor ──
  258. echo ""
  259. bash "$REPO/doctor.sh"