diff --git a/SETUP.md b/SETUP.md index a6887b1d..35aa8e2f 100644 --- a/SETUP.md +++ b/SETUP.md @@ -290,7 +290,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -301,7 +301,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -312,7 +312,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -323,7 +323,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -334,7 +334,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -345,7 +345,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -356,7 +356,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -367,7 +367,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -376,7 +376,7 @@ The tracker needs **8 of Claude Code's 24 hook events** registered in `~/.claude } ``` -> **Important:** Timeout values are in **milliseconds** for command hooks (5000 = 5 seconds). If you already have a `"hooks"` key in settings.json, merge these entries into it rather than overwriting. +> **Important:** Timeout values are in **seconds** for command hooks (`5` = 5 seconds, not milliseconds — `5000` would be 83 minutes). If you already have a `"hooks"` key in settings.json, merge these entries into it rather than overwriting. **Verify:** ```bash @@ -592,7 +592,7 @@ ls -la ~/.claude/hooks/session_title_generator.py { "type": "command", "command": "python3 ~/.claude/hooks/session_title_generator.py", - "timeout": 15000 + "timeout": 15 } ] } @@ -611,7 +611,7 @@ If you have Tier 2 live tracker, your `SessionEnd` should now have TWO entries: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] }, @@ -620,7 +620,7 @@ If you have Tier 2 live tracker, your `SessionEnd` should now have TWO entries: { "type": "command", "command": "python3 ~/.claude/hooks/session_title_generator.py", - "timeout": 15000 + "timeout": 15 } ] } @@ -802,7 +802,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -813,7 +813,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -824,7 +824,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -835,7 +835,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -846,7 +846,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -857,7 +857,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -868,7 +868,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -879,7 +879,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] }, @@ -888,7 +888,7 @@ The full `~/.claude/settings.json` for Tier 2 + 3: { "type": "command", "command": "python3 ~/.claude/hooks/session_title_generator.py", - "timeout": 15000 + "timeout": 15 } ] } @@ -912,7 +912,7 @@ If you installed the branch detector hook in Tier 4, add it to `SessionStart` al { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 }, { "type": "command", diff --git a/api/SETUP.md b/api/SETUP.md index 8f3867da..d25b7065 100644 --- a/api/SETUP.md +++ b/api/SETUP.md @@ -81,7 +81,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -92,7 +92,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -103,7 +103,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -114,7 +114,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -125,7 +125,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -136,7 +136,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -147,7 +147,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -158,7 +158,7 @@ Add the following to `~/.claude/settings.json`: { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } diff --git a/api/models/hook.py b/api/models/hook.py index afd54713..246b0974 100644 --- a/api/models/hook.py +++ b/api/models/hook.py @@ -13,7 +13,7 @@ { "matcher": "*", "hooks": [ - {"type": "command", "command": "python3 script.py", "timeout": 5000} + {"type": "command", "command": "python3 script.py", "timeout": 5} ] } ] @@ -110,7 +110,7 @@ class HookRegistration(BaseModel): command: str script_filename: Optional[str] = None script_language: str = "unknown" - timeout_ms: Optional[int] = None + timeout_seconds: Optional[int] = None can_block: bool = False @@ -372,7 +372,7 @@ def _parse_hook_groups( if not command: continue - timeout_ms = hook_entry.get("timeout") + timeout_seconds = hook_entry.get("timeout") # For plugins, expand ${CLAUDE_PLUGIN_ROOT} in the display command display_command = command @@ -390,7 +390,7 @@ def _parse_hook_groups( command=display_command, script_filename=_extract_script_filename(command), script_language=_detect_script_language(command), - timeout_ms=timeout_ms, + timeout_seconds=timeout_seconds, can_block=can_block, description=description, ) diff --git a/api/scripts/SETUP.md b/api/scripts/SETUP.md index af37f601..a32270b4 100644 --- a/api/scripts/SETUP.md +++ b/api/scripts/SETUP.md @@ -44,42 +44,42 @@ hooks: SessionStart: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 UserPromptSubmit: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 PostToolUse: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 Notification: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 Stop: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 SubagentStart: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 SubagentStop: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 SessionEnd: - command: | cat | python3 ~/.local/bin/claude-code-karma-tracker - timeout: 2000 + timeout: 2 ``` #### Option B: Global hooks (all projects) @@ -89,14 +89,14 @@ Add to `~/.claude/settings.json`: ```json { "hooks": { - "SessionStart": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }], - "UserPromptSubmit": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }], - "PostToolUse": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }], - "Notification": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }], - "Stop": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }], - "SessionEnd": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }], - "SubagentStart": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }], - "SubagentStop": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2000 }] + "SessionStart": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }], + "UserPromptSubmit": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }], + "PostToolUse": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }], + "Notification": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }], + "Stop": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }], + "SessionEnd": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }], + "SubagentStart": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }], + "SubagentStop": [{ "command": "cat | python3 ~/.local/bin/claude-code-karma-tracker", "timeout": 2 }] } } ``` diff --git a/captain-hook/README.md b/captain-hook/README.md index bb4448b9..e20321c1 100644 --- a/captain-hook/README.md +++ b/captain-hook/README.md @@ -98,7 +98,7 @@ Hooks are defined in `.claude/hooks.yaml`: hooks: PreToolUse: - command: "your-script.sh" - timeout: 5000 + timeout: 5 match_tools: ["Write", "Edit"] # optional filter - type: "prompt" # LLM-powered hook diff --git a/captain-hook/docs/hooks/CwdChanged-info-available.md b/captain-hook/docs/hooks/CwdChanged-info-available.md index d86fae4a..ccfb6e3d 100644 --- a/captain-hook/docs/hooks/CwdChanged-info-available.md +++ b/captain-hook/docs/hooks/CwdChanged-info-available.md @@ -56,7 +56,7 @@ hooks: OLD=$(echo "$INPUT" | jq -r '.old_cwd') NEW=$(echo "$INPUT" | jq -r '.new_cwd') echo "$(date): $OLD -> $NEW" >> /tmp/cwd_history.log - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/Elicitation-info-available.md b/captain-hook/docs/hooks/Elicitation-info-available.md index 789e183d..621fd627 100644 --- a/captain-hook/docs/hooks/Elicitation-info-available.md +++ b/captain-hook/docs/hooks/Elicitation-info-available.md @@ -66,7 +66,7 @@ hooks: echo "Blocked elicitation from $SERVER" >&2 exit 2 fi - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/ElicitationResult-info-available.md b/captain-hook/docs/hooks/ElicitationResult-info-available.md index b1f07541..2d55dbd7 100644 --- a/captain-hook/docs/hooks/ElicitationResult-info-available.md +++ b/captain-hook/docs/hooks/ElicitationResult-info-available.md @@ -61,7 +61,7 @@ hooks: INPUT=$(cat) SERVER=$(echo "$INPUT" | jq -r '.mcp_server') echo "User responded to $SERVER" >> /tmp/elicitations.log - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/FileChanged-info-available.md b/captain-hook/docs/hooks/FileChanged-info-available.md index b54885a3..0d19e149 100644 --- a/captain-hook/docs/hooks/FileChanged-info-available.md +++ b/captain-hook/docs/hooks/FileChanged-info-available.md @@ -55,7 +55,7 @@ hooks: INPUT=$(cat) FILE=$(echo "$INPUT" | jq -r '.file_path') echo "External change: $FILE" >> /tmp/file_changes.log - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/InstructionsLoaded-info-available.md b/captain-hook/docs/hooks/InstructionsLoaded-info-available.md index 83a4d8b5..ea13e1c6 100644 --- a/captain-hook/docs/hooks/InstructionsLoaded-info-available.md +++ b/captain-hook/docs/hooks/InstructionsLoaded-info-available.md @@ -63,7 +63,7 @@ hooks: INPUT=$(cat) FILE=$(echo "$INPUT" | jq -r '.file_path') echo "Loaded instructions: $FILE" >> /tmp/instructions.log - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/Notification-info-available.md b/captain-hook/docs/hooks/Notification-info-available.md index 496733d3..2473609b 100644 --- a/captain-hook/docs/hooks/Notification-info-available.md +++ b/captain-hook/docs/hooks/Notification-info-available.md @@ -71,7 +71,7 @@ hooks: SESSION=$(echo "$INPUT" | jq -r '.session_id') TYPE=$(echo "$INPUT" | jq -r '.notification_type') echo "[$(date)] [$SESSION] $TYPE" >> /tmp/claude-notifications.log - timeout: 2000 + timeout: 2 ``` ### Custom macOS Notifications @@ -93,7 +93,7 @@ hooks: osascript -e 'display notification "Permission needed" with title "Claude Code" sound name "Ping"' ;; esac - timeout: 3000 + timeout: 3 ``` ### Sound Alerts @@ -114,7 +114,7 @@ hooks: afplay /System/Library/Sounds/Ping.aiff & ;; esac - timeout: 2000 + timeout: 2 ``` ### Slack/Discord Integration @@ -133,7 +133,7 @@ hooks: -d "{\"text\": \"Claude Code needs permission (session: $SESSION)\"}" \ > /dev/null 2>&1 & fi - timeout: 3000 + timeout: 3 ``` ### Terminal Bell @@ -148,7 +148,7 @@ hooks: # Ring terminal bell printf '\a' fi - timeout: 1000 + timeout: 1 ``` ### Status Tracking @@ -168,7 +168,7 @@ hooks: karma radio set-status waiting --message "Awaiting permission" ;; esac - timeout: 3000 + timeout: 3 ``` ### Track Idle Time @@ -184,7 +184,7 @@ hooks: IDLE_FILE="/tmp/claude-idle-$SESSION" echo "$(date +%s)" > "$IDLE_FILE" fi - timeout: 1000 + timeout: 1 ``` ### Focus Window (macOS) @@ -199,7 +199,7 @@ hooks: # Bring Terminal to front for permissions osascript -e 'tell application "Terminal" to activate' fi - timeout: 2000 + timeout: 2 ``` ### Email Alert for Long Waits @@ -231,7 +231,7 @@ hooks: rm -f "$WAIT_FILE" fi fi - timeout: 5000 + timeout: 5 ``` ### Desktop Notification with Icon @@ -251,7 +251,7 @@ hooks: terminal-notifier -title "Claude Code" -message "Permission required" -sound Ping 2>/dev/null || true ;; esac - timeout: 3000 + timeout: 3 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/PermissionDenied-info-available.md b/captain-hook/docs/hooks/PermissionDenied-info-available.md index df318d5b..e2633f38 100644 --- a/captain-hook/docs/hooks/PermissionDenied-info-available.md +++ b/captain-hook/docs/hooks/PermissionDenied-info-available.md @@ -73,7 +73,7 @@ hooks: REASON=$(echo "$INPUT" | jq -r '.reason') TOOL=$(echo "$INPUT" | jq -r '.tool_name') echo "Denied $TOOL: $REASON" >> /tmp/denied.log - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/PermissionRequest-info-available.md b/captain-hook/docs/hooks/PermissionRequest-info-available.md index 638314e4..729ec91e 100644 --- a/captain-hook/docs/hooks/PermissionRequest-info-available.md +++ b/captain-hook/docs/hooks/PermissionRequest-info-available.md @@ -89,7 +89,7 @@ hooks: SESSION=$(echo "$INPUT" | jq -r '.session_id') MESSAGE=$(echo "$INPUT" | jq -r '.message') echo "[$(date)] Permission requested: $MESSAGE" >> /tmp/permissions.log - timeout: 2000 + timeout: 2 ``` ### Auto-Allow Safe Commands @@ -107,7 +107,7 @@ hooks: echo '{"hookSpecificOutput": {"permissionDecision": "allow"}}' fi # If no output, shows normal dialog - timeout: 2000 + timeout: 2 ``` ### Block Dangerous Operations @@ -122,7 +122,7 @@ hooks: if echo "$MESSAGE" | grep -qE 'rm -rf|sudo|chmod 777|curl.*\|.*sh'; then echo '{"hookSpecificOutput": {"permissionDecision": "deny", "reason": "Blocked by security policy"}}' fi - timeout: 2000 + timeout: 2 ``` ### Project-Specific Allow List @@ -143,7 +143,7 @@ hooks: fi done < "$ALLOW_FILE" fi - timeout: 3000 + timeout: 3 ``` ### Time-Based Permissions @@ -162,7 +162,7 @@ hooks: echo '{"hookSpecificOutput": {"permissionDecision": "allow"}}' fi fi - timeout: 2000 + timeout: 2 ``` ### Prompt-Based Decision (LLM) @@ -196,7 +196,7 @@ hooks: osascript -e "display notification \"Blocked: $MESSAGE\" with title \"Claude Code Security\"" echo '{"hookSpecificOutput": {"permissionDecision": "deny", "reason": "Destructive operations require manual approval"}}' fi - timeout: 3000 + timeout: 3 ``` ### Auto-Allow in CI/Automation @@ -208,7 +208,7 @@ hooks: if [ -n "$CI" ] || [ -n "$GITHUB_ACTIONS" ]; then echo '{"hookSpecificOutput": {"permissionDecision": "allow"}}' fi - timeout: 1000 + timeout: 1 ``` ### File Operation Permissions @@ -228,7 +228,7 @@ hooks: if echo "$MESSAGE" | grep -qE 'Write.*/(\.|config|env|secret)'; then echo '{"hookSpecificOutput": {"permissionDecision": "deny", "reason": "Cannot write to sensitive files"}}' fi - timeout: 2000 + timeout: 2 ``` ### Rate Limiting @@ -249,7 +249,7 @@ hooks: echo "[$(date)] Permission limit reached" >> /tmp/permissions.log # Don't auto-allow anymore - let user decide fi - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/PostToolUse-info-available.md b/captain-hook/docs/hooks/PostToolUse-info-available.md index bb0aca2d..6cdb36ea 100644 --- a/captain-hook/docs/hooks/PostToolUse-info-available.md +++ b/captain-hook/docs/hooks/PostToolUse-info-available.md @@ -162,7 +162,7 @@ hooks: - command: | INPUT=$(cat) echo "$INPUT" >> /tmp/claude-tools.jsonl - timeout: 2000 + timeout: 2 ``` ### Track File Changes @@ -176,7 +176,7 @@ hooks: RESULT=$(echo "$INPUT" | jq -r '.tool_response' | head -c 100) echo "[$(date)] $TOOL: $FILE -> $RESULT" >> /tmp/file-changes.log match_tools: ["Write", "Edit"] - timeout: 2000 + timeout: 2 ``` ### Error Detection & Notification @@ -190,7 +190,7 @@ hooks: TOOL=$(echo "$INPUT" | jq -r '.tool_name') osascript -e "display notification \"$TOOL failed\" with title \"Claude Code\"" fi - timeout: 3000 + timeout: 3 ``` ### Build Result Feedback @@ -209,7 +209,7 @@ hooks: fi fi match_tools: ["Bash"] - timeout: 5000 + timeout: 5 ``` ### Status Reporting (Karma Radio) @@ -221,7 +221,7 @@ hooks: export KARMA_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id') TOOL=$(echo "$INPUT" | jq -r '.tool_name') karma radio report-progress --message "Completed $TOOL" - timeout: 5000 + timeout: 5 ``` ### MCP Call Analytics @@ -235,7 +235,7 @@ hooks: SERVER=$(echo "$TOOL" | cut -d'_' -f3) echo "[$(date)] MCP call to $SERVER" >> /tmp/mcp-usage.log fi - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/PreCompact-info-available.md b/captain-hook/docs/hooks/PreCompact-info-available.md index ce7c2400..a34f0c25 100644 --- a/captain-hook/docs/hooks/PreCompact-info-available.md +++ b/captain-hook/docs/hooks/PreCompact-info-available.md @@ -93,7 +93,7 @@ hooks: SESSION=$(echo "$INPUT" | jq -r '.session_id') TRIGGER=$(echo "$INPUT" | jq -r '.trigger') echo "[$(date)] Compaction triggered ($TRIGGER) for session $SESSION" >> /tmp/compaction.log - timeout: 2000 + timeout: 2 ``` ### Backup Transcript Before Compaction @@ -111,7 +111,7 @@ hooks: cp "$TRANSCRIPT" "$BACKUP_DIR/pre-compact-$SESSION-$(date +%Y%m%d%H%M%S).jsonl" echo "Transcript backed up before compaction" fi - timeout: 10000 + timeout: 10 ``` ### Extract Key Information @@ -137,7 +137,7 @@ hooks: echo "$FILES" | sed 's/"file_path":"//g' | sed 's/"//g' | sed 's/^/ - /' fi fi - timeout: 10000 + timeout: 10 ``` ### Conditional by Trigger @@ -161,7 +161,7 @@ hooks: fi ;; esac - timeout: 3000 + timeout: 3 ``` ### Preserve Decision Log @@ -182,7 +182,7 @@ hooks: # This output goes to Claude's context echo "Note: Key decisions saved to $DECISIONS_FILE" echo "Review this file if context about earlier decisions is needed." - timeout: 5000 + timeout: 5 ``` ### Calculate Session Statistics @@ -202,7 +202,7 @@ hooks: echo " Lines: $LINES" >> /tmp/session-stats.log echo " Size: $SIZE" >> /tmp/session-stats.log fi - timeout: 3000 + timeout: 3 ``` ### Status Update @@ -213,7 +213,7 @@ hooks: INPUT=$(cat) export KARMA_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id') karma radio report-progress --message "Context compacting..." - timeout: 3000 + timeout: 3 ``` ### Notify on Auto-Compaction @@ -228,7 +228,7 @@ hooks: # macOS notification osascript -e 'display notification "Context being compacted - long session" with title "Claude Code"' fi - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/PreToolUse-info-available.md b/captain-hook/docs/hooks/PreToolUse-info-available.md index 99beddc9..e3f2458c 100644 --- a/captain-hook/docs/hooks/PreToolUse-info-available.md +++ b/captain-hook/docs/hooks/PreToolUse-info-available.md @@ -207,7 +207,7 @@ hooks: INPUT=$(cat) TOOL=$(echo "$INPUT" | jq -r '.tool_name') echo "Tool: $TOOL" >> /tmp/hooks.log - timeout: 5000 + timeout: 5 ``` ### Filter by Tool Name (using matcher) @@ -218,7 +218,7 @@ hooks: hooks: - type: "command" command: "./scripts/validate-write.sh" - timeout: 3000 + timeout: 3 ``` ### Block Dangerous Commands @@ -235,7 +235,7 @@ hooks: echo "Dangerous command blocked" >&2 exit 2 fi - timeout: 1000 + timeout: 1 ``` ### MCP Tool Matching @@ -246,7 +246,7 @@ hooks: hooks: - type: "command" command: "./scripts/log-mcp.sh" - timeout: 2000 + timeout: 2 ``` ### Prompt-Based Hook (LLM) diff --git a/captain-hook/docs/hooks/SessionEnd-info-available.md b/captain-hook/docs/hooks/SessionEnd-info-available.md index 20fecfdd..eb9a39b6 100644 --- a/captain-hook/docs/hooks/SessionEnd-info-available.md +++ b/captain-hook/docs/hooks/SessionEnd-info-available.md @@ -86,7 +86,7 @@ hooks: echo " Reason: $REASON" >> /tmp/claude-sessions.log echo " Transcript: $TRANSCRIPT" >> /tmp/claude-sessions.log echo "" >> /tmp/claude-sessions.log - timeout: 5000 + timeout: 5 ``` ### Status Tracking (Karma Radio) @@ -98,7 +98,7 @@ hooks: export KARMA_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id') REASON=$(echo "$INPUT" | jq -r '.reason') karma radio set-status completed --message "Session ended: $REASON" - timeout: 5000 + timeout: 5 ``` ### Cleanup Temporary Files @@ -112,7 +112,7 @@ hooks: # Clean up session-specific temp files rm -f "/tmp/claude-$SESSION-"* 2>/dev/null rm -f "/tmp/hooks-$SESSION.log" 2>/dev/null - timeout: 3000 + timeout: 3 ``` ### Archive Transcript @@ -129,7 +129,7 @@ hooks: mkdir -p "$ARCHIVE_DIR" cp "$TRANSCRIPT" "$ARCHIVE_DIR/session-$SESSION-$(date +%Y%m%d).jsonl" fi - timeout: 10000 + timeout: 10 ``` ### Calculate Session Statistics @@ -149,7 +149,7 @@ hooks: echo " Messages: $MESSAGES" >> ~/.claude-stats.log echo " Tool calls: $TOOLS" >> ~/.claude-stats.log fi - timeout: 5000 + timeout: 5 ``` ### Notify on Exit @@ -162,7 +162,7 @@ hooks: # macOS notification osascript -e "display notification \"Session ended: $REASON\" with title \"Claude Code\"" - timeout: 3000 + timeout: 3 ``` ### Conditional Cleanup by Reason @@ -190,7 +190,7 @@ hooks: echo "[WARN] Unexpected session termination" >> /tmp/claude-errors.log ;; esac - timeout: 5000 + timeout: 5 ``` ### Git Status Snapshot @@ -207,7 +207,7 @@ hooks: git status --short > ~/.claude-git-snapshots/"$SESSION-end.txt" git log -1 --format="%H %s" >> ~/.claude-git-snapshots/"$SESSION-end.txt" fi - timeout: 5000 + timeout: 5 ``` ### Send Analytics @@ -224,7 +224,7 @@ hooks: -H "Content-Type: application/json" \ -d "{\"session\": \"$SESSION\", \"reason\": \"$REASON\", \"ended\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" \ > /dev/null 2>&1 & - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/SessionStart-info-available.md b/captain-hook/docs/hooks/SessionStart-info-available.md index 3a3e63f1..36f3a38b 100644 --- a/captain-hook/docs/hooks/SessionStart-info-available.md +++ b/captain-hook/docs/hooks/SessionStart-info-available.md @@ -112,7 +112,7 @@ hooks: echo "Directory: $(pwd)" echo "Time: $(date)" echo "" - timeout: 5000 + timeout: 5 ``` ### Git Context @@ -127,7 +127,7 @@ hooks: echo "- Status: $(git status --short | wc -l | tr -d ' ') changed files" echo "" fi - timeout: 5000 + timeout: 5 ``` ### Node.js Project Setup @@ -147,7 +147,7 @@ hooks: echo "NODE_ENV=development" >> "$CLAUDE_ENV_FILE" fi fi - timeout: 5000 + timeout: 5 ``` ### NVM Version Switching @@ -175,7 +175,7 @@ hooks: echo "Using Node $(node -v) from .nvmrc" fi - timeout: 10000 + timeout: 10 ``` ### Load Recent Issues @@ -186,7 +186,7 @@ hooks: echo "Recent GitHub Issues:" gh issue list --limit 5 --state open 2>/dev/null || echo "GitHub CLI not available" echo "" - timeout: 15000 + timeout: 15 ``` ### Status Tracking (Karma Radio) @@ -198,7 +198,7 @@ hooks: export KARMA_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id') export KARMA_AGENT_ID=$(echo "$INPUT" | jq -r '.session_id') karma radio set-status pending --message "Session started" - timeout: 5000 + timeout: 5 ``` ### Conditional by Source @@ -225,7 +225,7 @@ hooks: echo "Context compacted - preserving key info..." ;; esac - timeout: 5000 + timeout: 5 ``` ### Load Project-Specific Config @@ -240,7 +240,7 @@ hooks: echo "$CONFIG" | jq -r 'to_entries | .[] | "- \(.key): \(.value)"' echo "" fi - timeout: 3000 + timeout: 3 ``` ### Set Up Virtual Environment (Python) @@ -257,7 +257,7 @@ hooks: fi fi fi - timeout: 5000 + timeout: 5 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/Stop-info-available.md b/captain-hook/docs/hooks/Stop-info-available.md index f6e56bed..8d4c6288 100644 --- a/captain-hook/docs/hooks/Stop-info-available.md +++ b/captain-hook/docs/hooks/Stop-info-available.md @@ -88,7 +88,7 @@ hooks: INPUT=$(cat) SESSION=$(echo "$INPUT" | jq -r '.session_id') echo "[$(date)] Agent stopped: $SESSION" >> /tmp/claude-stops.log - timeout: 2000 + timeout: 2 ``` ### Continue Until Tests Pass @@ -105,7 +105,7 @@ hooks: echo '{"hookSpecificOutput": {"decision": "continue", "reason": "Tests are failing - please fix them"}}' fi fi - timeout: 30000 + timeout: 30 ``` ### Continue Until Build Succeeds @@ -121,7 +121,7 @@ hooks: echo '{"hookSpecificOutput": {"decision": "continue", "reason": "Build is failing - please fix compilation errors"}}' fi fi - timeout: 60000 + timeout: 60 ``` ### Status Tracking (Karma Radio) @@ -132,7 +132,7 @@ hooks: INPUT=$(cat) export KARMA_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id') karma radio set-status completed --message "Session completed" - timeout: 5000 + timeout: 5 ``` ### Continue if TODO Items Remain @@ -152,7 +152,7 @@ hooks: echo "{\"hookSpecificOutput\": {\"decision\": \"continue\", \"reason\": \"$PENDING TODO items still pending\"}}" fi fi - timeout: 5000 + timeout: 5 ``` ### Prompt-Based Continue Decision (LLM) @@ -182,7 +182,7 @@ hooks: - command: | # macOS notification when Claude finishes osascript -e 'display notification "Claude finished working" with title "Claude Code"' - timeout: 2000 + timeout: 2 ``` ### Check Lint Before Stopping @@ -200,7 +200,7 @@ hooks: echo "{\"hookSpecificOutput\": {\"decision\": \"continue\", \"reason\": \"Found $LINT_ERRORS lint errors - please fix them\"}}" fi fi - timeout: 30000 + timeout: 30 ``` ### Time-Limited Continue @@ -223,7 +223,7 @@ hooks: echo '{"hookSpecificOutput": {"decision": "continue", "reason": "Continue marker present"}}' fi fi - timeout: 5000 + timeout: 5 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/SubagentStop-info-available.md b/captain-hook/docs/hooks/SubagentStop-info-available.md index b978d1ad..0e06dea5 100644 --- a/captain-hook/docs/hooks/SubagentStop-info-available.md +++ b/captain-hook/docs/hooks/SubagentStop-info-available.md @@ -80,7 +80,7 @@ hooks: INPUT=$(cat) SESSION=$(echo "$INPUT" | jq -r '.session_id') echo "[$(date)] Subagent stopped: $SESSION" >> /tmp/subagent-stops.log - timeout: 2000 + timeout: 2 ``` ### Continue Until Exploration Complete @@ -102,7 +102,7 @@ hooks: fi fi fi - timeout: 10000 + timeout: 10 ``` ### Status Tracking @@ -113,7 +113,7 @@ hooks: INPUT=$(cat) export KARMA_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id') karma radio report-progress --message "Subagent completed" - timeout: 3000 + timeout: 3 ``` ### Prompt-Based Evaluation (LLM) @@ -155,7 +155,7 @@ hooks: # Your continue condition here : fi - timeout: 3000 + timeout: 3 ``` ### Different Behavior by Subagent Type @@ -177,7 +177,7 @@ hooks: echo '{"hookSpecificOutput": {"decision": "continue", "reason": "Ensure exploration is comprehensive"}}' fi fi - timeout: 5000 + timeout: 5 ``` ### Quality Check Before Returning @@ -200,7 +200,7 @@ hooks: fi fi fi - timeout: 5000 + timeout: 5 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/TaskCompleted-info-available.md b/captain-hook/docs/hooks/TaskCompleted-info-available.md index 8359e542..d7d0038a 100644 --- a/captain-hook/docs/hooks/TaskCompleted-info-available.md +++ b/captain-hook/docs/hooks/TaskCompleted-info-available.md @@ -68,7 +68,7 @@ Exit code 0, no output. hooks: TaskCompleted: - command: ./scripts/verify-task-done.sh - timeout: 5000 + timeout: 5 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/TaskCreated-info-available.md b/captain-hook/docs/hooks/TaskCreated-info-available.md index ca04053e..ce90887c 100644 --- a/captain-hook/docs/hooks/TaskCreated-info-available.md +++ b/captain-hook/docs/hooks/TaskCreated-info-available.md @@ -68,7 +68,7 @@ Exit code 0, no output. hooks: TaskCreated: - command: ./scripts/audit-task-created.sh - timeout: 3000 + timeout: 3 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/TeammateIdle-info-available.md b/captain-hook/docs/hooks/TeammateIdle-info-available.md index 13075e6b..90a21e1e 100644 --- a/captain-hook/docs/hooks/TeammateIdle-info-available.md +++ b/captain-hook/docs/hooks/TeammateIdle-info-available.md @@ -59,7 +59,7 @@ Exit code 2 with stderr to keep the agent active (e.g., to dispatch new work). hooks: TeammateIdle: - command: ./scripts/maybe-dispatch-task.sh - timeout: 5000 + timeout: 5 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/UserPromptSubmit-info-available.md b/captain-hook/docs/hooks/UserPromptSubmit-info-available.md index 596e6cbb..b6930b4f 100644 --- a/captain-hook/docs/hooks/UserPromptSubmit-info-available.md +++ b/captain-hook/docs/hooks/UserPromptSubmit-info-available.md @@ -120,7 +120,7 @@ hooks: echo "" echo "Recent commits:" git log --oneline -3 2>/dev/null || true - timeout: 5000 + timeout: 5 ``` ### Add Project Context @@ -132,7 +132,7 @@ hooks: echo "Node project: $(jq -r '.name' package.json)" echo "Scripts: $(jq -r '.scripts | keys | join(", ")' package.json)" fi - timeout: 3000 + timeout: 3 ``` ### Block Specific Keywords @@ -148,7 +148,7 @@ hooks: echo "Dangerous operation blocked for safety" >&2 exit 2 fi - timeout: 2000 + timeout: 2 ``` ### Log All Prompts @@ -160,7 +160,7 @@ hooks: SESSION=$(echo "$INPUT" | jq -r '.session_id') PROMPT=$(echo "$INPUT" | jq -r '.prompt') echo "[$(date)] [$SESSION] $PROMPT" >> /tmp/claude-prompts.log - timeout: 1000 + timeout: 1 ``` ### Add Issue Context @@ -177,7 +177,7 @@ hooks: echo "Issue #$ISSUE context:" gh issue view "$ISSUE" --json title,body,state 2>/dev/null || true fi - timeout: 10000 + timeout: 10 ``` ### Prompt-Based Validation (LLM) @@ -207,7 +207,7 @@ hooks: echo "- Time: $(date '+%Y-%m-%d %H:%M:%S %Z')" echo "- Working directory: $(pwd)" echo "- User: $(whoami)" - timeout: 1000 + timeout: 1 ``` ### Inject Custom Instructions @@ -225,7 +225,7 @@ hooks: echo "- Add tests for new functions" echo "- Update CHANGELOG.md for user-facing changes" fi - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/WorktreeCreate-info-available.md b/captain-hook/docs/hooks/WorktreeCreate-info-available.md index 0e7eeb61..ebb774c5 100644 --- a/captain-hook/docs/hooks/WorktreeCreate-info-available.md +++ b/captain-hook/docs/hooks/WorktreeCreate-info-available.md @@ -64,7 +64,7 @@ hooks: WorktreeCreate: - type: "http" url: "https://hooks.example.com/worktree" - timeout: 5000 + timeout: 5 ``` ## Use Cases diff --git a/captain-hook/docs/hooks/WorktreeRemove-info-available.md b/captain-hook/docs/hooks/WorktreeRemove-info-available.md index a66622c3..4d48b02a 100644 --- a/captain-hook/docs/hooks/WorktreeRemove-info-available.md +++ b/captain-hook/docs/hooks/WorktreeRemove-info-available.md @@ -53,7 +53,7 @@ hooks: INPUT=$(cat) PATH_=$(echo "$INPUT" | jq -r '.worktree_path') echo "$(date): Removed $PATH_" >> /tmp/worktree_removals.log - timeout: 2000 + timeout: 2 ``` ## Use Cases diff --git a/docs/about/hooks-guide.md b/docs/about/hooks-guide.md index e4ecd909..5b90f13d 100644 --- a/docs/about/hooks-guide.md +++ b/docs/about/hooks-guide.md @@ -138,7 +138,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -149,7 +149,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -160,7 +160,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -171,7 +171,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -182,7 +182,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -193,7 +193,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -204,7 +204,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] } @@ -215,7 +215,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/live_session_tracker.py", - "timeout": 5000 + "timeout": 5 } ] }, @@ -224,7 +224,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/session_title_generator.py", - "timeout": 15000 + "timeout": 15 } ] } @@ -235,7 +235,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js { "type": "command", "command": "python3 ~/.claude/hooks/plan_approval.py", - "timeout": 10000 + "timeout": 10 } ] } @@ -244,7 +244,7 @@ Add hook registrations to your Claude Code settings file (`~/.claude/settings.js } ``` -The `timeout` value is in milliseconds. If a hook exceeds its timeout, Claude Code kills the process and continues without it. +The `timeout` value is in **seconds**, not milliseconds (`5` = 5 seconds; `5000` would be 83 minutes). If a hook exceeds its timeout, Claude Code kills the process and continues without it. --- diff --git a/docs/feature/hooks-page/plan.md b/docs/feature/hooks-page/plan.md index 9c88e93e..35ec15ca 100644 --- a/docs/feature/hooks-page/plan.md +++ b/docs/feature/hooks-page/plan.md @@ -64,7 +64,7 @@ Hooks are defined in JSON settings files and merged from multiple sources: { "type": "command", "command": "node script.js", - "timeout": 5000 + "timeout": 5 } ], "description": "Optional description" @@ -79,7 +79,7 @@ Hooks are defined in JSON settings files and merged from multiple sources: - `matcher`: Filter pattern — `*` for all, tool name, or regex on tool input - `type`: Always `"command"` for executable hooks - `command`: Shell command to execute (plugins use `${CLAUDE_PLUGIN_ROOT}` variable) -- `timeout`: Max execution time in milliseconds +- `timeout`: Max execution time in **seconds** (Claude Code's schema — not milliseconds, despite the field naming below) - `description`: Optional human-readable description ### Hook Event Types (11 total) @@ -156,7 +156,7 @@ HookRegistration │ ├── command: str # Full command string │ ├── script_path: str # Resolved path to script file │ ├── script_language: enum # "python" | "node" | "shell" | "unknown" -│ ├── timeout_ms: int # Timeout in milliseconds +│ ├── timeout_ms: int # NOTE: misnamed -- holds raw seconds from settings.json, never multiplied; rename to timeout_seconds │ └── can_block: bool # Derived from event_type │ └── Metadata diff --git a/frontend/src/lib/api-types.ts b/frontend/src/lib/api-types.ts index aca3a81e..356f9361 100644 --- a/frontend/src/lib/api-types.ts +++ b/frontend/src/lib/api-types.ts @@ -1660,7 +1660,7 @@ export interface HookRegistration { command: string; script_filename?: string | null; script_language: string; - timeout_ms?: number | null; + timeout_seconds?: number | null; can_block: boolean; } diff --git a/frontend/src/routes/hooks/[event_type]/+page.svelte b/frontend/src/routes/hooks/[event_type]/+page.svelte index ddcf35de..898de8ec 100644 --- a/frontend/src/routes/hooks/[event_type]/+page.svelte +++ b/frontend/src/routes/hooks/[event_type]/+page.svelte @@ -160,13 +160,13 @@ > {/if} - {#if registration.timeout_ms} + {#if registration.timeout_seconds}