From 17bcd0130e17533b7ca168b449ab9a878446d124 Mon Sep 17 00:00:00 2001 From: HeshamHM28 Date: Tue, 17 Mar 2026 06:57:28 +0200 Subject: [PATCH 1/3] add HEAD check gate to skip expensive work on most Stop hook invocations --- scripts/suggest-optimize.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scripts/suggest-optimize.sh b/scripts/suggest-optimize.sh index b3cf829..cbf0501 100755 --- a/scripts/suggest-optimize.sh +++ b/scripts/suggest-optimize.sh @@ -23,6 +23,16 @@ fi REPO_ROOT=$(cd "$(git rev-parse --show-toplevel 2>/dev/null)" && pwd -P) || exit 0 cd "$(pwd -P)" +# --- Cheap gate: skip if HEAD hasn't changed since last check --- +CURRENT_HEAD=$(git rev-parse HEAD 2>/dev/null) || exit 0 +STATE_DIR="/tmp/codeflash-state" +REPO_HASH=$(echo "$REPO_ROOT" | shasum -a 256 | cut -d' ' -f1) +LAST_HEAD_FILE="$STATE_DIR/$REPO_HASH-head" +mkdir -p "$STATE_DIR" +if [ -f "$LAST_HEAD_FILE" ] && [ "$(cat "$LAST_HEAD_FILE")" = "$CURRENT_HEAD" ]; then + exit 0 +fi + # --- Check if codeflash is already auto-allowed in .claude/settings.json --- CODEFLASH_AUTO_ALLOWED="false" SETTINGS_JSON="$REPO_ROOT/.claude/settings.json" @@ -65,9 +75,14 @@ fi # Find commits with Python files made after the session started PY_COMMITS=$(git log --after="@$SESSION_START" --name-only --diff-filter=ACMR --pretty=format: -- '*.py' 2>/dev/null | sort -u | grep -v '^$' || true) if [ -z "$PY_COMMITS" ]; then + # HEAD changed but no Python files — update the marker so we don't re-check + echo "$CURRENT_HEAD" > "$LAST_HEAD_FILE" exit 0 fi +# HEAD has new Python commits — record it so we don't re-trigger on subsequent turns +echo "$CURRENT_HEAD" > "$LAST_HEAD_FILE" + # Dedup: don't trigger twice for the same set of changes across sessions. # Use the project directory from transcript_path for state storage. PROJECT_DIR=$(dirname "$TRANSCRIPT_PATH") From 8249bc4654fad27f6131ef79b4ce2cdd0d94f3c5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 17 Mar 2026 23:29:38 +0000 Subject: [PATCH 2/3] fix: use .claude/ directory instead of /tmp for HEAD cache state Store the HEAD cache file in $REPO_ROOT/.claude/ (the project-specific Claude directory) instead of /tmp/codeflash-state/. This is consistent with how the plugin already uses .claude/ for settings.json and avoids polluting /tmp. Co-Authored-By: Claude Opus 4.6 --- scripts/suggest-optimize.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/suggest-optimize.sh b/scripts/suggest-optimize.sh index d5c5a89..b029519 100755 --- a/scripts/suggest-optimize.sh +++ b/scripts/suggest-optimize.sh @@ -25,9 +25,8 @@ cd "$(pwd -P)" # --- Cheap gate: skip if HEAD hasn't changed since last check --- CURRENT_HEAD=$(git rev-parse HEAD 2>/dev/null) || exit 0 -STATE_DIR="/tmp/codeflash-state" -REPO_HASH=$(echo "$REPO_ROOT" | shasum -a 256 | cut -d' ' -f1) -LAST_HEAD_FILE="$STATE_DIR/$REPO_HASH-head" +STATE_DIR="$REPO_ROOT/.claude" +LAST_HEAD_FILE="$STATE_DIR/.codeflash-last-head" mkdir -p "$STATE_DIR" if [ -f "$LAST_HEAD_FILE" ] && [ "$(cat "$LAST_HEAD_FILE")" = "$CURRENT_HEAD" ]; then exit 0 From 8c21ea05feb6262ba1933816eac599aa3cc74153 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 17 Mar 2026 23:34:26 +0000 Subject: [PATCH 3/3] fix: use transcript directory instead of /tmp for HEAD cache state Store the HEAD cache file in the Claude-managed transcript directory (alongside codeflash-seen) instead of /tmp/codeflash-state/. The transcript directory is already used for per-session state and is the proper plugin-specific location for this kind of data. Also fixes a bug where the HEAD cache was never written after the check, so the gate would never actually skip subsequent invocations. Co-Authored-By: Claude Opus 4.6 --- scripts/suggest-optimize.sh | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/scripts/suggest-optimize.sh b/scripts/suggest-optimize.sh index b029519..e063d43 100755 --- a/scripts/suggest-optimize.sh +++ b/scripts/suggest-optimize.sh @@ -23,15 +23,6 @@ fi REPO_ROOT=$(cd "$(git rev-parse --show-toplevel 2>/dev/null)" && pwd -P) || exit 0 cd "$(pwd -P)" -# --- Cheap gate: skip if HEAD hasn't changed since last check --- -CURRENT_HEAD=$(git rev-parse HEAD 2>/dev/null) || exit 0 -STATE_DIR="$REPO_ROOT/.claude" -LAST_HEAD_FILE="$STATE_DIR/.codeflash-last-head" -mkdir -p "$STATE_DIR" -if [ -f "$LAST_HEAD_FILE" ] && [ "$(cat "$LAST_HEAD_FILE")" = "$CURRENT_HEAD" ]; then - exit 0 -fi - # --- Check if codeflash is already auto-allowed in .claude/settings.json --- CODEFLASH_AUTO_ALLOWED="false" SETTINGS_JSON="$REPO_ROOT/.claude/settings.json" @@ -48,6 +39,15 @@ TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null if [ -z "$TRANSCRIPT_PATH" ] || [ ! -f "$TRANSCRIPT_PATH" ]; then exit 0 fi +TRANSCRIPT_DIR=$(dirname "$TRANSCRIPT_PATH") + +# --- Cheap gate: skip if HEAD hasn't changed since last check --- +CURRENT_HEAD=$(git rev-parse HEAD 2>/dev/null) || exit 0 +LAST_HEAD_FILE="$TRANSCRIPT_DIR/codeflash-last-head" +if [ -f "$LAST_HEAD_FILE" ] && [ "$(cat "$LAST_HEAD_FILE")" = "$CURRENT_HEAD" ]; then + exit 0 +fi +echo "$CURRENT_HEAD" > "$LAST_HEAD_FILE" # Get the transcript file's creation (birth) time as the session start timestamp. # This predates any commits Claude could have made in this session. @@ -88,8 +88,6 @@ if echo "$CHANGED_COMMITS" | grep -qE '\.(js|ts|jsx|tsx)$'; then fi # Dedup: don't trigger twice for the same set of changes across sessions. -# Use the project directory from transcript_path for state storage. -TRANSCRIPT_DIR=$(dirname "$TRANSCRIPT_PATH") SEEN_MARKER="$TRANSCRIPT_DIR/codeflash-seen" COMMIT_HASH=$(git log --after="@$SESSION_START" --pretty=format:%H -- '*.py' '*.js' '*.ts' '*.jsx' '*.tsx' 2>/dev/null | shasum -a 256 | cut -d' ' -f1)