Files
GLM-Tools-Skills-Agents/hooks/community/jat/pre-compact-save-agent.sh
uroma b60638f0a3 Add community skills, agents, system prompts from 22+ sources
Community Skills (32):
- jat: jat-start, jat-verify, jat-complete
- pi-mono: codex-cli, codex-5.3-prompting, interactive-shell
- picoclaw: github, weather, tmux, summarize, skill-creator
- dyad: 18 skills (swarm-to-plan, multi-pr-review, fix-issue, lint, etc.)
- dexter: dcf valuation skill

Agents (23):
- pi-mono subagents: scout, planner, reviewer, worker
- toad: 19 agent configs (Claude, Codex, Gemini, Copilot, OpenCode, etc.)

System Prompts (91):
- Anthropic: 15 Claude prompts (opus-4.6, code, cowork, etc.)
- OpenAI: 49 GPT prompts (gpt-5 series, o3, o4-mini, tools)
- Google: 13 Gemini prompts (2.5-pro, 3-pro, workspace, cli)
- xAI: 5 Grok prompts
- Other: 9 misc prompts (Notion, Raycast, Warp, Kagi, etc.)

Hooks (9):
- JAT hooks for session management, signal tracking, activity logging

Prompts (6):
- pi-mono templates for PR review, issue analysis, changelog audit

Sources analyzed: jat, ralph-desktop, toad, pi-mono, cmux, pi-interactive-shell,
craft-agents-oss, dexter, picoclaw, dyad, system_prompts_leaks, Prometheus,
zed, clawdbot, OS-Copilot, and more
2026-02-13 10:58:17 +00:00

114 lines
5.2 KiB
Bash
Executable File

#!/bin/bash
# Pre-compact hook: Save current agent identity, workflow state, and terminal scrollback before compaction
# This ensures we can restore identity, workflow context, AND terminal history after compaction
#
# Uses WINDOWID-based file - stable across /clear (unlike PPID which changes)
# Each terminal window has unique WINDOWID, avoiding race conditions
PROJECT_DIR="$(pwd)"
CLAUDE_DIR="$PROJECT_DIR/.claude"
JAT_LOGS_DIR="$PROJECT_DIR/.jat/logs"
# Use WINDOWID for persistence (stable across /clear, unique per terminal)
# Falls back to PPID if WINDOWID not available
WINDOW_KEY="${WINDOWID:-$PPID}"
PERSISTENT_AGENT_FILE="$CLAUDE_DIR/.agent-identity-${WINDOW_KEY}"
PERSISTENT_STATE_FILE="$CLAUDE_DIR/.agent-workflow-state-${WINDOW_KEY}.json"
# Find the current session's agent file
SESSION_ID=$(cat /tmp/claude-session-${PPID}.txt 2>/dev/null | tr -d '\n')
# Use sessions/ subdirectory to keep .claude/ clean
AGENT_FILE="$CLAUDE_DIR/sessions/agent-${SESSION_ID}.txt"
# Get tmux session name for signal file lookup and scrollback capture
TMUX_SESSION=""
if [[ -n "${TMUX:-}" ]]; then
TMUX_SESSION=$(tmux display-message -p '#S' 2>/dev/null)
fi
# ============================================================================
# CAPTURE TERMINAL SCROLLBACK BEFORE COMPACTION
# This preserves the pre-compaction terminal history that would otherwise be lost
# Uses unified session log: .jat/logs/session-{sessionName}.log
# ============================================================================
if [[ -n "$TMUX_SESSION" ]]; then
# Use the unified capture script
CAPTURE_SCRIPT="$HOME/.local/bin/capture-session-log.sh"
if [[ -x "$CAPTURE_SCRIPT" ]]; then
PROJECT_DIR="$PROJECT_DIR" "$CAPTURE_SCRIPT" "$TMUX_SESSION" "compacted" 2>/dev/null || true
echo "[PreCompact] Captured scrollback for $TMUX_SESSION (compacted)" >> "$CLAUDE_DIR/.agent-activity.log"
else
# Fallback: inline capture if script not found
mkdir -p "$JAT_LOGS_DIR" 2>/dev/null
LOG_FILE="$JAT_LOGS_DIR/session-${TMUX_SESSION}.log"
TIMESTAMP=$(date -Iseconds)
SCROLLBACK=$(tmux capture-pane -t "$TMUX_SESSION" -p -S - -E - 2>/dev/null || true)
if [[ -n "$SCROLLBACK" ]]; then
# Add header if new file
if [[ ! -f "$LOG_FILE" ]]; then
echo "# Session Log: $TMUX_SESSION" > "$LOG_FILE"
echo "# Created: $TIMESTAMP" >> "$LOG_FILE"
echo "================================================================================" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
fi
# Append scrollback with separator
echo "$SCROLLBACK" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
echo "════════════════════════════════════════════════════════════════════════════════" >> "$LOG_FILE"
echo "📦 CONTEXT COMPACTED at $TIMESTAMP" >> "$LOG_FILE"
echo "════════════════════════════════════════════════════════════════════════════════" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
echo "[PreCompact] Captured scrollback to: $LOG_FILE" >> "$CLAUDE_DIR/.agent-activity.log"
fi
fi
fi
if [[ -f "$AGENT_FILE" ]]; then
AGENT_NAME=$(cat "$AGENT_FILE" | tr -d '\n')
# Save agent name to window-specific location
echo "$AGENT_NAME" > "$PERSISTENT_AGENT_FILE"
# Build workflow state JSON
SIGNAL_STATE="unknown"
TASK_ID=""
TASK_TITLE=""
# Try to get last signal state from signal file
SIGNAL_FILE="/tmp/jat-signal-tmux-${TMUX_SESSION}.json"
if [[ -f "$SIGNAL_FILE" ]]; then
# Signal file may have .state or .signalType depending on source
SIGNAL_STATE=$(jq -r '.state // .signalType // .type // "unknown"' "$SIGNAL_FILE" 2>/dev/null)
# Task ID may be in .task_id or .data.taskId
TASK_ID=$(jq -r '.task_id // .data.taskId // .taskId // ""' "$SIGNAL_FILE" 2>/dev/null)
TASK_TITLE=$(jq -r '.data.taskTitle // .taskTitle // ""' "$SIGNAL_FILE" 2>/dev/null)
fi
# If no signal file, try to get task from JAT Tasks
if [[ -z "$TASK_ID" ]] && command -v jt &>/dev/null; then
TASK_ID=$(jt list --json 2>/dev/null | jq -r --arg a "$AGENT_NAME" '.[] | select(.assignee == $a and .status == "in_progress") | .id' 2>/dev/null | head -1)
if [[ -n "$TASK_ID" ]]; then
TASK_TITLE=$(jt show "$TASK_ID" --json 2>/dev/null | jq -r '.[0].title // ""' 2>/dev/null)
fi
fi
# Save workflow state
cat > "$PERSISTENT_STATE_FILE" << EOF
{
"agentName": "$AGENT_NAME",
"signalState": "$SIGNAL_STATE",
"taskId": "$TASK_ID",
"taskTitle": "$TASK_TITLE",
"savedAt": "$(date -Iseconds)"
}
EOF
# Output marker for IDE state detection
echo "[JAT:COMPACTING]"
# Log for debugging
echo "[PreCompact] Saved agent: $AGENT_NAME, state: $SIGNAL_STATE, task: $TASK_ID (WINDOWID=$WINDOW_KEY)" >> "$CLAUDE_DIR/.agent-activity.log"
fi