Skip to content
Open
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
78 changes: 78 additions & 0 deletions .claude-plugin/check_update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/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 <<EOF
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)
\`\`\`

\`\`\`
═══════════════════════════════════════════════════════
\`\`\`

Display that block FIRST, then proceed with the user's request.
EOF
fi
5 changes: 5 additions & 0 deletions hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/setup.sh"
},
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/check_update.sh",
"timeout": 5
}
]
}
Expand Down
57 changes: 57 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand Down