diff --git a/hooks/block-interactive.sh b/hooks/block-interactive.sh index d45b2cd..d071523 100644 --- a/hooks/block-interactive.sh +++ b/hooks/block-interactive.sh @@ -1,17 +1,17 @@ -#!/usr/bin/env bash -# block-interactive.sh — Blocks AskUserQuestion in unattended sessions -# -# PreToolUse hook: exits 2 to block, 0 to allow. -# When Claude tries to ask a question, this forces it to decide instead. -# -# Copyright 2026 Stackbilt LLC — Apache 2.0 - -INPUT=$(cat) -TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) - -if [[ "$TOOL" == "AskUserQuestion" ]]; then - echo "BLOCKED: Autonomous mode — do not ask questions. Make a reasonable decision and document your reasoning." >&2 - exit 2 -fi - -exit 0 +#!/usr/bin/env bash +# block-interactive.sh — Blocks AskUserQuestion in unattended sessions +# +# PreToolUse hook: exits 2 to block, 0 to allow. +# When Claude tries to ask a question, this forces it to decide instead. +# +# Copyright 2026 Stackbilt LLC — Apache 2.0 + +INPUT=$(cat) +TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) + +if [[ "$TOOL" == "AskUserQuestion" ]]; then + echo "BLOCKED: Autonomous mode — do not ask questions. Make a reasonable decision and document your reasoning." >&2 + exit 2 +fi + +exit 0 diff --git a/hooks/safety-gate.sh b/hooks/safety-gate.sh index 05abffb..eec3417 100644 --- a/hooks/safety-gate.sh +++ b/hooks/safety-gate.sh @@ -1,48 +1,48 @@ -#!/usr/bin/env bash -# safety-gate.sh — Blocks destructive commands in unattended sessions -# -# PreToolUse hook for Bash tool: checks command for dangerous patterns. -# Blocks: rm -rf, git push --force, DROP TABLE, deploys, secret access. -# -# Copyright 2026 Stackbilt LLC — Apache 2.0 - -INPUT=$(cat) -TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) - -if [[ "$TOOL" != "Bash" ]]; then - exit 0 -fi - -CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) - -# Destructive filesystem operations -if echo "$CMD" | grep -qiE '(rm\s+-rf|rm\s+-r\s+/|>\s*/dev/)'; then - echo "BLOCKED: Destructive filesystem operation not allowed in autonomous mode" >&2 - exit 2 -fi - -# Destructive git operations -if echo "$CMD" | grep -qiE '(git\s+reset\s+--hard|git\s+push\s+--force|git\s+push\s+-f|git\s+clean\s+-f)'; then - echo "BLOCKED: Destructive git operation not allowed in autonomous mode" >&2 - exit 2 -fi - -# Database destruction -if echo "$CMD" | grep -qiE '(DROP\s+TABLE|TRUNCATE\s+TABLE|DELETE\s+FROM\s+\w+\s*$)'; then - echo "BLOCKED: Destructive database operation not allowed in autonomous mode" >&2 - exit 2 -fi - -# Production deploys (require human approval) -if echo "$CMD" | grep -qiE '(wrangler\s+deploy|wrangler\s+publish|npm\s+run\s+deploy|kubectl\s+apply|terraform\s+apply)'; then - echo "BLOCKED: Production deploys require human approval. Commit your work and stop." >&2 - exit 2 -fi - -# Secret management -if echo "$CMD" | grep -qiE '(wrangler\s+secret|echo\s+.*API_KEY|echo\s+.*TOKEN|echo\s+.*SECRET)'; then - echo "BLOCKED: Secret management not allowed in autonomous mode" >&2 - exit 2 -fi - -exit 0 +#!/usr/bin/env bash +# safety-gate.sh — Blocks destructive commands in unattended sessions +# +# PreToolUse hook for Bash tool: checks command for dangerous patterns. +# Blocks: rm -rf, git push --force, DROP TABLE, deploys, secret access. +# +# Copyright 2026 Stackbilt LLC — Apache 2.0 + +INPUT=$(cat) +TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) + +if [[ "$TOOL" != "Bash" ]]; then + exit 0 +fi + +CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) + +# Destructive filesystem operations +if echo "$CMD" | grep -qiE '(rm\s+-rf|rm\s+-r\s+/|>\s*/dev/)'; then + echo "BLOCKED: Destructive filesystem operation not allowed in autonomous mode" >&2 + exit 2 +fi + +# Destructive git operations +if echo "$CMD" | grep -qiE '(git\s+reset\s+--hard|git\s+push\s+--force|git\s+push\s+-f|git\s+clean\s+-f)'; then + echo "BLOCKED: Destructive git operation not allowed in autonomous mode" >&2 + exit 2 +fi + +# Database destruction +if echo "$CMD" | grep -qiE '(DROP\s+TABLE|TRUNCATE\s+TABLE|DELETE\s+FROM\s+\w+\s*$)'; then + echo "BLOCKED: Destructive database operation not allowed in autonomous mode" >&2 + exit 2 +fi + +# Production deploys (require human approval) +if echo "$CMD" | grep -qiE '(wrangler\s+deploy|wrangler\s+publish|npm\s+run\s+deploy|kubectl\s+apply|terraform\s+apply)'; then + echo "BLOCKED: Production deploys require human approval. Commit your work and stop." >&2 + exit 2 +fi + +# Secret management +if echo "$CMD" | grep -qiE '(wrangler\s+secret|echo\s+.*API_KEY|echo\s+.*TOKEN|echo\s+.*SECRET)'; then + echo "BLOCKED: Secret management not allowed in autonomous mode" >&2 + exit 2 +fi + +exit 0 diff --git a/hooks/syntax-check.sh b/hooks/syntax-check.sh index f5c023d..3df35bd 100644 --- a/hooks/syntax-check.sh +++ b/hooks/syntax-check.sh @@ -1,42 +1,42 @@ -#!/usr/bin/env bash -# syntax-check.sh — PostToolUse hook for Edit/Write -# -# After editing TypeScript/JavaScript files, runs a quick syntax check -# so errors are caught immediately rather than 50 tool calls later. -# -# Copyright 2026 Stackbilt LLC — Apache 2.0 - -INPUT=$(cat) -TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) - -if [[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]]; then - exit 0 -fi - -FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null) - -# Only check TypeScript/JavaScript files -case "$FILE" in - *.ts|*.tsx|*.js|*.jsx) - # Find nearest tsconfig - DIR=$(dirname "$FILE") - TSCONFIG="" - while [[ "$DIR" != "/" && "$DIR" != "." ]]; do - if [[ -f "${DIR}/tsconfig.json" ]]; then - TSCONFIG="${DIR}/tsconfig.json" - break - fi - DIR=$(dirname "$DIR") - done - - if [[ -n "$TSCONFIG" ]]; then - ERRORS=$(cd "$(dirname "$TSCONFIG")" && npx tsc --noEmit --pretty false 2>&1 | grep -c "error TS" || true) - if [[ "$ERRORS" -gt 0 ]]; then - echo "WARNING: ${ERRORS} TypeScript error(s) detected after editing ${FILE}. Run typecheck to see details." >&2 - fi - fi - ;; -esac - -# Never block — advisory only -exit 0 +#!/usr/bin/env bash +# syntax-check.sh — PostToolUse hook for Edit/Write +# +# After editing TypeScript/JavaScript files, runs a quick syntax check +# so errors are caught immediately rather than 50 tool calls later. +# +# Copyright 2026 Stackbilt LLC — Apache 2.0 + +INPUT=$(cat) +TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) + +if [[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]]; then + exit 0 +fi + +FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null) + +# Only check TypeScript/JavaScript files +case "$FILE" in + *.ts|*.tsx|*.js|*.jsx) + # Find nearest tsconfig + DIR=$(dirname "$FILE") + TSCONFIG="" + while [[ "$DIR" != "/" && "$DIR" != "." ]]; do + if [[ -f "${DIR}/tsconfig.json" ]]; then + TSCONFIG="${DIR}/tsconfig.json" + break + fi + DIR=$(dirname "$DIR") + done + + if [[ -n "$TSCONFIG" ]]; then + ERRORS=$(cd "$(dirname "$TSCONFIG")" && npx tsc --noEmit --pretty false 2>&1 | grep -c "error TS" || true) + if [[ "$ERRORS" -gt 0 ]]; then + echo "WARNING: ${ERRORS} TypeScript error(s) detected after editing ${FILE}. Run typecheck to see details." >&2 + fi + fi + ;; +esac + +# Never block — advisory only +exit 0 diff --git a/plugin/safety/block-interactive.sh b/plugin/safety/block-interactive.sh index d45b2cd..d071523 100644 --- a/plugin/safety/block-interactive.sh +++ b/plugin/safety/block-interactive.sh @@ -1,17 +1,17 @@ -#!/usr/bin/env bash -# block-interactive.sh — Blocks AskUserQuestion in unattended sessions -# -# PreToolUse hook: exits 2 to block, 0 to allow. -# When Claude tries to ask a question, this forces it to decide instead. -# -# Copyright 2026 Stackbilt LLC — Apache 2.0 - -INPUT=$(cat) -TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) - -if [[ "$TOOL" == "AskUserQuestion" ]]; then - echo "BLOCKED: Autonomous mode — do not ask questions. Make a reasonable decision and document your reasoning." >&2 - exit 2 -fi - -exit 0 +#!/usr/bin/env bash +# block-interactive.sh — Blocks AskUserQuestion in unattended sessions +# +# PreToolUse hook: exits 2 to block, 0 to allow. +# When Claude tries to ask a question, this forces it to decide instead. +# +# Copyright 2026 Stackbilt LLC — Apache 2.0 + +INPUT=$(cat) +TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) + +if [[ "$TOOL" == "AskUserQuestion" ]]; then + echo "BLOCKED: Autonomous mode — do not ask questions. Make a reasonable decision and document your reasoning." >&2 + exit 2 +fi + +exit 0 diff --git a/plugin/safety/safety-gate.sh b/plugin/safety/safety-gate.sh index 05abffb..eec3417 100644 --- a/plugin/safety/safety-gate.sh +++ b/plugin/safety/safety-gate.sh @@ -1,48 +1,48 @@ -#!/usr/bin/env bash -# safety-gate.sh — Blocks destructive commands in unattended sessions -# -# PreToolUse hook for Bash tool: checks command for dangerous patterns. -# Blocks: rm -rf, git push --force, DROP TABLE, deploys, secret access. -# -# Copyright 2026 Stackbilt LLC — Apache 2.0 - -INPUT=$(cat) -TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) - -if [[ "$TOOL" != "Bash" ]]; then - exit 0 -fi - -CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) - -# Destructive filesystem operations -if echo "$CMD" | grep -qiE '(rm\s+-rf|rm\s+-r\s+/|>\s*/dev/)'; then - echo "BLOCKED: Destructive filesystem operation not allowed in autonomous mode" >&2 - exit 2 -fi - -# Destructive git operations -if echo "$CMD" | grep -qiE '(git\s+reset\s+--hard|git\s+push\s+--force|git\s+push\s+-f|git\s+clean\s+-f)'; then - echo "BLOCKED: Destructive git operation not allowed in autonomous mode" >&2 - exit 2 -fi - -# Database destruction -if echo "$CMD" | grep -qiE '(DROP\s+TABLE|TRUNCATE\s+TABLE|DELETE\s+FROM\s+\w+\s*$)'; then - echo "BLOCKED: Destructive database operation not allowed in autonomous mode" >&2 - exit 2 -fi - -# Production deploys (require human approval) -if echo "$CMD" | grep -qiE '(wrangler\s+deploy|wrangler\s+publish|npm\s+run\s+deploy|kubectl\s+apply|terraform\s+apply)'; then - echo "BLOCKED: Production deploys require human approval. Commit your work and stop." >&2 - exit 2 -fi - -# Secret management -if echo "$CMD" | grep -qiE '(wrangler\s+secret|echo\s+.*API_KEY|echo\s+.*TOKEN|echo\s+.*SECRET)'; then - echo "BLOCKED: Secret management not allowed in autonomous mode" >&2 - exit 2 -fi - -exit 0 +#!/usr/bin/env bash +# safety-gate.sh — Blocks destructive commands in unattended sessions +# +# PreToolUse hook for Bash tool: checks command for dangerous patterns. +# Blocks: rm -rf, git push --force, DROP TABLE, deploys, secret access. +# +# Copyright 2026 Stackbilt LLC — Apache 2.0 + +INPUT=$(cat) +TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) + +if [[ "$TOOL" != "Bash" ]]; then + exit 0 +fi + +CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) + +# Destructive filesystem operations +if echo "$CMD" | grep -qiE '(rm\s+-rf|rm\s+-r\s+/|>\s*/dev/)'; then + echo "BLOCKED: Destructive filesystem operation not allowed in autonomous mode" >&2 + exit 2 +fi + +# Destructive git operations +if echo "$CMD" | grep -qiE '(git\s+reset\s+--hard|git\s+push\s+--force|git\s+push\s+-f|git\s+clean\s+-f)'; then + echo "BLOCKED: Destructive git operation not allowed in autonomous mode" >&2 + exit 2 +fi + +# Database destruction +if echo "$CMD" | grep -qiE '(DROP\s+TABLE|TRUNCATE\s+TABLE|DELETE\s+FROM\s+\w+\s*$)'; then + echo "BLOCKED: Destructive database operation not allowed in autonomous mode" >&2 + exit 2 +fi + +# Production deploys (require human approval) +if echo "$CMD" | grep -qiE '(wrangler\s+deploy|wrangler\s+publish|npm\s+run\s+deploy|kubectl\s+apply|terraform\s+apply)'; then + echo "BLOCKED: Production deploys require human approval. Commit your work and stop." >&2 + exit 2 +fi + +# Secret management +if echo "$CMD" | grep -qiE '(wrangler\s+secret|echo\s+.*API_KEY|echo\s+.*TOKEN|echo\s+.*SECRET)'; then + echo "BLOCKED: Secret management not allowed in autonomous mode" >&2 + exit 2 +fi + +exit 0 diff --git a/plugin/safety/syntax-check.sh b/plugin/safety/syntax-check.sh index f5c023d..3df35bd 100644 --- a/plugin/safety/syntax-check.sh +++ b/plugin/safety/syntax-check.sh @@ -1,42 +1,42 @@ -#!/usr/bin/env bash -# syntax-check.sh — PostToolUse hook for Edit/Write -# -# After editing TypeScript/JavaScript files, runs a quick syntax check -# so errors are caught immediately rather than 50 tool calls later. -# -# Copyright 2026 Stackbilt LLC — Apache 2.0 - -INPUT=$(cat) -TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) - -if [[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]]; then - exit 0 -fi - -FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null) - -# Only check TypeScript/JavaScript files -case "$FILE" in - *.ts|*.tsx|*.js|*.jsx) - # Find nearest tsconfig - DIR=$(dirname "$FILE") - TSCONFIG="" - while [[ "$DIR" != "/" && "$DIR" != "." ]]; do - if [[ -f "${DIR}/tsconfig.json" ]]; then - TSCONFIG="${DIR}/tsconfig.json" - break - fi - DIR=$(dirname "$DIR") - done - - if [[ -n "$TSCONFIG" ]]; then - ERRORS=$(cd "$(dirname "$TSCONFIG")" && npx tsc --noEmit --pretty false 2>&1 | grep -c "error TS" || true) - if [[ "$ERRORS" -gt 0 ]]; then - echo "WARNING: ${ERRORS} TypeScript error(s) detected after editing ${FILE}. Run typecheck to see details." >&2 - fi - fi - ;; -esac - -# Never block — advisory only -exit 0 +#!/usr/bin/env bash +# syntax-check.sh — PostToolUse hook for Edit/Write +# +# After editing TypeScript/JavaScript files, runs a quick syntax check +# so errors are caught immediately rather than 50 tool calls later. +# +# Copyright 2026 Stackbilt LLC — Apache 2.0 + +INPUT=$(cat) +TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) + +if [[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]]; then + exit 0 +fi + +FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null) + +# Only check TypeScript/JavaScript files +case "$FILE" in + *.ts|*.tsx|*.js|*.jsx) + # Find nearest tsconfig + DIR=$(dirname "$FILE") + TSCONFIG="" + while [[ "$DIR" != "/" && "$DIR" != "." ]]; do + if [[ -f "${DIR}/tsconfig.json" ]]; then + TSCONFIG="${DIR}/tsconfig.json" + break + fi + DIR=$(dirname "$DIR") + done + + if [[ -n "$TSCONFIG" ]]; then + ERRORS=$(cd "$(dirname "$TSCONFIG")" && npx tsc --noEmit --pretty false 2>&1 | grep -c "error TS" || true) + if [[ "$ERRORS" -gt 0 ]]; then + echo "WARNING: ${ERRORS} TypeScript error(s) detected after editing ${FILE}. Run typecheck to see details." >&2 + fi + fi + ;; +esac + +# Never block — advisory only +exit 0