check-sleep.sh 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #!/bin/bash
  2. # Caffeinate hook: Blocks sleep commands and suggests background tasks
  3. set -euo pipefail
  4. input=$(cat)
  5. command=$(echo "$input" | jq -r '.tool_input.command // empty')
  6. if [[ -z "$command" ]]; then
  7. exit 0
  8. fi
  9. # Allow sleep if run_in_background is true - that's the whole point!
  10. run_in_bg=$(echo "$input" | jq -r '.tool_input.run_in_background // false')
  11. if [[ "$run_in_bg" == "true" ]]; then
  12. exit 0
  13. fi
  14. block_message='ACTION REQUIRED: Your sleep command was blocked. You MUST now call Bash again with the SAME command but add the parameter run_in_background: true. Do this immediately in your next tool call. Do not explain or apologize - just retry with run_in_background: true.'
  15. output_block() {
  16. # Output JSON to stdout for blocking decision
  17. # Output message to stderr to feed back to Claude
  18. cat << EOF
  19. {
  20. "hookSpecificOutput": {
  21. "hookEventName": "PreToolUse",
  22. "permissionDecision": "deny",
  23. "permissionDecisionReason": "$block_message"
  24. }
  25. }
  26. EOF
  27. exit 0
  28. }
  29. # Remove all quoted strings to avoid false positives
  30. # Replace single and double quoted strings with placeholder
  31. cmd_no_quotes=$(echo "$command" | sed -E "s/\"[^\"]*\"//g; s/'[^']*'//g")
  32. # Check for sleep command patterns in the de-quoted command
  33. # Pattern 1: Command starts with sleep
  34. if [[ "$cmd_no_quotes" =~ (^|[[:space:]])sleep[[:space:]]+[0-9] ]]; then
  35. output_block
  36. fi
  37. # Pattern 2: sleep after any common separator (&&, ||, ;, |, do, then)
  38. if [[ "$cmd_no_quotes" =~ (\&\&|;\||[[:space:]]do[[:space:]]|[[:space:]]then[[:space:]])[[:space:]]*sleep[[:space:]] ]]; then
  39. output_block
  40. fi
  41. # Pattern 3: Simple contains check - if "sleep " followed by number appears anywhere
  42. if [[ "$cmd_no_quotes" =~ sleep[[:space:]]+[0-9] ]]; then
  43. output_block
  44. fi
  45. # Pattern 4: sleep with variable like $TIMEOUT or ${DELAY}
  46. if [[ "$cmd_no_quotes" =~ sleep[[:space:]]+\$ ]]; then
  47. output_block
  48. fi
  49. # No sleep command detected - allow
  50. exit 0