mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-02-01 20:23:36 +00:00
Add caffeinate plugin to prevent blocking sleep commands
This plugin intercepts sleep commands in Bash and prompts Claude to use
background execution (run_in_background: true) instead. This keeps the
session responsive during long-running operations.
Features:
- Blocks sleep commands with helpful retry message
- Allows sleep in quoted strings (false positive prevention)
- Catches sleep in compound commands (&&, ||, ;) and loops
- Allows background commands through (run_in_background: true)
🏠 Remote-Dev: homespace
Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%)
Claude-Steers: 6
Claude-Permission-Prompts: 0
Claude-Escapes: 0
This commit is contained in:
17
plugins/caffeinate/hooks/hooks.json
Normal file
17
plugins/caffeinate/hooks/hooks.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"description": "Blocks sleep commands and reminds Claude to use background tasks",
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-sleep.sh",
|
||||
"timeout": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
61
plugins/caffeinate/hooks/scripts/check-sleep.sh
Executable file
61
plugins/caffeinate/hooks/scripts/check-sleep.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
# Caffeinate hook: Blocks sleep commands and suggests background tasks
|
||||
set -euo pipefail
|
||||
|
||||
input=$(cat)
|
||||
command=$(echo "$input" | jq -r '.tool_input.command // empty')
|
||||
|
||||
if [[ -z "$command" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Allow sleep if run_in_background is true - that's the whole point!
|
||||
run_in_bg=$(echo "$input" | jq -r '.tool_input.run_in_background // false')
|
||||
if [[ "$run_in_bg" == "true" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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.'
|
||||
|
||||
output_block() {
|
||||
# Output JSON to stdout for blocking decision
|
||||
# Output message to stderr to feed back to Claude
|
||||
cat << EOF
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "deny",
|
||||
"permissionDecisionReason": "$block_message"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Remove all quoted strings to avoid false positives
|
||||
# Replace single and double quoted strings with placeholder
|
||||
cmd_no_quotes=$(echo "$command" | sed -E "s/\"[^\"]*\"//g; s/'[^']*'//g")
|
||||
|
||||
# Check for sleep command patterns in the de-quoted command
|
||||
# Pattern 1: Command starts with sleep
|
||||
if [[ "$cmd_no_quotes" =~ (^|[[:space:]])sleep[[:space:]]+[0-9] ]]; then
|
||||
output_block
|
||||
fi
|
||||
|
||||
# Pattern 2: sleep after any common separator (&&, ||, ;, |, do, then)
|
||||
if [[ "$cmd_no_quotes" =~ (\&\&|;\||[[:space:]]do[[:space:]]|[[:space:]]then[[:space:]])[[:space:]]*sleep[[:space:]] ]]; then
|
||||
output_block
|
||||
fi
|
||||
|
||||
# Pattern 3: Simple contains check - if "sleep " followed by number appears anywhere
|
||||
if [[ "$cmd_no_quotes" =~ sleep[[:space:]]+[0-9] ]]; then
|
||||
output_block
|
||||
fi
|
||||
|
||||
# Pattern 4: sleep with variable like $TIMEOUT or ${DELAY}
|
||||
if [[ "$cmd_no_quotes" =~ sleep[[:space:]]+\$ ]]; then
|
||||
output_block
|
||||
fi
|
||||
|
||||
# No sleep command detected - allow
|
||||
exit 0
|
||||
Reference in New Issue
Block a user