plugins/claude/code/scripts/session-history-restore.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

93 lines
2.8 KiB
Bash

#!/bin/bash
# session-history-restore.sh
# Restores and displays the most recent session context from history.json.
HISTORY_FILE="${HOME}/.claude/sessions/history.json"
PRUNE_AGE_DAYS=7 # Prune sessions older than 7 days
# Ensure the history file exists, otherwise exit silently.
if [[ ! -f "$HISTORY_FILE" ]]; then
exit 0
fi
# --- Prune Old Sessions ---
NOW=$(date '+%s')
PRUNE_TIMESTAMP=$((NOW - PRUNE_AGE_DAYS * 86400))
PRUNED_HISTORY=$(jq --argjson prune_ts "$PRUNE_TIMESTAMP" '
.sessions = (.sessions | map(select(.last_updated >= $prune_ts)))
' "$HISTORY_FILE")
# Atomically write the pruned history back to the file
TMP_FILE="${HISTORY_FILE}.tmp"
echo "$PRUNED_HISTORY" > "$TMP_FILE" && mv "$TMP_FILE" "$HISTORY_FILE"
# --- Read the Most Recent Session ---
# Get the last session from the (potentially pruned) history
LAST_SESSION=$(echo "$PRUNED_HISTORY" | jq '.sessions[-1]')
# If no sessions, exit.
if [[ "$LAST_SESSION" == "null" ]]; then
exit 0
fi
# --- Format and Display Session Context ---
MODULE=$(echo "$LAST_SESSION" | jq -r '.module')
BRANCH=$(echo "$LAST_SESSION" | jq -r '.branch')
LAST_UPDATED=$(echo "$LAST_SESSION" | jq -r '.last_updated')
# Calculate human-readable "last active" time
AGE_SECONDS=$((NOW - LAST_UPDATED))
if (( AGE_SECONDS < 60 )); then
LAST_ACTIVE="less than a minute ago"
elif (( AGE_SECONDS < 3600 )); then
LAST_ACTIVE="$((AGE_SECONDS / 60)) minutes ago"
elif (( AGE_SECONDS < 86400 )); then
LAST_ACTIVE="$((AGE_SECONDS / 3600)) hours ago"
else
LAST_ACTIVE="$((AGE_SECONDS / 86400)) days ago"
fi
# --- Build the Output ---
# Using ANSI escape codes for formatting (bold, colors)
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Header
echo -e "${BLUE}${BOLD}📋 Previous Session Context${NC}" >&2
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" >&2
echo -e "${BOLD}Module:${NC} ${MODULE} (${BRANCH})" >&2
echo -e "${BOLD}Last active:${NC} ${LAST_ACTIVE}" >&2
echo "" >&2
# Key Actions
KEY_ACTIONS=$(echo "$LAST_SESSION" | jq -r '.key_actions[]?')
if [[ -n "$KEY_ACTIONS" ]]; then
echo -e "${BOLD}Key actions:${NC}" >&2
while read -r action; do
echo -e "${action}" >&2
done <<< "$KEY_ACTIONS"
echo "" >&2
fi
# Pending Tasks
PENDING_TASKS=$(echo "$LAST_SESSION" | jq -r '.pending_tasks[]?')
if [[ -n "$PENDING_TASKS" ]]; then
echo -e "${BOLD}Pending tasks:${NC}" >&2
while read -r task; do
echo -e "${task}" >&2
done <<< "$PENDING_TASKS"
echo "" >&2
fi
# Decisions Made
DECISIONS=$(echo "$LAST_SESSION" | jq -r '.decisions[]?')
if [[ -n "$DECISIONS" ]]; then
echo -e "${BOLD}Decisions made:${NC}" >&2
while read -r decision; do
echo -e "${decision}" >&2
done <<< "$DECISIONS"
echo "" >&2
fi
exit 0