Skip to content

Instantly share code, notes, and snippets.

@jamesaphoenix
Created August 6, 2025 09:11
Show Gist options
  • Select an option

  • Save jamesaphoenix/c907a09e4f6ba9f039afe4547213227b to your computer and use it in GitHub Desktop.

Select an option

Save jamesaphoenix/c907a09e4f6ba9f039afe4547213227b to your computer and use it in GitHub Desktop.
#!/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