From 68ecc4dbb5b1f5683a2ceeafef39b5fb55e1be0b Mon Sep 17 00:00:00 2001 From: calreynolds Date: Thu, 5 Mar 2026 14:21:02 -0500 Subject: [PATCH 1/3] Add version upgrade notification via SessionStart hook Users don't know when a newer version of ai-dev-kit is available. This adds a lightweight check that runs at Claude Code session start and notifies the user if an update exists. How it works: - check_update.sh compares local version against GitHub latest - Results cached for 24h to avoid repeated network requests - Silent on any failure (offline, timeout, missing files) - Hook stdout is injected as context Claude sees and relays Supports multiple install paths: - Plugin mode (CLAUDE_PLUGIN_ROOT/VERSION) - Project-scoped install (.ai-dev-kit/version) - Global install (~/.ai-dev-kit/version) Co-Authored-By: Claude Opus 4.6 --- .claude-plugin/check_update.sh | 72 ++++++++++++++++++++++++++++++++++ hooks/hooks.json | 5 +++ 2 files changed, 77 insertions(+) create mode 100755 .claude-plugin/check_update.sh diff --git a/.claude-plugin/check_update.sh b/.claude-plugin/check_update.sh new file mode 100755 index 00000000..85530c8a --- /dev/null +++ b/.claude-plugin/check_update.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Version update check for Databricks AI Dev Kit. +# Stdout from this script is injected as context Claude can see at session start. +# Silent on success (up to date) or failure (network error, missing files). + +# Find the installed version. Check multiple locations: +# 1. Plugin mode: VERSION at plugin root +# 2. Project-scoped install: .ai-dev-kit/version in project dir +# 3. Global install: ~/.ai-dev-kit/version +# 4. Fallback: script-relative +VERSION_FILE="" +for candidate in \ + "${CLAUDE_PLUGIN_ROOT:+$CLAUDE_PLUGIN_ROOT/VERSION}" \ + "${CLAUDE_PROJECT_DIR:+$CLAUDE_PROJECT_DIR/.ai-dev-kit/version}" \ + "$HOME/.ai-dev-kit/version" \ + "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/VERSION"; do + [ -n "$candidate" ] && [ -f "$candidate" ] && VERSION_FILE="$candidate" && break +done +CACHE_FILE="$HOME/.ai-dev-kit/.update-check" +REMOTE_URL="https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/VERSION" +CACHE_TTL=86400 # 24 hours + +[ ! -f "$VERSION_FILE" ] && exit 0 +local_ver=$(cat "$VERSION_FILE" 2>/dev/null) +[ -z "$local_ver" ] && exit 0 + +remote_ver="" + +# Check cache +if [ -f "$CACHE_FILE" ]; then + cached_ts=$(grep '^TIMESTAMP=' "$CACHE_FILE" 2>/dev/null | cut -d= -f2) + cached_ver=$(grep '^REMOTE_VERSION=' "$CACHE_FILE" 2>/dev/null | cut -d= -f2) + now=$(date +%s) + if [ -n "$cached_ts" ] && [ -n "$cached_ver" ] && [ $((now - cached_ts)) -lt $CACHE_TTL ]; then + remote_ver="$cached_ver" + fi +fi + +# Fetch if cache is stale +if [ -z "$remote_ver" ]; then + remote_ver=$(curl -fsSL --connect-timeout 3 --max-time 3 "$REMOTE_URL" 2>/dev/null || echo "") + if [ -n "$remote_ver" ] && [[ ! "$remote_ver" =~ (404|Not\ Found|error) ]]; then + mkdir -p "$HOME/.ai-dev-kit" + printf 'TIMESTAMP=%s\nREMOTE_VERSION=%s\n' "$(date +%s)" "$remote_ver" > "$CACHE_FILE" + else + exit 0 + fi +fi + +# If versions differ, output a message for Claude to relay to the user +if [ -n "$remote_ver" ] && [ "$remote_ver" != "$local_ver" ]; then + cat < Date: Thu, 5 Mar 2026 14:28:21 -0500 Subject: [PATCH 2/3] Add install.sh support for version check hook Wire the check_update.sh hook into .claude/settings.json during install so that install.sh users (not just plugin users) get the version notification at session start. Uses Python JSON merge when possible to safely add the hook to existing settings without overwriting other config. Falls back to writing a new file if settings.json doesn't exist yet. Co-Authored-By: Claude Opus 4.6 --- install.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/install.sh b/install.sh index 7ed46779..fc64acc1 100755 --- a/install.sh +++ b/install.sh @@ -886,6 +886,55 @@ GEMINIEOF ok "GEMINI.md" } +write_claude_hook() { + local path=$1 + local script=$2 + mkdir -p "$(dirname "$path")" + + # Merge into existing settings.json if present, using Python for safe JSON handling + if [ -f "$path" ] && [ -f "$VENV_PYTHON" ]; then + "$VENV_PYTHON" -c " +import json +path = '$path' +script = '$script' +hook_entry = {'type': 'command', 'command': 'bash ' + script, 'timeout': 5} +try: + with open(path) as f: cfg = json.load(f) +except: cfg = {} +hooks = cfg.setdefault('hooks', {}) +session_hooks = hooks.setdefault('SessionStart', []) +# Check if hook already exists +for group in session_hooks: + for h in group.get('hooks', []): + if 'check_update.sh' in h.get('command', ''): + exit(0) # Already configured +# Append new hook group +session_hooks.append({'hooks': [hook_entry]}) +with open(path, 'w') as f: json.dump(cfg, f, indent=2); f.write('\n') +" 2>/dev/null && return + fi + + # Fallback: write new file (only if no existing file) + [ -f "$path" ] && return # Don't overwrite existing settings without Python + cat > "$path" << EOF +{ + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "bash $script", + "timeout": 5 + } + ] + } + ] + } +} +EOF +} + write_mcp_configs() { step "Configuring MCP" @@ -895,6 +944,14 @@ write_mcp_configs() { claude) [ "$SCOPE" = "global" ] && write_mcp_json "$HOME/.claude/mcp.json" || write_mcp_json "$base_dir/.mcp.json" ok "Claude MCP config" + # Add version check hook to Claude settings + local check_script="$REPO_DIR/.claude-plugin/check_update.sh" + if [ "$SCOPE" = "global" ]; then + write_claude_hook "$HOME/.claude/settings.json" "$check_script" + else + write_claude_hook "$base_dir/.claude/settings.json" "$check_script" + fi + ok "Claude update check hook" ;; cursor) if [ "$SCOPE" = "global" ]; then From dc329853b5a403cfb83ca96396b3d94e5141894d Mon Sep 17 00:00:00 2001 From: calreynolds Date: Thu, 5 Mar 2026 14:38:45 -0500 Subject: [PATCH 3/3] Improve upgrade notification: make install command easily copy-pasteable Move the install command out of the ASCII box into its own code block on a single line so users can select and copy it cleanly. Co-Authored-By: Claude Opus 4.6 --- .claude-plugin/check_update.sh | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/.claude-plugin/check_update.sh b/.claude-plugin/check_update.sh index 85530c8a..e7a744c1 100755 --- a/.claude-plugin/check_update.sh +++ b/.claude-plugin/check_update.sh @@ -53,18 +53,24 @@ if [ -n "$remote_ver" ] && [ "$remote_ver" != "$local_ver" ]; then URGENT — before doing ANYTHING else, you MUST display this exact block to the user: \`\`\` -╔══════════════════════════════════════════════════════════════╗ -║ ║ -║ Databricks AI Dev Kit — update available! ║ -║ ║ -║ Installed: v${local_ver} ║ -║ Available: v${remote_ver} ║ -║ ║ -║ To upgrade, run: ║ -║ bash <(curl -sL https://raw.githubusercontent.com/ ║ -║ databricks-solutions/ai-dev-kit/main/install.sh) ║ -║ ║ -╚══════════════════════════════════════════════════════════════╝ +╔═══════════════════════════════════════════════════════╗ +║ ║ +║ Databricks AI Dev Kit — update available! ║ +║ ║ +║ Installed: v${local_ver} ║ +║ Available: v${remote_ver} ║ +║ ║ +╚═══════════════════════════════════════════════════════╝ +\`\`\` + +To upgrade, run: + +\`\`\` +bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) +\`\`\` + +\`\`\` +═══════════════════════════════════════════════════════ \`\`\` Display that block FIRST, then proceed with the user's request.