#!/usr/bin/env bash # Stable entrypoint for the seo-data engine. JSON on stdout; exit 0 on ok/degrade, # exit 2 on bad usage. Never prints secrets. set -uo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" ENV_FILE="${SEO_DATA_ENV_FILE:-${HOME}/.claude/.env}" # canonical; tests override to /dev/null STORE="${SEO_DATA_STORE:-${HOME}/.claude/seo-data/tokens.json}" VENV_PY="${HOME}/.claude/.venv-seo-data/bin/python3" # Library stderr must never leak a secret into agent context — suppress it # globally unless explicitly debugging (SEO_DATA_DEBUG=1 restores it). [ -n "${SEO_DATA_DEBUG:-}" ] || exec 2>/dev/null # Load secrets quietly (sourced, never echoed). if [ -f "$ENV_FILE" ]; then set -a; # shellcheck source=/dev/null . "$ENV_FILE"; set +a fi # Prefer the isolated venv (has google-auth); fall back to system python3 for # stdlib-only paths (accounts / mock / degrade). PY="python3"; [ -x "$VENV_PY" ] && PY="$VENV_PY" # Whole-string label guard (shell-safe ASCII). POSIX `case` in a C-locale # subshell — newline-proof and locale-independent, unlike a per-line grep. _label_safe() ( LC_ALL=C; case "$1" in ''|[!A-Za-z0-9]*|*[!A-Za-z0-9._-]*) exit 1;; esac ) cmd="${1:-}"; shift || true case "$cmd" in accounts) exec "$PY" "$HERE/tokenstore.py" list --file "$STORE" ;; crux|queries|inspect|cannibal) exec "$PY" "$HERE/google_seo.py" "$cmd" --store "$STORE" "$@" ;; # No auth, no Google: stdlib-only, runs even without the venv. sitemap) exec "$PY" "$HERE/sitemap.py" --store "$STORE" "$@" ;; forget) # forget --label