Created
August 6, 2025 09:11
-
-
Save jamesaphoenix/c907a09e4f6ba9f039afe4547213227b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| # Claude Code PostToolUse hook for type checking | |
| # Reads JSON from stdin and runs TypeScript compiler on the project when TS files are modified | |
| INPUT=$(cat) | |
| # Debug: show what we received | |
| echo "Received input: $INPUT" >&2 | |
| # Check if input is valid JSON | |
| if ! echo "$INPUT" | jq empty 2>/dev/null; then | |
| echo "Error: Invalid JSON input" >&2 | |
| exit 1 | |
| fi | |
| TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty') | |
| # Security: Validate file paths to prevent path traversal and skip sensitive files | |
| is_safe_file() { | |
| local FILE="$1" | |
| # Check for path traversal | |
| if [[ "$FILE" == *".."* ]]; then | |
| echo "Skipping potentially unsafe path: $FILE" >&2 | |
| return 1 | |
| fi | |
| # Skip sensitive files | |
| case "$FILE" in | |
| *.env*|*.key|*.pem|*.p12|*.pfx|.git/*|node_modules/*|*/node_modules/*) | |
| echo "Skipping sensitive file: $FILE" >&2 | |
| return 1 | |
| ;; | |
| *) | |
| return 0 | |
| ;; | |
| esac | |
| } | |
| # Check if file is TypeScript | |
| is_typescript_file() { | |
| local FILE="$1" | |
| case "$FILE" in | |
| *.ts|*.tsx|*.d.ts) | |
| return 0 | |
| ;; | |
| *) | |
| return 1 | |
| ;; | |
| esac | |
| } | |
| # Check if any TypeScript files were modified | |
| check_for_typescript_files() { | |
| local FOUND_TS=false | |
| case "$TOOL_NAME" in | |
| "MultiEdit") | |
| echo "$INPUT" | jq -r '.tool_input.files[]?.file_path // empty' | while read -r FILE; do | |
| if [[ -n "$FILE" ]] && is_safe_file "$FILE" && is_typescript_file "$FILE"; then | |
| echo "TypeScript file detected: $FILE" >&2 | |
| FOUND_TS=true | |
| fi | |
| done | |
| ;; | |
| "Write"|"Edit") | |
| FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.target_file // empty') | |
| if [[ -n "$FILE_PATH" ]] && is_safe_file "$FILE_PATH" && is_typescript_file "$FILE_PATH"; then | |
| echo "TypeScript file detected: $FILE_PATH" >&2 | |
| FOUND_TS=true | |
| fi | |
| ;; | |
| esac | |
| echo "$FOUND_TS" | |
| } | |
| # Process different tool types | |
| case "$TOOL_NAME" in | |
| "Write"|"Edit"|"MultiEdit") | |
| echo "Processing $TOOL_NAME operation..." >&2 | |
| # Check if any TypeScript files were modified | |
| TS_FOUND=$(check_for_typescript_files) | |
| if [[ "$TS_FOUND" == "true" ]]; then | |
| echo "TypeScript files detected, running type check..." >&2 | |
| # Run type check on the project | |
| if ! pnpm tsc --noEmit 2>&1; then | |
| echo "Warning: TypeScript compilation has errors" >&2 | |
| # Don't fail the hook, just report the issue | |
| else | |
| echo "TypeScript compilation successful" >&2 | |
| fi | |
| else | |
| echo "No TypeScript files detected, skipping type check" >&2 | |
| fi | |
| ;; | |
| *) | |
| echo "Skipping non-file operation: $TOOL_NAME" >&2 | |
| ;; | |
| esac | |
| echo "Type check hook completed" >&2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment