#!/bin/bash # # Claude Code Hook: user-prompt-submit # Runs BEFORE each user message is processed # Injects relevant context from the database into the conversation # # Expected environment variables: # CLAUDE_PROJECT_ID - UUID of the current project # JWT_TOKEN - Authentication token for API # CLAUDE_API_URL - API base URL (default: http://localhost:8000) # CONTEXT_RECALL_ENABLED - Set to "false" to disable (default: true) # MIN_RELEVANCE_SCORE - Minimum score for context (default: 5.0) # MAX_CONTEXTS - Maximum number of contexts to retrieve (default: 10) # # Load configuration if exists CONFIG_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/context-recall-config.env" if [ -f "$CONFIG_FILE" ]; then source "$CONFIG_FILE" fi # Default values API_URL="${CLAUDE_API_URL:-http://localhost:8000}" ENABLED="${CONTEXT_RECALL_ENABLED:-true}" MIN_SCORE="${MIN_RELEVANCE_SCORE:-5.0}" MAX_ITEMS="${MAX_CONTEXTS:-10}" # Exit early if disabled if [ "$ENABLED" != "true" ]; then exit 0 fi # Detect project ID from git repo if not set if [ -z "$CLAUDE_PROJECT_ID" ]; then # Try to get from git config PROJECT_ID=$(git config --local claude.projectid 2>/dev/null) if [ -z "$PROJECT_ID" ]; then # Try to derive from git remote URL GIT_REMOTE=$(git config --get remote.origin.url 2>/dev/null) if [ -n "$GIT_REMOTE" ]; then # Hash the remote URL to create a consistent ID PROJECT_ID=$(echo -n "$GIT_REMOTE" | md5sum | cut -d' ' -f1) fi fi else PROJECT_ID="$CLAUDE_PROJECT_ID" fi # Exit if no project ID available if [ -z "$PROJECT_ID" ]; then # Silent exit - no context available exit 0 fi # Exit if no JWT token if [ -z "$JWT_TOKEN" ]; then exit 0 fi # Build API request URL RECALL_URL="${API_URL}/api/conversation-contexts/recall" QUERY_PARAMS="project_id=${PROJECT_ID}&limit=${MAX_ITEMS}&min_relevance_score=${MIN_SCORE}" # Fetch context from API (with timeout and error handling) CONTEXT_RESPONSE=$(curl -s --max-time 3 \ "${RECALL_URL}?${QUERY_PARAMS}" \ -H "Authorization: Bearer ${JWT_TOKEN}" \ -H "Accept: application/json" 2>/dev/null) # Check if request was successful if [ $? -ne 0 ] || [ -z "$CONTEXT_RESPONSE" ]; then # Silent failure - API unavailable exit 0 fi # Parse and format context (expects JSON array of context objects) # Example response: [{"title": "...", "dense_summary": "...", "relevance_score": 8.5}, ...] CONTEXT_COUNT=$(echo "$CONTEXT_RESPONSE" | grep -o '"id"' | wc -l) if [ "$CONTEXT_COUNT" -gt 0 ]; then echo "" echo "" echo "## 📚 Previous Context" echo "" echo "The following context has been automatically recalled from previous sessions:" echo "" # Extract and format each context entry # Note: This uses simple text parsing. For production, consider using jq if available. echo "$CONTEXT_RESPONSE" | python3 -c " import sys, json try: contexts = json.load(sys.stdin) if isinstance(contexts, list): for i, ctx in enumerate(contexts, 1): title = ctx.get('title', 'Untitled') summary = ctx.get('dense_summary', '') score = ctx.get('relevance_score', 0) ctx_type = ctx.get('context_type', 'unknown') print(f'### {i}. {title} (Score: {score}/10)') print(f'*Type: {ctx_type}*') print() print(summary) print() print('---') print() except: pass " 2>/dev/null echo "" echo "*This context was automatically injected to help maintain continuity across sessions.*" echo "" fi # Exit successfully exit 0