plugins/claude/code/scripts/session-history-capture.sh
Snider 930fd1a132
feat(session-history): Enhanced context preservation with session history (#79)
This commit introduces a new session history feature to improve context preservation between sessions. The previous mechanism, which relied on a simple scratchpad file, has been replaced with a more robust system that stores structured session data in `~/.claude/sessions/history.json`.

Key features of this new system include:
- Structured session history: Session data, including the module, branch, and key actions, is stored in a JSON file.
- Auto-capture of file modifications: The `session-history-capture.sh` script, triggered before each tool use, captures file modifications from `git status` and records them as key actions.
- Context restoration on session start: The `session-history-restore.sh` script, triggered at the start of a new session, displays a summary of the most recent session's context.
- Pruning of old sessions: Sessions older than seven days are automatically pruned from the history.

Limitation:
This implementation does not include the auto-extraction of pending tasks and decisions from the conversation history, as was originally requested. An investigation revealed that it is not currently possible for a hook script to access the conversation history, which is a prerequisite for this feature. The groundwork for this functionality has been laid in the JSON structure, and it can be implemented in the future if the platform's capabilities are extended to allow access to the conversation history.
2026-02-02 07:27:13 +00:00

97 lines
3.1 KiB
Bash

#!/bin/bash
# capture-session-history.sh
# Captures session context, focusing on git status, and saves it to history.json.
HISTORY_FILE="${HOME}/.claude/sessions/history.json"
SESSION_TIMEOUT=10800 # 3 hours
# Ensure session directory exists
mkdir -p "${HOME}/.claude/sessions"
# Initialize history file if it doesn't exist
if [[ ! -f "$HISTORY_FILE" ]]; then
echo '{"sessions": []}' > "$HISTORY_FILE"
fi
# --- Get Session Identifiers ---
MODULE=$(basename "$(pwd)")
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
NOW=$(date '+%s')
# --- Read and Find Current Session ---
HISTORY_CONTENT=$(cat "$HISTORY_FILE")
SESSION_INDEX=$(echo "$HISTORY_CONTENT" | jq \
--arg module "$MODULE" \
--arg branch "$BRANCH" \
--argjson now "$NOW" \
--argjson timeout "$SESSION_TIMEOUT" '
.sessions | to_entries |
map(select(.value.module == $module and .value.branch == $branch and ($now - .value.last_updated < $timeout))) |
.[-1].key
')
# --- Extract Key Actions from Git ---
# Get list of modified/new files. `git status --short` gives entries like " M path/file.txt".
# We'll format them into more readable strings.
ACTIONS_LIST=()
while read -r line; do
status=$(echo "$line" | cut -c 1-2)
path=$(echo "$line" | cut -c 4-)
action=""
case "$status" in
" M") action="Modified: $path" ;;
"A ") action="Added: $path" ;;
"D ") action="Deleted: $path" ;;
"R ") action="Renamed: $path" ;;
"C ") action="Copied: $path" ;;
"??") action="Untracked: $path" ;;
esac
if [[ -n "$action" ]]; then
ACTIONS_LIST+=("$action")
fi
done < <(git status --short)
KEY_ACTIONS_JSON=$(printf '%s\n' "${ACTIONS_LIST[@]}" | jq -R . | jq -s .)
# --- Update or Create Session ---
if [[ "$SESSION_INDEX" != "null" ]]; then
# Update existing session
UPDATED_HISTORY=$(echo "$HISTORY_CONTENT" | jq \
--argjson index "$SESSION_INDEX" \
--argjson ts "$NOW" \
--argjson actions "$KEY_ACTIONS_JSON" '
.sessions[$index].last_updated = $ts |
.sessions[$index].key_actions = $actions
# Note: pending_tasks and decisions would be updated here from conversation
'
)
else
# Create new session
SESSION_ID="session_$(date '+%Y%m%d%H%M%S')_$$"
NEW_SESSION=$(jq -n \
--arg id "$SESSION_ID" \
--argjson ts "$NOW" \
--arg module "$MODULE" \
--arg branch "$BRANCH" \
--argjson actions "$KEY_ACTIONS_JSON" '
{
"id": $id,
"started": $ts,
"last_updated": $ts,
"module": $module,
"branch": $branch,
"key_actions": $actions,
"pending_tasks": [],
"decisions": []
}'
)
UPDATED_HISTORY=$(echo "$HISTORY_CONTENT" | jq --argjson new_session "$NEW_SESSION" '.sessions += [$new_session]')
fi
# Write back to file
# Use a temp file for atomic write
TMP_FILE="${HISTORY_FILE}.tmp"
echo "$UPDATED_HISTORY" > "$TMP_FILE" && mv "$TMP_FILE" "$HISTORY_FILE"
# This script does not produce output, it works in the background.
exit 0