#!/bin/bash # 持續學習 - 會話評估器 # 在 Stop 鉤子 (Hook) 執行,從 Claude Code 工作階段中擷取可重用的模式 # # 為什麼選擇 Stop 鉤子而非 UserPromptSubmit: # - Stop 在會話結束時僅執行一次(輕量級) # - UserPromptSubmit 在每則訊息發送時都會執行(重量級,會增加延遲) # # 鉤子配置 (於 ~/claude/settings.json 中): # { # "hooks": { # "Stop": [{ # "matcher": "*", # "hooks": [{ # "type": "command", # "command": "~/claude/skills/continuous-learning/evaluate-session.sh" # }] # }] # } # } # # 偵測模式:error_resolution, debugging_techniques, workarounds, project_specific # 忽略模式:simple_typos, one_time_fixes, external_api_issues # 擷取後的技能儲存於:~/claude/skills/learned/ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CONFIG_FILE="$SCRIPT_DIR/config.json" LEARNED_SKILLS_PATH="${HOME}/.claude/skills/learned" MIN_SESSION_LENGTH=10 # 若配置檔案存在則載入 if [ -f "$CONFIG_FILE" ]; then if ! command -v jq &>/dev/null; then echo "[ContinuousLearning] 需要 jq 來解析 config.json 但尚未安裝,將使用預設值" >&2 else MIN_SESSION_LENGTH=$(jq -r '.min_session_length // 10' "$CONFIG_FILE") LEARNED_SKILLS_PATH=$(jq -r '.learned_skills_path // "~/claude/skills/learned/"' "$CONFIG_FILE" | sed "s|~|$HOME|") fi fi # 確保已學習技能目錄存在 mkdir -p "$LEARNED_SKILLS_PATH" # 從 stdin JSON 獲取對話紀錄路徑 (Claude Code 鉤子輸入) # 為了向下相容,若失敗則回退到環境變數 stdin_data=$(cat) transcript_path=$(echo "$stdin_data" | grep -o '"transcript_path":"[^"]*"' | head -1 | cut -d'"' -f4) if [ -z "$transcript_path" ]; then transcript_path="${CLAUDE_TRANSCRIPT_PATH:-}" fi if [ -z "$transcript_path" ] || [ ! -f "$transcript_path" ]; then exit 0 fi # 計算會話中的訊息數量 message_count=$(grep -c '"type":"user"' "$transcript_path" 2>/dev/null || echo "0") # 跳過過短的會話 if [ "$message_count" -lt "$MIN_SESSION_LENGTH" ]; then echo "[ContinuousLearning] 會話過短(僅有 $message_count 則訊息),跳過評估" >&2 exit 0 fi # 提示 Claude 應針對此會話評估可擷取的模式 echo "[ContinuousLearning] 此會話共有 $message_count 則訊息 - 開始評估可擷取的模式" >&2 echo "[ContinuousLearning] 將已學習技能儲存至:$LEARNED_SKILLS_PATH" >&2