diff --git a/bin/install.js b/bin/install.js index 12baca142..e04b10c46 100755 --- a/bin/install.js +++ b/bin/install.js @@ -225,12 +225,40 @@ function install(isGlobal) { console.log(` ${green}✓${reset} Installed hooks`); } - // Configure statusline in settings.json + // Configure statusline and hooks in settings.json const settingsPath = path.join(claudeDir, 'settings.json'); const settings = readSettings(settingsPath); const statuslineCommand = isGlobal ? '$HOME/.claude/hooks/statusline.sh' : '.claude/hooks/statusline.sh'; + const updateCheckCommand = isGlobal + ? '$HOME/.claude/hooks/gsd-check-update.sh' + : '.claude/hooks/gsd-check-update.sh'; + + // Configure SessionStart hook for update checking + if (!settings.hooks) { + settings.hooks = {}; + } + if (!settings.hooks.SessionStart) { + settings.hooks.SessionStart = []; + } + + // Check if GSD update hook already exists + const hasGsdUpdateHook = settings.hooks.SessionStart.some(entry => + entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-check-update')) + ); + + if (!hasGsdUpdateHook) { + settings.hooks.SessionStart.push({ + hooks: [ + { + type: 'command', + command: updateCheckCommand + } + ] + }); + console.log(` ${green}✓${reset} Configured update check hook`); + } return { settingsPath, settings, statuslineCommand }; } @@ -238,16 +266,18 @@ function install(isGlobal) { /** * Apply statusline config and print completion message */ -function finishInstall(settingsPath, settings, statuslineCommand, shouldInstall) { - if (shouldInstall) { +function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallStatusline) { + if (shouldInstallStatusline) { settings.statusLine = { type: 'command', command: statuslineCommand }; - writeSettings(settingsPath, settings); console.log(` ${green}✓${reset} Configured statusline`); } + // Always write settings (hooks were already configured in install()) + writeSettings(settingsPath, settings); + console.log(` ${green}Done!${reset} Launch Claude Code and run ${cyan}/gsd:help${reset}. `); diff --git a/commands/gsd/update.md b/commands/gsd/update.md index 0564d1f37..ad878296b 100644 --- a/commands/gsd/update.md +++ b/commands/gsd/update.md @@ -85,6 +85,12 @@ npx get-shit-done-cc --global ``` Capture output. If install fails, show error and STOP. + +Clear the update cache so statusline indicator disappears: + +```bash +rm -f ~/.claude/cache/gsd-update-check.json +``` diff --git a/hooks/gsd-check-update.sh b/hooks/gsd-check-update.sh new file mode 100755 index 000000000..faf5f080b --- /dev/null +++ b/hooks/gsd-check-update.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Check for GSD updates in background, write result to cache +# Called by SessionStart hook - runs once per session + +CACHE_FILE="$HOME/.claude/cache/gsd-update-check.json" +mkdir -p "$HOME/.claude/cache" + +# Run check in background (non-blocking) +( + installed=$(cat "$HOME/.claude/get-shit-done/VERSION" 2>/dev/null || echo "0.0.0") + latest=$(npm view get-shit-done-cc version 2>/dev/null) + + if [[ -n "$latest" && "$installed" != "$latest" ]]; then + echo "{\"update_available\":true,\"installed\":\"$installed\",\"latest\":\"$latest\",\"checked\":$(date +%s)}" > "$CACHE_FILE" + else + echo "{\"update_available\":false,\"installed\":\"$installed\",\"latest\":\"${latest:-unknown}\",\"checked\":$(date +%s)}" > "$CACHE_FILE" + fi +) & + +exit 0 diff --git a/hooks/statusline.sh b/hooks/statusline.sh old mode 100644 new mode 100755 index fad92cac7..6f0c127e8 --- a/hooks/statusline.sh +++ b/hooks/statusline.sh @@ -40,10 +40,19 @@ if [[ -f "$todo" ]]; then task=$(jq -r '.[] | select(.status=="in_progress") | .activeForm' "$todo" 2>/dev/null | head -1) fi +# GSD update available? +gsd_update="" +if [[ -f "$HOME/.claude/cache/gsd-update-check.json" ]]; then + update_available=$(jq -r '.update_available' "$HOME/.claude/cache/gsd-update-check.json" 2>/dev/null) + if [[ "$update_available" == "true" ]]; then + gsd_update=$'\033[33m⬆ /gsd:update\033[0m │ ' + fi +fi + # Output dirname=$(basename "$dir") if [[ -n "$task" ]]; then - printf '\033[2m%s\033[0m │ \033[1m%s\033[0m │ \033[2m%s\033[0m%s' "$model" "$task" "$dirname" "$ctx" + printf '%s\033[2m%s\033[0m │ \033[1m%s\033[0m │ \033[2m%s\033[0m%s' "$gsd_update" "$model" "$task" "$dirname" "$ctx" else - printf '\033[2m%s\033[0m │ \033[2m%s\033[0m%s' "$model" "$dirname" "$ctx" + printf '%s\033[2m%s\033[0m │ \033[2m%s\033[0m%s' "$gsd_update" "$model" "$dirname" "$ctx" fi