[Config] Add coding guidelines and code-fixer agent
Major additions: - Add CODING_GUIDELINES.md with "NO EMOJIS" rule - Create code-fixer agent for automated violation fixes - Add offline mode v2 hooks with local caching/queue - Add periodic context save with invisible Task Scheduler setup - Add agent coordination rules and database connection docs Infrastructure: - Update hooks: task-complete-v2, user-prompt-submit-v2 - Add periodic_save_check.py for auto-save every 5min - Add PowerShell scripts: setup_periodic_save.ps1, update_to_invisible.ps1 - Add sync-contexts script for queue synchronization Documentation: - OFFLINE_MODE.md, PERIODIC_SAVE_INVISIBLE_SETUP.md - Migration procedures and verification docs - Fix flashing window guide Updates: - Update agent configs (backup, code-review, coding, database, gitea, testing) - Update claude.md with coding guidelines reference - Update .gitignore for new cache/queue directories Status: Pre-automated-fixer baseline commit Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
226
.claude/hooks/periodic-context-save
Normal file
226
.claude/hooks/periodic-context-save
Normal file
@@ -0,0 +1,226 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Periodic Context Save Hook
|
||||
# Runs as a background daemon to save context every 5 minutes of active time
|
||||
#
|
||||
# Usage: bash .claude/hooks/periodic-context-save start
|
||||
# bash .claude/hooks/periodic-context-save stop
|
||||
# bash .claude/hooks/periodic-context-save status
|
||||
#
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CLAUDE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
PID_FILE="$CLAUDE_DIR/.periodic-save.pid"
|
||||
STATE_FILE="$CLAUDE_DIR/.periodic-save-state"
|
||||
CONFIG_FILE="$CLAUDE_DIR/context-recall-config.env"
|
||||
|
||||
# Load configuration
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
source "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Configuration
|
||||
SAVE_INTERVAL_SECONDS=300 # 5 minutes
|
||||
CHECK_INTERVAL_SECONDS=60 # Check every minute
|
||||
API_URL="${CLAUDE_API_URL:-http://172.16.3.30:8001}"
|
||||
|
||||
# Detect project ID
|
||||
detect_project_id() {
|
||||
# Try git config first
|
||||
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
|
||||
PROJECT_ID=$(echo -n "$GIT_REMOTE" | md5sum | cut -d' ' -f1)
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$PROJECT_ID"
|
||||
}
|
||||
|
||||
# Check if Claude Code is active (not idle)
|
||||
is_claude_active() {
|
||||
# Check if there are recent Claude Code processes or activity
|
||||
# This is a simple heuristic - can be improved
|
||||
|
||||
# On Windows with Git Bash, check for claude process
|
||||
if command -v tasklist.exe >/dev/null 2>&1; then
|
||||
tasklist.exe 2>/dev/null | grep -i claude >/dev/null 2>&1
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Assume active if we can't detect
|
||||
return 0
|
||||
}
|
||||
|
||||
# Get active time from state file
|
||||
get_active_time() {
|
||||
if [ -f "$STATE_FILE" ]; then
|
||||
cat "$STATE_FILE" | grep "^active_seconds=" | cut -d'=' -f2
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
# Update active time in state file
|
||||
update_active_time() {
|
||||
local active_seconds=$1
|
||||
echo "active_seconds=$active_seconds" > "$STATE_FILE"
|
||||
echo "last_update=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> "$STATE_FILE"
|
||||
}
|
||||
|
||||
# Save context to database
|
||||
save_periodic_context() {
|
||||
local project_id=$(detect_project_id)
|
||||
|
||||
# Generate context summary
|
||||
local title="Periodic Save - $(date +"%Y-%m-%d %H:%M")"
|
||||
local summary="Auto-saved context after 5 minutes of active work. Session in progress on project: ${project_id:-unknown}"
|
||||
|
||||
# Create JSON payload
|
||||
local payload=$(cat <<EOF
|
||||
{
|
||||
"context_type": "session_summary",
|
||||
"title": "$title",
|
||||
"dense_summary": "$summary",
|
||||
"relevance_score": 5.0,
|
||||
"tags": "[\"auto-save\", \"periodic\", \"active-session\"]"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
# POST to API
|
||||
if [ -n "$JWT_TOKEN" ]; then
|
||||
curl -s -X POST "${API_URL}/api/conversation-contexts" \
|
||||
-H "Authorization: Bearer ${JWT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$payload" >/dev/null 2>&1
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "[$(date)] Context saved successfully" >&2
|
||||
else
|
||||
echo "[$(date)] Failed to save context" >&2
|
||||
fi
|
||||
else
|
||||
echo "[$(date)] No JWT token - cannot save context" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Main monitoring loop
|
||||
monitor_loop() {
|
||||
local active_seconds=0
|
||||
|
||||
echo "[$(date)] Periodic context save daemon started (PID: $$)" >&2
|
||||
echo "[$(date)] Will save context every ${SAVE_INTERVAL_SECONDS}s of active time" >&2
|
||||
|
||||
while true; do
|
||||
# Check if Claude is active
|
||||
if is_claude_active; then
|
||||
# Increment active time
|
||||
active_seconds=$((active_seconds + CHECK_INTERVAL_SECONDS))
|
||||
update_active_time $active_seconds
|
||||
|
||||
# Check if we've reached the save interval
|
||||
if [ $active_seconds -ge $SAVE_INTERVAL_SECONDS ]; then
|
||||
echo "[$(date)] ${SAVE_INTERVAL_SECONDS}s of active time reached - saving context" >&2
|
||||
save_periodic_context
|
||||
|
||||
# Reset timer
|
||||
active_seconds=0
|
||||
update_active_time 0
|
||||
fi
|
||||
else
|
||||
echo "[$(date)] Claude Code inactive - not counting time" >&2
|
||||
fi
|
||||
|
||||
# Wait before next check
|
||||
sleep $CHECK_INTERVAL_SECONDS
|
||||
done
|
||||
}
|
||||
|
||||
# Start daemon
|
||||
start_daemon() {
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
local pid=$(cat "$PID_FILE")
|
||||
if kill -0 $pid 2>/dev/null; then
|
||||
echo "Periodic context save daemon already running (PID: $pid)"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start in background
|
||||
nohup bash "$0" _monitor >> "$CLAUDE_DIR/periodic-save.log" 2>&1 &
|
||||
local pid=$!
|
||||
echo $pid > "$PID_FILE"
|
||||
|
||||
echo "Started periodic context save daemon (PID: $pid)"
|
||||
echo "Logs: $CLAUDE_DIR/periodic-save.log"
|
||||
}
|
||||
|
||||
# Stop daemon
|
||||
stop_daemon() {
|
||||
if [ ! -f "$PID_FILE" ]; then
|
||||
echo "Periodic context save daemon not running"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local pid=$(cat "$PID_FILE")
|
||||
if kill $pid 2>/dev/null; then
|
||||
echo "Stopped periodic context save daemon (PID: $pid)"
|
||||
rm -f "$PID_FILE"
|
||||
rm -f "$STATE_FILE"
|
||||
else
|
||||
echo "Failed to stop daemon (PID: $pid) - may not be running"
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check status
|
||||
check_status() {
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
local pid=$(cat "$PID_FILE")
|
||||
if kill -0 $pid 2>/dev/null; then
|
||||
local active_seconds=$(get_active_time)
|
||||
echo "Periodic context save daemon is running (PID: $pid)"
|
||||
echo "Active time: ${active_seconds}s / ${SAVE_INTERVAL_SECONDS}s"
|
||||
return 0
|
||||
else
|
||||
echo "Daemon PID file exists but process not running"
|
||||
rm -f "$PID_FILE"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo "Periodic context save daemon not running"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Command dispatcher
|
||||
case "$1" in
|
||||
start)
|
||||
start_daemon
|
||||
;;
|
||||
stop)
|
||||
stop_daemon
|
||||
;;
|
||||
status)
|
||||
check_status
|
||||
;;
|
||||
_monitor)
|
||||
# Internal command - run monitor loop
|
||||
monitor_loop
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|status}"
|
||||
echo ""
|
||||
echo "Periodic context save daemon - saves context every 5 minutes of active time"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " start - Start the background daemon"
|
||||
echo " stop - Stop the daemon"
|
||||
echo " status - Check daemon status"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user