init: scaffold Seth-Workflow-April-2026
User-agnostic, shareable AI-assisted development workflow distilled from 26+ real projects. Includes 9 composable rules, 4 project templates, pre-push secret scanning hook, 3 methodology guides, and customization docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
# Hook: block git pushes if tracked files contain secrets from a secrets env file
|
||||
#
|
||||
# SETUP:
|
||||
# 1. Create ~/.config/secrets.env with your secret values (one per line: KEY=value)
|
||||
# 2. Add this hook to Claude Code settings.json:
|
||||
# {
|
||||
# "hooks": {
|
||||
# "PreToolUse": [{
|
||||
# "matcher": "Bash",
|
||||
# "hooks": [{
|
||||
# "type": "command",
|
||||
# "command": "/path/to/check-secrets-before-push.sh",
|
||||
# "timeout": 30,
|
||||
# "statusMessage": "Checking for secrets before push..."
|
||||
# }]
|
||||
# }]
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# HOW IT WORKS:
|
||||
# - Reads the Bash tool input from stdin (JSON with tool_input.command)
|
||||
# - Only activates on git push or similar push commands
|
||||
# - Loads secret values from ~/.config/secrets.env
|
||||
# - Scans tracked files for any matching secret values
|
||||
# - Outputs a JSON block decision if secrets are found
|
||||
#
|
||||
# SECRETS FILE FORMAT (~/.config/secrets.env):
|
||||
# API_KEY=sk-abc123...
|
||||
# DB_PASSWORD=hunter2
|
||||
# # Comments are skipped
|
||||
# SHORT=ab # Values under 6 chars are skipped (too many false positives)
|
||||
|
||||
INPUT=$(cat)
|
||||
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)
|
||||
|
||||
# Only care about push commands
|
||||
echo "$CMD" | grep -qE '(git\s+push)' || exit 0
|
||||
|
||||
# Check if we're in a git repo
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || exit 0
|
||||
|
||||
# Load secrets to check for
|
||||
SECRETS_FILE="$HOME/.config/secrets.env"
|
||||
[[ -f "$SECRETS_FILE" ]] || exit 0
|
||||
|
||||
# Extract secret values (skip comments, empty lines, short values)
|
||||
PATTERNS=()
|
||||
while IFS='=' read -r key value; do
|
||||
[[ -z "$key" || "$key" =~ ^# ]] && continue
|
||||
value="${value#\"}"
|
||||
value="${value%\"}"
|
||||
value="${value#\'}"
|
||||
value="${value%\'}"
|
||||
[[ ${#value} -lt 6 ]] && continue
|
||||
PATTERNS+=("$value")
|
||||
done < "$SECRETS_FILE"
|
||||
|
||||
[[ ${#PATTERNS[@]} -eq 0 ]] && exit 0
|
||||
|
||||
# Scan tracked files for secret values
|
||||
FOUND=()
|
||||
for secret in "${PATTERNS[@]}"; do
|
||||
file=$(git -C "$REPO_ROOT" grep -rlF "$secret" -- . 2>/dev/null | head -1 || true)
|
||||
if [[ -n "$file" ]]; then
|
||||
key_name=$(grep -F "$secret" "$SECRETS_FILE" 2>/dev/null | head -1 | cut -d= -f1)
|
||||
FOUND+=("$key_name in $file")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#FOUND[@]} -gt 0 ]]; then
|
||||
printf '{"decision":"block","reason":"BLOCKED: Secrets found in tracked files:\\n'
|
||||
for f in "${FOUND[@]}"; do
|
||||
printf ' - %s\\n' "$f"
|
||||
done
|
||||
printf '\\nReplace with env var references before pushing."}\n'
|
||||
fi
|
||||
Reference in New Issue
Block a user