Quality Patterns Library
When to Use This Skill
- •Implementing security validation hooks
- •Setting up auto-formatting workflows
- •Integrating with CI/CD pipelines
- •Adding audit logging
- •Building notification systems
- •Creating guardrails for safe automation
Security Hook Patterns
Block Dangerous Commands
settings.json:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/security-check.sh"
}
]
}
]
}
}
security-check.sh:
bash
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
# Dangerous patterns to block
BLOCKED_PATTERNS=(
'rm -rf /'
'rm -rf ~'
'rm -rf \*'
'sudo rm'
'chmod 777'
'> /dev/sd'
'mkfs\.'
'dd if='
':(){:|:&};:'
'curl.*| bash'
'wget.*| sh'
'eval.*\$'
)
for pattern in "${BLOCKED_PATTERNS[@]}"; do
if echo "$COMMAND" | grep -qE "$pattern"; then
echo "BLOCKED: Dangerous command pattern: $pattern" >&2
exit 2
fi
done
# Block credential file operations
if echo "$COMMAND" | grep -qE '\.(env|pem|key|credentials|secrets)'; then
echo "BLOCKED: Potential credential file access" >&2
exit 2
fi
# Block production database commands
if echo "$COMMAND" | grep -qiE 'production|prod' && \
echo "$COMMAND" | grep -qiE 'DROP|DELETE|TRUNCATE'; then
echo "BLOCKED: Destructive production database operation" >&2
exit 2
fi
exit 0
Protect Sensitive Files
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
protect-files.sh:
bash
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
PROTECTED=(
'.env'
'.env.local'
'.env.production'
'credentials.json'
'secrets.yaml'
'.aws/credentials'
'.ssh/'
'id_rsa'
'*.pem'
'*.key'
)
for pattern in "${PROTECTED[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "BLOCKED: Protected file: $FILE_PATH" >&2
exit 2
fi
done
exit 0
Auto-Formatting Patterns
Multi-Language Formatter
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/auto-format.sh"
}
]
}
]
}
}
auto-format.sh:
bash
#!/bin/bash INPUT=$(cat) FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') # JavaScript/TypeScript if [[ "$FILE_PATH" =~ \.(js|jsx|ts|tsx|json)$ ]]; then prettier --write "$FILE_PATH" 2>/dev/null || true eslint "$FILE_PATH" --fix 2>/dev/null || true fi # Python if [[ "$FILE_PATH" =~ \.py$ ]]; then black "$FILE_PATH" 2>/dev/null || true isort "$FILE_PATH" 2>/dev/null || true fi # Rust if [[ "$FILE_PATH" =~ \.rs$ ]]; then rustfmt "$FILE_PATH" 2>/dev/null || true fi # Go if [[ "$FILE_PATH" =~ \.go$ ]]; then gofmt -w "$FILE_PATH" 2>/dev/null || true fi # YAML if [[ "$FILE_PATH" =~ \.(yaml|yml)$ ]]; then yamlfmt "$FILE_PATH" 2>/dev/null || true fi exit 0
Lint After Format
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true",
"timeout": 10
},
{
"type": "command",
"command": "eslint \"$CLAUDE_FILE_PATHS\" --fix 2>/dev/null || true",
"timeout": 15
},
{
"type": "command",
"command": "npm run typecheck 2>&1 | head -20 || true",
"async": true,
"timeout": 30
}
]
}
]
}
}
CI/CD Integration Patterns
GitHub Actions Workflow
.github/workflows/claude-code.yml:
yaml
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
claude:
if: contains(github.event.comment.body, '@claude')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
Test on File Change
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/run-related-tests.sh",
"async": true,
"timeout": 120
}
]
}
]
}
}
run-related-tests.sh:
bash
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# Skip non-source files
if [[ ! "$FILE_PATH" =~ \.(ts|tsx|js|jsx)$ ]]; then
exit 0
fi
# Find and run related test file
TEST_FILE="${FILE_PATH%.ts}.test.ts"
TEST_FILE="${TEST_FILE%.tsx}.test.tsx"
TEST_FILE="${TEST_FILE%.js}.test.js"
if [ -f "$TEST_FILE" ]; then
npm test -- --testPathPattern="$(basename "$TEST_FILE")" 2>&1 | tail -30
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "{\"systemMessage\": \"Tests failed after editing $FILE_PATH\"}"
else
echo "{\"systemMessage\": \"Tests passed for $FILE_PATH\"}"
fi
fi
exit 0
Pre-Commit Validation
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git commit:*)",
"hooks": [
{
"type": "command",
"command": "npm run lint && npm test"
}
]
}
]
}
}
Audit Logging Patterns
Comprehensive Audit Log
json
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit-session.sh start"
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit-session.sh end"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit|Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit-tool.sh"
}
]
}
]
}
}
audit-tool.sh:
bash
#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
SESSION=$(echo "$INPUT" | jq -r '.session_id')
LOG_DIR="$CLAUDE_PROJECT_DIR/.claude/logs"
mkdir -p "$LOG_DIR"
LOG_ENTRY=$(jq -n \
--arg ts "$TIMESTAMP" \
--arg tool "$TOOL" \
--arg session "$SESSION" \
--argjson input "$(echo "$INPUT" | jq '.tool_input')" \
'{timestamp: $ts, tool: $tool, session: $session, input: $input}')
echo "$LOG_ENTRY" >> "$LOG_DIR/audit.jsonl"
exit 0
JSON Lines Format
Audit logs use JSONL format for easy querying:
bash
# Find all Bash commands in last session jq -s 'map(select(.tool == "Bash"))' .claude/logs/audit.jsonl # Find file modifications jq -s 'map(select(.tool == "Write" or .tool == "Edit"))' .claude/logs/audit.jsonl
Notification Patterns
Slack Notification
json
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/notify-slack.sh",
"async": true
}
]
}
]
}
}
notify-slack.sh:
bash
#!/bin/bash
WEBHOOK="${SLACK_WEBHOOK_URL:-}"
[ -z "$WEBHOOK" ] && exit 0
INPUT=$(cat)
MESSAGE=$(echo "$INPUT" | jq -r '.message // "Claude Code task completed"')
curl -X POST "$WEBHOOK" \
-H 'Content-Type: application/json' \
-d "{\"text\": \"✅ $MESSAGE\"}" \
2>/dev/null
exit 0
Desktop Notification
json
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Task completed\" with title \"Claude Code\"' 2>/dev/null || true",
"async": true
}
]
}
]
}
}
Guardrail Patterns
Confirm Before Deploy
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(npm run deploy:*)|Bash(./deploy:*)",
"hooks": [
{
"type": "prompt",
"prompt": "A deploy command is about to run. Verify this is intentional. If deploying to production, return JSON with decision:'deny'. Context: $ARGUMENTS",
"timeout": 15
}
]
}
]
}
}
Rate Limiting
rate-limit.sh:
bash
#!/bin/bash TOOL=$1 LIMIT_FILE="/tmp/claude-rate-limit-$TOOL" LIMIT=10 # max calls per minute # Get current count COUNT=$(cat "$LIMIT_FILE" 2>/dev/null || echo "0 0") LAST_RESET=$(echo "$COUNT" | cut -d' ' -f1) CALL_COUNT=$(echo "$COUNT" | cut -d' ' -f2) NOW=$(date +%s) # Reset if minute passed if [ $((NOW - LAST_RESET)) -gt 60 ]; then echo "$NOW 1" > "$LIMIT_FILE" exit 0 fi # Check limit if [ "$CALL_COUNT" -ge "$LIMIT" ]; then echo "BLOCKED: Rate limit exceeded for $TOOL" >&2 exit 2 fi # Increment echo "$LAST_RESET $((CALL_COUNT + 1))" > "$LIMIT_FILE" exit 0
Anti-Patterns to Avoid
❌ Blocking hooks that timeout
Long-running hooks block Claude. Use async: true for slow operations.
❌ Hooks that fail on missing tools
Always check if tools exist: command -v prettier &>/dev/null && prettier ...
❌ Verbose logging
Don't log every operation. Log significant actions only.
❌ Security through obscurity
Don't rely on hiding commands. Use explicit deny lists.
❌ Hard-coded paths
Use $CLAUDE_PROJECT_DIR for project paths.