
Continuous Learning V2
Run a background observer loop that samples session activity and triggers analysis on a cooldown so your Claude Code workflow learns without spawning runaway parallel processes.
Install
npx skills add https://github.com/affaan-m/everything-claude-code --skill continuous-learning-v2What is this skill?
- Background observer loop with re-entrancy guard to block overlapping analyses
- Configurable analysis cooldown (default 60s) and idle timeout (default 1800s)
- Session lease directory under `.observer-sessions` to detect active work
- USR1/signal handling and cleanup for sleep PID and PID file on exit
- Tail-based sampling hooks tied to observations/activity files (memory-safe vs runaway parallel Claude runs)
Adoption & trust: 6.5k installs on skills.sh; 210k GitHub stars; 2/3 security scanners passed (skills.sh audits).
Recommended Skills
Journey fit
Agent-tooling is the canonical shelf because the skill is infrastructure for how your coding agent improves over time, not a single feature ship task. Continuous-learning-v2 installs observer loops, PID files, and session leases in the project—core agent ergonomics for solo builders using ECC-style setups.
Common Questions / FAQ
Is Continuous Learning V2 safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Continuous Learning V2
#!/usr/bin/env bash # Continuous Learning v2 - Observer background loop # # Fix for #521: Added re-entrancy guard, cooldown throttle, and # tail-based sampling to prevent memory explosion from runaway # parallel Claude analysis processes. set +e unset CLAUDECODE SLEEP_PID="" USR1_FIRED=0 PENDING_ANALYSIS=0 ANALYZING=0 LAST_ANALYSIS_EPOCH=0 # Minimum seconds between analyses (prevents rapid re-triggering) ANALYSIS_COOLDOWN="${ECC_OBSERVER_ANALYSIS_COOLDOWN:-60}" IDLE_TIMEOUT_SECONDS="${ECC_OBSERVER_IDLE_TIMEOUT_SECONDS:-1800}" SESSION_LEASE_DIR="${PROJECT_DIR}/.observer-sessions" ACTIVITY_FILE="${PROJECT_DIR}/.observer-last-activity" cleanup() { [ -n "$SLEEP_PID" ] && kill "$SLEEP_PID" 2>/dev/null if [ -f "$PID_FILE" ] && [ "$(cat "$PID_FILE" 2>/dev/null)" = "$$" ]; then rm -f "$PID_FILE" fi exit 0 } trap cleanup TERM INT file_mtime_epoch() { local file="$1" if [ ! -f "$file" ]; then printf '0\n' return fi if stat -c %Y "$file" >/dev/null 2>&1; then stat -c %Y "$file" 2>/dev/null || printf '0\n' return fi if stat -f %m "$file" >/dev/null 2>&1; then stat -f %m "$file" 2>/dev/null || printf '0\n' return fi printf '0\n' } has_active_session_leases() { if [ ! -d "$SESSION_LEASE_DIR" ]; then return 1 fi find "$SESSION_LEASE_DIR" -type f -name '*.json' -print -quit 2>/dev/null | grep -q . } latest_activity_epoch() { local observations_epoch activity_epoch observations_epoch="$(file_mtime_epoch "$OBSERVATIONS_FILE")" activity_epoch="$(file_mtime_epoch "$ACTIVITY_FILE")" if [ "$activity_epoch" -gt "$observations_epoch" ] 2>/dev/null; then printf '%s\n' "$activity_epoch" else printf '%s\n' "$observations_epoch" fi } exit_if_idle_without_sessions() { if has_active_session_leases; then return fi local last_activity now_epoch idle_for last_activity="$(latest_activity_epoch)" now_epoch="$(date +%s)" idle_for=$(( now_epoch - last_activity )) if [ "$last_activity" -eq 0 ] || [ "$idle_for" -ge "$IDLE_TIMEOUT_SECONDS" ]; then echo "[$(date)] Observer idle without active session leases for ${idle_for}s; exiting" >> "$LOG_FILE" cleanup fi } wait_for_claude_analysis() { local child_pid="$1" local wait_status=0 while true; do wait "$child_pid" wait_status=$? if [ "$wait_status" -eq 0 ]; then return 0 fi # SIGUSR1 can interrupt wait while the Claude child is still running. # Re-wait in that case so a signal is not logged as a false child failure. if kill -0 "$child_pid" 2>/dev/null; then continue fi return "$wait_status" done } analyze_observations() { if [ ! -f "$OBSERVATIONS_FILE" ]; then return fi obs_count=$(wc -l < "$OBSERVATIONS_FILE" 2>/dev/null || echo 0) if [ "$obs_count" -lt "$MIN_OBSERVATIONS" ]; then return fi echo "[$(date)] Analyzing $obs_count observations for project ${PROJECT_NAME}..." >> "$LOG_FILE" if [ "${CLV2_IS_WINDOWS:-false}" = "true" ] && [ "${ECC_OBSERVER_ALLOW_WINDOWS:-false}" != "true" ]; then echo "[$(date)] Skipping claude analysis on Windows due to known non-interactive hang issue (#295). Set ECC_OBSERVER_ALLOW_WINDOWS=true to override." >> "$LOG_FILE" return fi if ! command -v claude >/dev/null 2>&1; then echo "[$(date)] claude CLI not found, skipping analysis" >> "$LOG_FILE" return fi # session-guardian: gate observer cycle (active hours, cooldown, idle detection) if ! bash "$(dirname "$0")/session-guardian.sh"; then echo "[$(date)] Observer cycle skipped by session-guardian" >> "$LOG_FILE" return fi # Sample recent observations instead of loading the entire file (#521). # This prevents multi-MB payloads from being passed to the LLM. MAX_ANALYSIS_LINES="${ECC_OBSERVER_MAX_ANALYSIS_LINES:-500}" observer_tmp_dir="${PROJECT_DIR}/.observer-tmp" mkdir -p "$observer_tmp_dir" analysis_file="$(mktemp "${observer_tmp_dir}/ecc-observer-analysis.XXXXXX.jsonl")" tail -n