#!/usr/bin/env bash # # tea-guard — PreToolUse hook for Bash commands. # # Enforces, deterministically, the one rule the prose in /tea:use cannot: # every `tea` invocation that touches Gitea MUST carry --login "$GITEA_LOGIN", # and $GITEA_LOGIN must be set. Without this, `tea` silently falls back to the # machine's default login (often the user's personal account) and writes under # the wrong identity. # # Exit codes: 0 = allow, 2 = block (stderr is fed back to Claude as the reason). # set -uo pipefail input="$(cat)" # Extract tool_input.command from the hook payload (jq if present, else python3). if command -v jq >/dev/null 2>&1; then cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // ""' 2>/dev/null || true)" else cmd="$(printf '%s' "$input" | /usr/bin/python3 -c 'import sys,json; print(json.load(sys.stdin).get("tool_input",{}).get("command","") or "")' 2>/dev/null || true)" fi # Not a `tea` command → not our concern. if ! printf '%s' "$cmd" | grep -Eq '(^|[;&|(]|[[:space:]])tea([[:space:]]|$)'; then exit 0 fi # Whitelist: login enumeration + meta. These do not act under any identity and # are needed by /tea:login itself (which runs while $GITEA_LOGIN may be unset). if printf '%s' "$cmd" | grep -Eq 'tea[[:space:]]+(logins[[:space:]]+(list|ls)|--version|-v|--help|help)([[:space:]]|$)'; then exit 0 fi # Require an explicit --login / -l on the invocation. if ! printf '%s' "$cmd" | grep -Eq '(--login|[[:space:]]-l)([[:space:]=])'; then echo "tea-guard: BLOCKED — every 'tea' command must include --login \"\$GITEA_LOGIN\" (or -l). Run /tea:login to pin the project login, then retry. Only 'tea logins list' and 'tea --version/--help' are exempt." >&2 exit 2 fi # Require $GITEA_LOGIN to be set in the environment. if [ -z "${GITEA_LOGIN:-}" ]; then echo "tea-guard: BLOCKED — \$GITEA_LOGIN is empty/unset, so --login \"\$GITEA_LOGIN\" would expand to nothing and tea would fall back to the default login. Run /tea:login to pin a login (writes .claude/settings.local.json), then restart the session so it is exported." >&2 exit 2 fi exit 0