feat: initial Claude Code configuration scaffold
Comprehensive Claude Code guidance system with: - 5 agents: tdd-guardian, code-reviewer, security-scanner, refactor-scan, dependency-audit - 18 skills covering languages (Python, TypeScript, Rust, Go, Java, C#), infrastructure (AWS, Azure, GCP, Terraform, Ansible, Docker/K8s, Database, CI/CD), testing (TDD, UI, Browser), and patterns (Monorepo, API Design, Observability) - 3 hooks: secret detection, auto-formatting, TDD git pre-commit - Strict TDD enforcement with 80%+ coverage requirements - Multi-model strategy: Opus for planning, Sonnet for execution (opusplan) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
54
.claude/hooks/auto-format.sh
Normal file
54
.claude/hooks/auto-format.sh
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# Auto-format files after writing
|
||||
# Runs appropriate formatter based on file extension
|
||||
|
||||
set -e
|
||||
|
||||
# Read the file path from stdin
|
||||
INPUT=$(cat)
|
||||
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // .filePath // empty')
|
||||
|
||||
if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get file extension
|
||||
EXT="${FILE_PATH##*.}"
|
||||
|
||||
case "$EXT" in
|
||||
py)
|
||||
if command -v ruff &> /dev/null; then
|
||||
ruff format "$FILE_PATH" 2>/dev/null || true
|
||||
ruff check --fix "$FILE_PATH" 2>/dev/null || true
|
||||
fi
|
||||
;;
|
||||
ts|tsx|js|jsx)
|
||||
# Try to find and use project's ESLint config
|
||||
DIR=$(dirname "$FILE_PATH")
|
||||
while [ "$DIR" != "/" ]; do
|
||||
if [ -f "$DIR/package.json" ]; then
|
||||
cd "$DIR"
|
||||
if [ -f "node_modules/.bin/eslint" ]; then
|
||||
./node_modules/.bin/eslint --fix "$FILE_PATH" 2>/dev/null || true
|
||||
fi
|
||||
break
|
||||
fi
|
||||
DIR=$(dirname "$DIR")
|
||||
done
|
||||
;;
|
||||
rs)
|
||||
if command -v rustfmt &> /dev/null; then
|
||||
rustfmt "$FILE_PATH" 2>/dev/null || true
|
||||
fi
|
||||
;;
|
||||
tf)
|
||||
if command -v terraform &> /dev/null; then
|
||||
terraform fmt "$FILE_PATH" 2>/dev/null || true
|
||||
fi
|
||||
;;
|
||||
yaml|yml)
|
||||
# Skip YAML formatting to preserve structure
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
51
.claude/hooks/check-secrets.sh
Normal file
51
.claude/hooks/check-secrets.sh
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
# Check for secrets in files before writing
|
||||
# Exit code 2 blocks the operation in Claude Code
|
||||
|
||||
set -e
|
||||
|
||||
# Read the file path from stdin (Claude passes tool_input as JSON)
|
||||
INPUT=$(cat)
|
||||
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // .filePath // empty')
|
||||
|
||||
if [ -z "$FILE_PATH" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Skip non-code files
|
||||
case "$FILE_PATH" in
|
||||
*.md|*.txt|*.json|*.yaml|*.yml|*.toml|*.lock|*.svg|*.png|*.jpg|*.gif)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Patterns that indicate secrets
|
||||
SECRET_PATTERNS=(
|
||||
'password\s*=\s*["\x27][^"\x27]+'
|
||||
'api[_-]?key\s*=\s*["\x27][^"\x27]+'
|
||||
'secret[_-]?key\s*=\s*["\x27][^"\x27]+'
|
||||
'aws[_-]?access[_-]?key[_-]?id\s*=\s*["\x27][A-Z0-9]+'
|
||||
'aws[_-]?secret[_-]?access[_-]?key\s*=\s*["\x27][^"\x27]+'
|
||||
'private[_-]?key\s*=\s*["\x27][^"\x27]+'
|
||||
'database[_-]?url\s*=\s*["\x27]postgres(ql)?://[^"\x27]+'
|
||||
'mongodb(\+srv)?://[^"\x27\s]+'
|
||||
'redis://[^"\x27\s]+'
|
||||
'AKIA[0-9A-Z]{16}'
|
||||
'ghp_[a-zA-Z0-9]{36}'
|
||||
'sk-[a-zA-Z0-9]{48}'
|
||||
'xox[baprs]-[0-9a-zA-Z-]+'
|
||||
)
|
||||
|
||||
# Check if file exists and scan for secrets
|
||||
if [ -f "$FILE_PATH" ]; then
|
||||
for pattern in "${SECRET_PATTERNS[@]}"; do
|
||||
if grep -qiE "$pattern" "$FILE_PATH" 2>/dev/null; then
|
||||
echo "BLOCKED: Potential secret detected in $FILE_PATH"
|
||||
echo "Pattern matched: $pattern"
|
||||
echo "Please use environment variables or secrets manager instead."
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
exit 0
|
||||
14
.claude/hooks/example-git-hooks/pre-commit
Normal file
14
.claude/hooks/example-git-hooks/pre-commit
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
# Git pre-commit hook for TDD enforcement
|
||||
#
|
||||
# Installation:
|
||||
# cp ~/.claude/hooks/example-git-hooks/pre-commit .git/hooks/pre-commit
|
||||
# chmod +x .git/hooks/pre-commit
|
||||
#
|
||||
# Or create a symlink:
|
||||
# ln -sf ~/.claude/hooks/example-git-hooks/pre-commit .git/hooks/pre-commit
|
||||
|
||||
# Source the TDD enforcement script
|
||||
~/.claude/hooks/pre-commit-tdd.sh
|
||||
|
||||
exit $?
|
||||
57
.claude/hooks/pre-commit-tdd.sh
Normal file
57
.claude/hooks/pre-commit-tdd.sh
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# Pre-commit hook to enforce TDD compliance
|
||||
# Verifies that test files are modified alongside production code
|
||||
|
||||
set -e
|
||||
|
||||
# Get staged files
|
||||
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
|
||||
|
||||
# Separate test and production files
|
||||
TEST_FILES=""
|
||||
PROD_FILES=""
|
||||
|
||||
for file in $STAGED_FILES; do
|
||||
case "$file" in
|
||||
*test*.py|*_test.py|*tests/*.py)
|
||||
TEST_FILES="$TEST_FILES $file"
|
||||
;;
|
||||
*.test.ts|*.test.tsx|*.spec.ts|*.spec.tsx|*/__tests__/*)
|
||||
TEST_FILES="$TEST_FILES $file"
|
||||
;;
|
||||
*_test.rs|*/tests/*.rs)
|
||||
TEST_FILES="$TEST_FILES $file"
|
||||
;;
|
||||
*.py|*.ts|*.tsx|*.js|*.jsx|*.rs)
|
||||
# Skip __init__.py, conftest.py, config files
|
||||
case "$file" in
|
||||
*__init__.py|*conftest.py|*config*.py|*.config.ts|*.config.js)
|
||||
;;
|
||||
*)
|
||||
PROD_FILES="$PROD_FILES $file"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if we have production files without test files
|
||||
if [ -n "$PROD_FILES" ] && [ -z "$TEST_FILES" ]; then
|
||||
echo "TDD VIOLATION: Production code changed without test changes"
|
||||
echo ""
|
||||
echo "Production files modified:"
|
||||
for file in $PROD_FILES; do
|
||||
echo " - $file"
|
||||
done
|
||||
echo ""
|
||||
echo "Please ensure you're following TDD:"
|
||||
echo " 1. Write a failing test first (RED)"
|
||||
echo " 2. Write minimum code to pass (GREEN)"
|
||||
echo " 3. Refactor if needed (REFACTOR)"
|
||||
echo ""
|
||||
echo "If this is a legitimate exception (config, types, etc.), use:"
|
||||
echo " git commit --no-verify"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user