Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,16 @@ Autonomous task queue for Claude Code with safety hooks, branch isolation, and P
- All paths relative to script directory
- Tasks use JSON format with id, title, repo, prompt, status fields
- Completion signal: TASK_COMPLETE or TASK_BLOCKED

## OSS Policy

This is a **public infrastructure package** governed by the Stackbilt OSS Infrastructure Package Update Policy.

Rules:
1. **Additive only** — never remove or rename public API without a major version bump
2. **No product logic** — framework patterns and generic utilities only. If a competitor could reconstruct Stackbilt product architecture from this code, it doesn't belong here.
3. **Strict semver** — patch for fixes, minor for new features, major for breaking changes
4. **Tests travel with code** — every public export must have test coverage
5. **Validate at boundaries** — all external API responses validated before returning to consumers

Full policy: `stackbilt_llc/policies/oss-infrastructure-update-policy.md`
34 changes: 17 additions & 17 deletions hooks/block-interactive.sh
Original file line number Diff line number Diff line change
@@ -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
96 changes: 48 additions & 48 deletions hooks/safety-gate.sh
Original file line number Diff line number Diff line change
@@ -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
84 changes: 42 additions & 42 deletions hooks/syntax-check.sh
Original file line number Diff line number Diff line change
@@ -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
34 changes: 17 additions & 17 deletions plugin/safety/block-interactive.sh
Original file line number Diff line number Diff line change
@@ -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
96 changes: 48 additions & 48 deletions plugin/safety/safety-gate.sh
Original file line number Diff line number Diff line change
@@ -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
Loading