Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/hooks/post-edit-record.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# Only track .php files, skip vendored/generated paths
if [[ "$FILE" == *.php ]] && [[ "$FILE" != vendor/* ]] && [[ "$FILE" != */vendor/* ]] && [[ "$FILE" != coverage/* ]] && [[ "$FILE" != */coverage/* ]]; then
TRACKER="/tmp/claude-edited-php-files-${CLAUDE_HOOK_SESSION_ID:-default}"
TRACKER="${TMPDIR:-/tmp}/claude-edited-php-files-${CLAUDE_HOOK_SESSION_ID:-default}"
echo "$FILE" >> "$TRACKER"
sort -u "$TRACKER" -o "$TRACKER"
fi
Expand Down
8 changes: 6 additions & 2 deletions .claude/hooks/session-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
# No network calls, no installs, no docker run - just detect and report.
cd "$CLAUDE_PROJECT_DIR" || exit 0

# Generate a stable session ID and persist via CLAUDE_ENV_FILE
# Use session_id from hook input and persist via CLAUDE_ENV_FILE

@juraj-cm juraj-cm Apr 17, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking] Both PostToolUse and Stop include session_id in their inputs, so you can consider simplifying this by removing the CLAUDE_HOOK_SESSION_ID definition and updating the two other hooks to fetch session_id directly from the input.

# so the edit tracker and stop hook share the same file path
SESSION_ID="$(date +%s)-$$"
INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')
if [[ -z "$SESSION_ID" ]]; then
SESSION_ID="$(date +%s)-$$"
fi
if [[ -n "$CLAUDE_ENV_FILE" ]]; then
echo "export CLAUDE_HOOK_SESSION_ID='$SESSION_ID'" >> "$CLAUDE_ENV_FILE"
fi
Expand Down
49 changes: 25 additions & 24 deletions .claude/hooks/stop-format.sh
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
#!/bin/bash
# Stop hook: batch-format PHP files touched this turn, run test suite, report issues.
# Tests are fast (~2s) so we include them every turn - failures are reported as context.
# Tests are fast (~2s) so we include them when files were edited.
# Failures are reported as context, not blocking.
cd "$CLAUDE_PROJECT_DIR" || exit 0

TRACKER="/tmp/claude-edited-php-files-${CLAUDE_HOOK_SESSION_ID:-default}"
TRACKER="${TMPDIR:-/tmp}/claude-edited-php-files-${CLAUDE_HOOK_SESSION_ID:-default}"

# Skip entirely if no files were edited this turn
[[ -f "$TRACKER" ]] || exit 0

files=$(cat "$TRACKER")
rm -f "$TRACKER"
[[ -n "$files" ]] || exit 0

ctx=""

# Batch php-cs-fixer autocorrect on tracked files (if any were edited)
if [[ -f "$TRACKER" ]]; then
files=$(cat "$TRACKER")
rm -f "$TRACKER"

if [[ -n "$files" ]]; then
if docker image inspect chartmogulphp82 &>/dev/null 2>&1; then
file_args=$(echo "$files" | tr '\n' ' ')
docker run --rm -w /src -v "$(pwd):/src" -v "$HOME/.composer/cache:/root/.composer/cache" chartmogulphp82 \
bash -c "vendor/bin/php-cs-fixer fix --no-interaction --quiet $file_args" 2>/dev/null || true
lint_out=$(docker run --rm -w /src -v "$(pwd):/src" -v "$HOME/.composer/cache:/root/.composer/cache" chartmogulphp82 \
bash -c "vendor/bin/php-cs-fixer fix --dry-run --no-interaction $file_args 2>&1")
elif [[ -x vendor/bin/php-cs-fixer ]]; then
echo "$files" | xargs vendor/bin/php-cs-fixer fix --no-interaction --quiet 2>/dev/null || true
lint_out=$(echo "$files" | xargs vendor/bin/php-cs-fixer fix --dry-run --no-interaction 2>&1)
fi
offenses=$(echo "$lint_out" | grep -E "^\s+\d+\)" | head -20)
if [[ -n "$offenses" ]]; then
ctx+="php-cs-fixer offenses remaining after autocorrect:\n$offenses\n"
fi
fi
# Batch php-cs-fixer autocorrect on tracked files
if docker image inspect chartmogulphp82 &>/dev/null 2>&1; then
file_args=$(echo "$files" | tr '\n' ' ')
docker run --rm -w /src -v "$(pwd):/src" -v "$HOME/.composer/cache:/root/.composer/cache" chartmogulphp82 \
bash -c "vendor/bin/php-cs-fixer fix --no-interaction --quiet $file_args" 2>/dev/null || true
lint_out=$(docker run --rm -w /src -v "$(pwd):/src" -v "$HOME/.composer/cache:/root/.composer/cache" chartmogulphp82 \
bash -c "vendor/bin/php-cs-fixer fix --dry-run --no-interaction $file_args 2>&1")
elif [[ -x vendor/bin/php-cs-fixer ]]; then
echo "$files" | xargs vendor/bin/php-cs-fixer fix --no-interaction --quiet 2>/dev/null || true
lint_out=$(echo "$files" | xargs vendor/bin/php-cs-fixer fix --dry-run --no-interaction 2>&1)
fi
offenses=$(echo "$lint_out" | grep -E "^\s+\d+\)" | head -20)
if [[ -n "$offenses" ]]; then
ctx+="php-cs-fixer offenses remaining after autocorrect:\n$offenses\n"
fi

# Always run tests - edits to tests or src both matter (~2s)
# Run tests - only when files were edited this turn (~2s)
if docker image inspect chartmogulphp82 &>/dev/null 2>&1; then
test_out=$(docker run --rm -w /src -v "$(pwd):/src" -v "$HOME/.composer/cache:/root/.composer/cache" chartmogulphp82 \
phpunit 2>&1)
Expand Down
16 changes: 14 additions & 2 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,20 @@
"Bash(git pull:*)",
"Bash(git cherry-pick:*)",
"Bash(git reset:*)",
"Bash(gh pr:*)",
"Bash(gh api:*)"
"Bash(gh pr view:*)",
"Bash(gh pr list:*)",
"Bash(gh pr diff:*)",
"Bash(gh pr checks:*)",
"Bash(gh pr status:*)",
"Bash(gh run view:*)",
"Bash(gh run list:*)",
"Bash(gh run watch:*)",
"Bash(gh issue view:*)",
"Bash(gh issue list:*)",
"Bash(gh release view:*)",
"Bash(gh release list:*)",
"Bash(gh repo view:*)",
"Bash(gh search:*)"
],
"deny": [
"Read(./.env*)"
Expand Down
Loading